Name | Type | is_array | initial_value |
//TESH.scrollpos=0
//TESH.alwaysfold=0
/*
Super Frost Joke by Adiktuz
Description:
The caster cracks a joke which can freeze enemy units around him
Configurables:
-The jokes
-The chances of freezing for each joke
-The duration of the freeze
-The targets of the freeze
-The damage of the freeze
-The AoE of the freeze
How to import:
-Copy and paste this code into your trigger editor
-Copy the two abilities and the buff
-Create a dummy caster if you don't have one or copy the one on this map
-Change the rawcodes to fit the new rawcodes on your map
-Edit the configurables to your liking
-Add your jokes using [function RegisterJokes takes string joke, real chance]
*examples given on InitJokes trigger
IMPORTANT: On the gameplay constants, set the UNIT MIN MOVESPEED to 0.00
Credits:
Jesus4Lyf for Timer32
*/
library SuperFrostJoke initializer Init requires T32
globals
//The rawcode of the Frost joke spell
private constant integer FJ_SPELL_ID = 'A000'
//The rawcode of the frost joke buff placer (the soulburn-based ability)
private constant integer FJ_BUFFPLACER_ID = 'A001'
//The rawcode of the frost joke buff which the buffplacer uses
private constant integer FJ_BUFF_ID = 'B000'
//The rawcode of the dummy unit
private constant integer DUMMY_ID = 'h000'
//Checks if the FJ deals damage, if yes be sure to set the damage amount at the function below the globals
private constant boolean DEALS_DAMAGE = false
//Checks if the FJ deals damage after the duration, if yes be sure to set the damage amount at the function below the globals
private constant boolean DEALS_END_DAMAGE = true
/*
Checks if the duration of the buff will stack if a unit gets hit by SFJ while still
being affected by a previous one, if false, the new cast will overwrite the older one
*/
private constant boolean STACK_TIME = false
//The attack type of the primary damage
private constant attacktype ATPD = ATTACK_TYPE_NORMAL
//The damage type of the primary damage
private constant damagetype DTPD = DAMAGE_TYPE_NORMAL
//The attack type of the secondary damage
private constant attacktype ATSD = ATTACK_TYPE_NORMAL
//The damage type of the secondary damage
private constant damagetype DTSD = DAMAGE_TYPE_NORMAL
//DO NOT EDIT BELOW THIS LINE UP TO THE NEXT COMMENT
private string array FrostJokes //[8190]
private real array FrostChances //[8190]
private integer JokesTotal = 0
private group FJ_Group = CreateGroup()
private boolean array IsJokeShown
private hashtable SFJ_Hash = InitHashtable()
//END of DO NOT EDIT
endglobals
//Set the damage formula using this function
private function GetDamage takes integer level returns real
return 0.00
endfunction
//Set the end damage formula using this function
private function GetEndDamage takes integer level returns real
return 75.00*level
endfunction
//Set the buff duration using this function
private function GetDuration takes integer level returns real
return 5.00
endfunction
//Set the chance formula using this function
private function GetChance takes integer level, integer index returns real
return FrostChances[index]
endfunction
//Set The AoE formula using this function
private function GetAoE takes integer level returns real
return 250.00*level
endfunction
//The frost joke struct which handles most of the system's work
private struct FrostJokeStruct
unit target //the units hit by SFJ
unit caster //the caster of SFJ
integer abillevel //the ability level of SFJ for the caster
real timeleft //the timeleft for the duration of the buff
static thistype data
static unit TempUnit = null
static unit FiltUnit = null
static unit TempCaster = null
static real chance = 0.00
static integer joke
static integer level
static integer playern
static player controller
static integer id
/*
the periodic method for the buff duration, executed by T32
*/
private method periodic takes nothing returns nothing
set this.timeleft = this.timeleft - T32_PERIOD
if this.timeleft <= 0.00 then
call this.stopPeriodic()
call UnitRemoveAbility(this.target, FJ_BUFFPLACER_ID)
call UnitRemoveAbility(this.target, FJ_BUFF_ID)
call FlushChildHashtable(SFJ_Hash, GetHandleId(this.target))
if DEALS_END_DAMAGE then
call UnitDamageTarget(this.caster, this.target, GetEndDamage(this.abillevel), false, false, ATPD, DTPD, null)
endif
call this.destroy()
endif
endmethod
//implements the T32x module
implement T32x
/*
the method run when a unit gets hit by the SFJ
*/
static method create takes unit target, unit caster, integer level returns thistype
set thistype.id = GetHandleId(target)
set data = LoadInteger(SFJ_Hash, thistype.id, 0)
/*
if the unit is currently unaffected by a SFJ, a new instance is created
else we override the current one or increase the time depending
on the global STACK_TIME
*/
if data == 0 then
set data = thistype.allocate()
set data.target = target
set data.caster = caster
set data.abillevel = level
set data.timeleft = GetDuration(level)
set thistype.TempCaster = CreateUnit(GetOwningPlayer(caster), DUMMY_ID,GetUnitX(caster), GetUnitY(caster), 0.00)
call UnitApplyTimedLife(thistype.TempCaster, 'BTLF', .5)
call SetUnitExploded(thistype.TempCaster, true)
call UnitAddAbility(thistype.TempCaster, FJ_BUFFPLACER_ID)
call IssueTargetOrder(thistype.TempCaster, "soulburn", target)
call data.startPeriodic()
call SaveInteger(SFJ_Hash, thistype.id, 0, data)
else
set data.target = target
set data.caster = caster
set data.abillevel = level
if STACK_TIME then
set data.timeleft = data.timeleft + GetDuration(level)
else
set data.timeleft = GetDuration(level)
endif
endif
if DEALS_DAMAGE then
call UnitDamageTarget(caster, target, GetDamage(level), false, false, ATPD, DTPD, null)
endif
return data
endmethod
/*
this method checks if a unit will get affected by the SFJ or not
*/
static method FrostJokeGroupLoop takes nothing returns boolean
set thistype.FiltUnit = GetFilterUnit()
set thistype.controller = GetOwningPlayer(FiltUnit)
set thistype.playern = GetPlayerId(thistype.controller)
if not IsJokeShown[thistype.playern] then
set IsJokeShown[thistype.playern] = true
call DisplayTextToPlayer(thistype.controller, 0, 0, FrostJokes[thistype.joke])
endif
//checks if the unit is alive
if GetWidgetLife(FiltUnit) > .405 and /*
checks if the unit is an enemy
*/ IsPlayerEnemy(thistype.controller, GetOwningPlayer(thistype.TempUnit)) and /*
checks if the unit will be frozen
*/ GetRandomReal(0.00, 100.00) <= thistype.chance then
call FrostJokeStruct.create(FiltUnit, thistype.TempUnit ,thistype.level)
endif
return false
endmethod
/*
this method picks every unit around the caster of SFJ and passes them to the method above
*/
static method FrostJoke takes nothing returns boolean
local integer i = 0
set thistype.TempUnit = GetTriggerUnit()
set thistype.level = GetUnitAbilityLevel(thistype.TempUnit, FJ_SPELL_ID)
set thistype.joke = GetRandomInt(0, JokesTotal)
set thistype.chance = GetChance(thistype.level, thistype.joke)
if GetSpellAbilityId() == FJ_SPELL_ID then
call GroupEnumUnitsInRange(FJ_Group, GetUnitX(thistype.TempUnit), GetUnitY(thistype.TempUnit), GetAoE(thistype.level), Condition(function thistype.FrostJokeGroupLoop))
endif
loop
exitwhen i > 15
set IsJokeShown[i] = false
set i = i + 1
endloop
return false
endmethod
endstruct
//The init method of this library
private function Init takes nothing returns nothing
local integer i = 0
local trigger t = CreateTrigger()
loop
exitwhen i > 15
call TriggerRegisterPlayerUnitEvent(t, Player(i), EVENT_PLAYER_UNIT_SPELL_EFFECT, null)
set i = i + 1
endloop
call TriggerAddCondition(t, Condition(function FrostJokeStruct.FrostJoke))
set t = null
endfunction
//The function used to register jokes
function RegisterJokes takes string joke, real chance returns nothing
set FrostJokes[JokesTotal] = joke
set FrostChances[JokesTotal] = chance
set JokesTotal = JokesTotal + 1
endfunction
endlibrary
//TESH.scrollpos=0
//TESH.alwaysfold=0
scope Jokes initializer Init
/*
you add the jokes here and set their success rate
function RegisterJokes takes string joke, real chance
*/
private function Init takes nothing returns nothing
call RegisterJokes("What is the smallest fish in the world?" + " Its the Pandaca pygmea fingerling!", 10.00)
call RegisterJokes("An apple a day, makes 10 apples after 10 days!", 30.00)
call RegisterJokes("You Man?", 10.00)
call RegisterJokes("Someone saw an orc with a fel orc, then he asked his friend: Are the orcs tomatoes, coz they turn from green into red", 15.00)
call RegisterJokes("I have three jokes, and I'll split them into two parts each... Jo Ke, Jo Ke, Jo Ke!!!", 15.00)
endfunction
endscope
//TESH.scrollpos=51
//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