Name | Type | is_array | initial_value |
//TESH.scrollpos=0
//TESH.alwaysfold=0
library DemonSlash requires RegisterPlayerUnitEvent, T32
// Demon Slash by The_Witcher
// The hero slashes through numerous enemys dealing aoe damage.
// When the hero crashes into an obstacle he stops.
//
// well not much to say look through/edit the setup part for your wishes
//
// The SETUP part
globals
// the rawcode of the ghost/demon appearing behind the caster when channeling
private constant integer DEMON_DUMMY_ID = 'h000'
// the rawcode and the order string of the Demon Slash ability
private constant integer ABILITY_ID = 'A000'
private constant string ORDER_STRING = "absorb"
// the size the dummy will be when fully grown (2 = 200%)
private constant real MAX_SIZE = 2
//the effect created when a unit is hit
private constant string BLOOD_EFFECT = "Objects\\Spawnmodels\\Human\\HumanBlood\\BloodElfSpellThiefBlood.mdl"
//the effect created on the weapon of the caster
private constant string WEAPON_EFFECT = "Abilities\\Weapons\\ZigguratMissile\\ZigguratMissile.mdl"
//the effect created on the body of the caster
private constant string BODY_EFFECT = "Abilities\\Spells\\Undead\\DeathCoil\\DeathCoilMissile.mdl"
//the effect created when the dummy disappears cause of abort
private constant string ABORT_EFFECT = "Abilities\\Spells\\Undead\\CarrionSwarm\\CarrionSwarmDamage.mdl"
endglobals
private function GetDamage takes integer level returns real
return 120.00 + 50 * (level - 1) //120 on level 1, 170 level 2, 220 level 3, ...
endfunction
private function GetAOE takes integer level returns real
return 100.00 + 20 * level //120 on level 1, 140 level 2, 160 level 3, ...
endfunction
private function GetSlashDistance takes integer level returns real
return 500.0 + 100 * level //600 on level 1, 700 level 2, 800 level 3, ...
endfunction
private function GetSlashSpeed takes integer level returns real
return 700.0 + 100 * level //800 on level 1, 900 level 2, 1000 level 3, ...
endfunction
private function GetChannelTime takes integer level returns real
return 4.00 - level / 2 //3, 5 on level 1, 3 level 2, 2, 5 level 3, ...
endfunction
//==============================================================================
//========================= SETUP END ======================================
//==============================================================================
private struct spell
static group g
static item ite
static unit Temp
static boolexpr BoolExpr
unit u
unit dummy
real v
real d
real vx
real vy
real phase
real temp
integer level
effect bodyFX
effect weaponFX
group damaged
method IsCoordPathable takes real x, real y returns boolean
local real xx
local real yy
call SetItemVisible(.ite, true)
call SetItemPosition(.ite, x, y)
set xx = GetItemX( .ite ) - x
set yy = GetItemY( .ite ) - y
call SetItemVisible(.ite, false)
if xx < 1 and xx > -1 and yy < 1 and yy > -1 then
return true
endif
return false
endmethod
method periodic takes nothing returns nothing
local unit k = null
if .phase == 0 then // phase 1
if GetUnitCurrentOrder(.u) == OrderId(ORDER_STRING) then
call SetUnitVertexColor(.dummy, 255, 255, 255, R2I(.temp / 100 * 255))
call SetUnitScalePercent(.dummy, .temp * MAX_SIZE, .temp * MAX_SIZE, .temp * MAX_SIZE)
set .temp = .temp + 100 / GetChannelTime(.level) * T32_PERIOD
if .temp >= 100 then
set .phase = 1
set .temp = 0
set .weaponFX = AddSpecialEffectTarget(WEAPON_EFFECT, .u, "weapon")
set .bodyFX = AddSpecialEffectTarget(BODY_EFFECT, .u, "chest")
call IssueImmediateOrder(.u,"stop")
call PauseUnit(.u, true)
call SetUnitInvulnerable(.u, true)
call SetUnitAnimation(.u, "attack")
call SetUnitAnimation(.dummy, "attack")
call QueueUnitAnimation(.dummy,"stand")
endif
else
call DestroyEffect(AddSpecialEffect(ABORT_EFFECT, GetUnitX(.dummy), GetUnitY(.dummy)))
call RemoveUnit(.dummy)
call DestroyGroup(.damaged)
call .stopPeriodic()
call .destroy()
endif
else // phase 2
call SetUnitVertexColor(.dummy, 255, 255, 255, R2I((100 - .temp) / 100 * 255))
set .temp = .temp + 400 / GetChannelTime(.level) * T32_PERIOD
if .d > 0 and IsCoordPathable(GetUnitX(.u) + .vx, GetUnitY(.u) + .vy) then
call SetUnitX(.u, GetUnitX(.u) + .vx )
call SetUnitY(.u, GetUnitY(.u) + .vy )
set .d = .d - .v
set .Temp = .u
call GroupEnumUnitsInRange(.g, GetUnitX(.u), GetUnitY(.u), GetAOE(.level), .BoolExpr)
loop
set k = FirstOfGroup(.g)
exitwhen k == null
call GroupRemoveUnit(.g, k)
if not IsUnitInGroup(k, .damaged) then
call GroupAddUnit(.damaged, k)
call UnitDamageTarget( .u, k, GetDamage(.level), true, false, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_NORMAL, WEAPON_TYPE_WHOKNOWS )
call DestroyEffect(AddSpecialEffectTarget(BLOOD_EFFECT, k, "chest"))
endif
endloop
else
call PauseUnit(.u, false)
call SetUnitAnimation(.u, "stand")
call SetUnitInvulnerable(.u, false)
call DestroyEffect(.weaponFX)
call DestroyEffect(.bodyFX)
call RemoveUnit(.dummy)
call DestroyGroup(.damaged)
call .stopPeriodic()
call .destroy()
endif
endif
endmethod
implement T32x
private static method create takes unit caster, real tx, real ty returns spell
local spell this = spell.allocate()
local real x = GetUnitX(caster)
local real y = GetUnitY(caster)
local real r = Atan2(ty - y, tx - x)
set .u = caster
set .level = GetUnitAbilityLevel(.u, ABILITY_ID)
set .v = GetSlashSpeed(.level) * T32_PERIOD
set .vx = .v * Cos(r)
set .vy = .v * Sin(r)
set x = x + 200 * Cos(r - bj_PI)
set y = y + 200 * Sin(r - bj_PI)
set .dummy = CreateUnit(GetOwningPlayer(caster), DEMON_DUMMY_ID, x, y, r * bj_RADTODEG)
call PauseUnit(.dummy, true)
call SetUnitVertexColor(.dummy, 255, 255, 255, 0)
set .phase = 0
set .temp = 0
set .d = GetSlashDistance(.level)
set .damaged = CreateGroup()
call .startPeriodic()
return this
endmethod
private static method cast takes nothing returns nothing
if GetSpellAbilityId() == ABILITY_ID then
call spell.create(GetTriggerUnit(), GetSpellTargetX(), GetSpellTargetY())
endif
endmethod
private static method AllyFilter takes nothing returns boolean
return ( IsUnitAlly(GetFilterUnit(), GetOwningPlayer(.Temp)) == false ) and not (IsUnitType(GetFilterUnit(), UNIT_TYPE_DEAD) or GetUnitTypeId(GetFilterUnit()) == 0 )
endmethod
private static method onInit takes nothing returns nothing
call RegisterPlayerUnitEvent( EVENT_PLAYER_UNIT_SPELL_CAST, function spell.cast )
set .BoolExpr = Condition(function spell.AllyFilter)
set .ite = CreateItem( 'wolg', 0, 0 )
call SetItemVisible(.ite, false)
set .g = CreateGroup()
endmethod
endstruct
endlibrary
//Code indented using The_Witcher's Script Language Aligner
//Download the newest version and report bugs at www.hiveworkshop.com
//TESH.scrollpos=2
//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
/**************************************************************
*
* RegisterPlayerUnitEvent
* v5.0.0.0
* By Magtheridon96
*
* I would like to give a special thanks to Bribe, azlier
* and BBQ for improving this library. For modularity, it only
* supports player unit events.
*
* Functions passed to RegisterPlayerUnitEvent must
* return false. They can return nothing as well. (Which is a Pro)
*
* Warning:
* --------
*
* - Don't use TriggerSleepAction inside registered code.
*
* API:
* ----
*
* - function RegisterPlayerUnitEvent
* takes
* playerunitevent whichEvent : The event you would like to register
* code whichFunction : The code you would like to register
* returns
* nothing
*
* - Registers code that will execute when an event fires.
*
* - function RegisterPlayerUnitEventForPlayer
* takes
* playerunitevent whichEvent : The event you would like to register
* code whichFunction : The code you would like to register
* player whichPlayer : The player you would like to register the event for
* returns
* nothing
*
* - Registers code that will execute when an event fires for a certain player.
*
**************************************************************/
library RegisterPlayerUnitEvent // Special Thanks to Bribe and azlier
globals
private trigger array t
endglobals
function RegisterPlayerUnitEvent takes playerunitevent p, code c returns nothing
local integer i = GetHandleId(p)
local integer k = 15
if t[i] == null then
set t[i] = CreateTrigger()
loop
call TriggerRegisterPlayerUnitEvent(t[i], Player(k), p, null)
exitwhen k == 0
set k = k - 1
endloop
endif
call TriggerAddCondition(t[i], Filter(c))
endfunction
function RegisterPlayerUnitEventForPlayer takes playerunitevent p, code c, player pl returns nothing
local integer i = 260 + 16 * GetHandleId(p) + GetPlayerId(pl)
if t[i] == null then
set t[i] = CreateTrigger()
call TriggerRegisterPlayerUnitEvent(t[i], pl, p, null)
endif
call TriggerAddCondition(t[i], Filter(c))
endfunction
endlibrary
//TESH.scrollpos=0
//TESH.alwaysfold=0
scope AutoRevive initializer Init
globals
private constant real DELAY = 8.0
endglobals
private function Revive takes nothing returns nothing
local unit u = GetTriggerUnit()
local real x = GetUnitX(u)
local real y = GetUnitY(u)
call TriggerSleepAction( DELAY )
call CreateUnit(GetOwningPlayer(u), GetUnitTypeId(u), x, y, 0)
endfunction
private function Init takes nothing returns nothing
call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_DEATH, function Revive)
endfunction
endscope
//Code indented using The_Witcher's Script Language Aligner
//Download the newest version and report bugs at www.hiveworkshop.com