- Joined
- Sep 14, 2012
- Messages
- 3,413
Okay guys here we put some systems we will use and some coding we need.
I'm using Table by Vexorian everywhere
And I think we'll use by Vexorian in the map -> More simple and less verbose ...
First a library for preload things and play sound :
Another non-tested preload thingy which is more efficient :
Fear System with the fear_of_the_dark sound :
GetUnitArmor/Damage (still needs some test but it should work) :
In the map header :
This was how to properly allocate
I'm using Table by Vexorian everywhere
And I think we'll use by Vexorian in the map -> More simple and less verbose ...
First a library for preload things and play sound :
JASS:
library Preload requires Table //By Vex atm
globals
//CHANGE THIS LINE TO FIT TO THE MAP WITH YOUR DUMMY_ID
private constant integer DUMMY_ID = 'hfoo'
endglobals
private module Module
static method onInit takes nothing returns nothing
call init()
endmethod
endmodule
private struct slop extends array
string snd
static HandleTable tab
thistype recycleNext
static integer instanceCount
static thistype recycle
static unit dummy
static method create takes nothing returns thistype
local thistype this
if recycle == 0 then
set instanceCount = instanceCount + 1
set this = instanceCount
else
set this = recycle
set recycle = recycle.recycleNext
endif
return this
endmethod
method destroy takes nothing returns nothing
set recycleNext = recycle
set recycle = this
endmethod
static method init takes nothing returns nothing
set tab = HandleTable.create()
set instanceCount = 0
set recycle = 0
set dummy = CreateUnit(Player(15), DUMMY_ID, 0,0,0)
call UnitApplyTimedLife(dummy, 'BTLF', 2)
endmethod
implement Module
endstruct
private function AfterPreload takes nothing returns nothing
local timer t = GetExpiredTimer()
local slop s = slop.tab[t]
local sound sn = CreateSound(s.snd, false, false, false, 12700, 12700, "" )
call SetSoundVolume(sn, 1)
call StartSound(sn)
call KillSoundWhenDone(sn)
set sn = null
call slop.tab.flush(t)
call DestroyTimer(t)
set t = null
call s.destroy()
endfunction
public function PreloadSound takes string snd returns nothing
local timer t = CreateTimer()
local slop s = slop.create()
set s.snd = snd
set slop.tab[t] = s
call TimerStart( t, 0.01, false, function AfterPreload )
set t = null
endfunction
public function PreloadSpell takes integer id returns nothing
call UnitAddAbility(slop.dummy, id)
endfunction
//The keyword public will be the difference between the BJ func and mine
public function PlaySound takes string s, real x, real y returns nothing
local sound snd = CreateSound(s,false,true,true,12700,12700,"")
call SetSoundVolume(snd,127)
call SetSoundPitch(snd,.88)
call SetSoundPosition(snd,x,y,50.)
call StartSound(snd)
call KillSoundWhenDone(snd)
set snd=null
endfunction
endlibrary
Another non-tested preload thingy which is more efficient :
JASS:
library Preload
globals
//Change the rawcode to make it fit to a dummy unit of your map.
private constant integer DUMMY_ID = 'hfoo'
endglobals
private module Module
static method onInit takes nothing returns nothing
call init()
endmethod
endmodule
struct PreloadEx extends array
private string snd
private thistype prev
private thistype next
private static integer count
private static unit dummy
private static timer period
private method destroy takes nothing returns nothing
if this.next != 0 then
set this.next.prev = this.prev
endif
set this.prev.next = this.next
set this.prev = thistype(0).prev
set thistype(0).prev = this
if thistype(0).next == 0 then
call PauseTimer(period)
endif
endmethod
private static method cond takes nothing returns boolean
set dummy = null
call DestroyTrigger(GetTriggeringTrigger())
return false
endmethod
static method PlaySound takes string s, real x, real y returns nothing
local sound snd = CreateSound(s,false,true,true,12700,12700,"")
call SetSoundVolume(snd,127)
call SetSoundPitch(snd,.88)
call SetSoundPosition(snd,x,y,50.)
call StartSound(snd)
call KillSoundWhenDone(snd)
set snd=null
endmethod
private static method periodic takes nothing returns nothing
local thistype this = thistype(0).next
local sound sn
loop
exitwhen this == 0
set sn = CreateSound(this.snd, false, false, false, 12700, 12700, "" )
call SetSoundVolume(sn, 1)
call StartSound(sn)
call KillSoundWhenDone(sn)
call this.destroy()
set this = this.next
endloop
set sn = null
endmethod
static method PreloadSpell takes integer id returns nothing
call UnitAddAbility(dummy, id)
endmethod
static method PreloadSound takes string snd returns nothing
local thistype this
if thistype(0).prev == 0 then
set count = count + 1
set this = count
else
set this = thistype(0).prev
set thistype(0).prev = thistype(0).prev.prev
endif
if thistype(0).next == 0 then
call TimerStart(period, 0.0312500, true, function thistype.periodic)
else
set thistype(0).next.prev = this
endif
set this.next = thistype(0).next
set thistype(0).next = this
set this.prev = thistype(0)
set this.snd = snd
endmethod
private static method init takes nothing returns nothing
local trigger t = CreateTrigger()
call TriggerRegisterTimerEvent(t, 2.1, false)
call TriggerAddCondition(t, Condition(function thistype.cond))
set count = 0
set period = CreateTimer()
set dummy = CreateUnit(Player(15), DUMMY_ID, 0,0,0)
call UnitApplyTimedLife(dummy, 'BTLF', 2)
set t = null
endmethod
implement Module
endstruct
endlibrary
Fear System with the fear_of_the_dark sound :
JASS:
library FearSystem /* v2.5
************************************************************************************
*
* */uses /*
* */optional/*
*
* */ Table, /* [url]http://www.hiveworkshop.com/forums/jass-resources-412/snippet-new-table-188084/[/url]
* //By Bribe or Vexorian
*
* */Preload /*
************************************************************************************
*
* struct Fear extends array
*
* Description
* -------------------------
*
* This is a fear system; use it to remove player
* control from a unit temporarily. Units affected
* will also be unable to attack.
*
* Fields
* -------------------------
*
* unit targ -> The unit you want to apply the fear.
*
* string path -> The path of the sfx you want to add to the unit.
*
* string attach -> The attachment string you want the sfx to be on the unit
*
* readonly effect e -> The effect currently applied to the unit.
* Initializes to null
*
* Methods
* -------------------------
*
* static method create takes nothing returns thistype
* method destroy takes nothing returns nothing
*
* method start takes nothing returns nothing
* When you have set every parameters you start your fear instance.
*
* method changeEffect takes string path, string attach returns nothing
* If you already have set the effect of your instance and it is running
* and you want to change it use this.
*
* static method isFeared takes unit u returns boolean
* static method get takes unit u returns thistype
*
* Operators
* -------------------------
*
* method operator time= takes real t returns nothing
* method operator time takes nothing returns real
*
* Credits
* -------------------------
*
* - Vexorian for vJASS and Table
* - Maker for the DisableUnit function
* - Bribe for Table
* - Chobibo for the addition in the DisableUnit function/
*
************************************************************************************/
//native UnitAlive takes unit u returns boolean
globals
//There will be check every FPS second.
private constant real FPS = 0.31250000
//Feared units will change direction every EACH_CHANGE FPS.
private constant integer EACH_CHANGE = 3
//Feared units will go maximum in a circle of 150 around them each time they change direction.
private constant real AROUND = 150.
//The rawcode of the attack disable. Be sure it is the same in the Object Editor.
private constant integer DISABLE_ATTACK = 'W000'
//The rawcode of the morph. Be sure it is the same in the Object Editor.
private constant integer MORPH_ID = 'Z001'
//The rawcode of the bear form. Be sure it is the same in the Object Editor.
private constant integer BEAR_ID = 'Z000'
private constant string SOUND_PATH = "FEAROFTHEDARK_SOUND_WAR3.mp3"
endglobals
static if Table.flush2D.exists then
globals
private HandleTable tab
endglobals
elseif Table.has.exists then
globals
private Table tb
endglobals
else
globals
private hashtable ht = InitHashtable()
endglobals
endif
private function round takes real r returns integer
if r-0.5 > R2I(r) then
return R2I(r+1)
else
return R2I(r)
endif
endfunction
private function modulo takes integer a, integer b returns integer
return a - (a/b)*b
endfunction
//Credits to Maker for this awesum func <3
private function DisableControl takes unit u returns nothing
local boolean b
call UnitAddAbility(u, 'Aloc')
call UnitRemoveAbility(u, 'Aloc')
if IsUnitType(u, UNIT_TYPE_HERO) then
call UnitAddAbility(u,MORPH_ID)
call IssueImmediateOrder(u, "metamorphosis")
call UnitRemoveAbility(u,MORPH_ID)
else
call UnitAddAbility(u, BEAR_ID)
call IssueImmediateOrder(u, "bearform")
call UnitRemoveAbility(u, BEAR_ID)
endif
//Thanks to chobibo for this idea
if GetLocalPlayer() != GetOwningPlayer(u) then
set b = not IsUnitHidden(u)
call ShowUnit(u,true)
call ShowUnit(u,false)
call ShowUnit(u,b)
endif
//I added this line to disable their attack too.
call UnitAddAbility(u,DISABLE_ATTACK)
endfunction
private function EnableControl takes unit u returns nothing
local boolean backup = not IsUnitHidden(u)
call ShowUnit(u,false)
//I added this line to enable their attack.
call UnitRemoveAbility(u,DISABLE_ATTACK)
call ShowUnit(u,true)
call ShowUnit(u,backup)
endfunction
struct Fear extends array
unit targ
string path
string attach
boolean s
readonly effect e
readonly boolean b
private integer steps
private integer startat
private static timer period
private static integer dindex
private static thistype array data
private static integer instanceCount
private static integer recycle
private thistype recycleNext
private static method periodic takes nothing returns nothing
local thistype this
local real x
local real y
local integer i = 0
loop
exitwhen i > dindex
set this = data[i]
if modulo(this.steps,EACH_CHANGE) == this.startat then
set x = GetUnitX(this.targ)
set y = GetUnitY(this.targ)
call IssuePointOrder(this.targ, "move", GetRandomReal(x-AROUND,x+AROUND), GetRandomReal(y-AROUND, x+AROUND) )
endif
set this.steps = this.steps - 1
if this.steps == 0 or not(UnitAlive(this.targ)) then
set data[i] = data[dindex]
set i = i - 1
set dindex = dindex - 1
if this.e != null then
call DestroyEffect(this.e)
set this.e = null
endif
call IssueImmediateOrder(this.targ,"stop")
call EnableControl(this.targ)
static if Table.flush2D.exists then
call tab.flush(this.targ)
elseif Table.has.exists then
return tb.remove(GetHandleId(this.targ))
else
return FlushChildHashtable(ht,GetHandleId(this.targ))
endif
if this.b then
set this.targ = null
set recycleNext = recycle
set recycle = this
endif
endif
if dindex == -1 then
call PauseTimer(period)
endif
set i = i + 1
endloop
endmethod
static method isFeared takes unit u returns boolean
static if Table.flush2D.exists then
return tab.exists(u)
elseif Table.has.exists then
return tb.has(GetHandleId(u))
else
return HaveSavedInteger(ht,GetHandleId(u),0)
endif
endmethod
method operator time= takes real t returns nothing
set this.steps = round(t/FPS)
endmethod
method operator time takes nothing returns real
return this.steps*FPS
endmethod
method changeEffect takes string path, string attach returns nothing
call DestroyEffect(this.e)
set this.e = null
set this.e = AddSpecialEffectTarget(path,this.targ,attach)
endmethod
static method get takes unit u returns thistype
local thistype this
if isFeared(u) then
static if Table.flush2D.exists then
set this = tab[u]
if this.b then
return tab[u]
else
debug call BJDebugMsg("Trying to get an instance that will be destroyed at the end of the execution")
return 0
endif
elseif Table.has.exists then
set this = tb[GetHandleId(u)]
if this.b then
return tb[GetHandleId(u)]
else
debug call BJDebugMsg("Trying to get an instance that will be destroyed at the end of the execution")
return 0
endif
else
set this = LoadInteger(ht,GetHandleId(u),0)
if this.b then
return LoadInteger(ht,GetHandleId(u),0)
else
debug call BJDebugMsg("Trying to get an instance that will be destroyed at the end of the execution")
return 0
endif
endif
else
debug call BJDebugMsg("Tryng to get wrong instance")
return 0
endif
endmethod
method start takes nothing returns nothing
debug if this.targ==null or this.steps==0 then
debug call BJDebugMsg("You're instanciating badly ....")
debug return
debug endif
set dindex = dindex + 1
set data[dindex] = this
set this.startat = modulo(this.steps,EACH_CHANGE)
call DisableControl(this.targ)
if this.path != "" and this.attach != "" then
set this.e = AddSpecialEffectTarget(this.path, this.targ, this.attach)
endif
if this.s then
call Preload_PlaySound(SOUND_PATH,GetUnitX(this.targ),GetUnitY(this.targ))
endif
static if Table.flush2D.exists then
set tab[this.targ] = this
elseif Table.has.exists then
set tb[GetHandleId(this.targ)] = this
else
call SaveInteger(ht,GetHandleId(this.targ),0,this)
endif
if dindex == 0 then
call TimerStart(period, FPS, true, function thistype.periodic)
endif
endmethod
static method create takes nothing returns thistype
local thistype this
if recycle == 0 then
set instanceCount = instanceCount + 1
set this = instanceCount
else
set this = recycle
set recycle = recycleNext
endif
set this.path = ""
set this.attach = ""
set this.e = null
set this.b = false
set this.s = false
return this
endmethod
method destroy takes nothing returns nothing
set this.b = true
endmethod
private static method onInit takes nothing returns nothing
static if Table.flush2D.exists then
set tab = HandleTable.create()
elseif Table.has.exists then
set tb = Table.create()
endif
set dindex = - 1
set instanceCount = 0
set recycle = 0
set period = CreateTimer()
call Preload_PreloadSound(SOUND_PATH)
endmethod
endstruct
endlibrary
GetUnitArmor/Damage (still needs some test but it should work) :
JASS:
library GetDamage requires Table
globals
private HandleTable tab
private HandleTable damage
//Set this to true if you want this system to get the attack damage of every unit of your map.
//But be aware that this may lag.
//If you let this to false then you will have to use the function Add(unit) to add a unit to this system.
private constant boolean ALL_UNITS = false
private constant integer DUMMY_ID = 'd000'
private constant real ARMOR_CONSTANT = 0.06
endglobals
static if not ALL_UNITS then
globals
private group UNITS = CreateGroup()
endglobals
public function Add takes unit u returns nothing
call GroupAddUnit( UNITS, u )
endfunction
endif
public function GetDamage takes unit u returns integer
return damage[u]
endfunction
public function GetArmor takes unit u returns real
local real life = GetWidgetLife( u )
local real life2
local real x = GetUnitX( u )
local real y = GetUnitY( u )
local unit v = CreateUnit( Player(15), DUMMY_ID, x, y, 0 )
local real test = 10
if GetWidgetLife(u) > 200 then
set test = 100
endif
call UnitDamageTarget( v, u, test, true, false, ATTACK_TYPE_CHAOS, DAMAGE_TYPE_NORMAL, null )
set life2 = life - GetWidgetLife( u )
call RemoveUnit( v )
set v = null
call SetWidgetLife( u, GetWidgetLife( u ) + life2 )
if ( life2 > test ) then
return (-1*(test - life2 ) ) / ( life2 * ARMOR_CONSTANT )
else
return ( test - life2 ) / ( life2 * ARMOR_CONSTANT )
endif
endfunction
private struct Damage extends array
unit attacker
unit attacked
trigger t
thistype recycle
static integer instanceCount
static thistype recycleNext
static method cond2 takes nothing returns boolean
local thistype this
if tab[GetEventDamageSource()] != 0 then
set this = tab[GetEventDamageSource()]
set damage[this.attacker] = R2I(GetEventDamage())
call tab.flush(this.attacker)
call DestroyTrigger(this.t)
set this.attacker = null
set this.attacked = null
set this.t = null
call this.destroy()
endif
return false
endmethod
static method cond takes nothing returns boolean
local thistype this
local boolean b = true
static if not ALL_UNITS then
if not IsUnitInGroup(GetAttacker(), UNITS) then
set b = false
endif
endif
if b then
if recycle == 0 then
set instanceCount = instanceCount + 1
set this = instanceCount
else
set this = recycle
set recycle = recycle.recycleNext
endif
set this.attacker = GetAttacker()
set this.attacked = GetTriggerUnit()
set this.t = CreateTrigger()
set tab[this.attacked] = this
call TriggerRegisterUnitEvent( this.t, this.attacked, EVENT_UNIT_DAMAGED )
call TriggerAddCondition( this.t, Condition( function thistype.cond2 ) )
endif
return false
endmethod
method destroy takes nothing returns nothing
set recycleNext = recycle
set recycle = this
endmethod
private static method onInit takes nothing returns nothing
local trigger t = CreateTrigger()
call TriggerRegisterAnyUnitEventBJ( t, EVENT_PLAYER_UNIT_ATTACKED )
call TriggerAddCondition( t, Condition(function thistype.cond) )
set tab = HandleTable.create()
set damage = HandleTable.create()
set instanceCount = 0
set recycleNext = 0
set t = null
endmethod
endstruct
endlibrary
In the map header :
JASS:
native UnitAlive takes unit u returns boolean
//This module can be used to implement in struct extends array for the init function.
module Module
private static method onInit takes nothing returns nothing
call init()
endmethod
endmodule
function ResetAbilityCooldown takes unit u, integer raw returns nothing
local integer i = 1
local integer lvl = GetUnitAbilityLevel(u, raw)
call UnitRemoveAbility(u, raw)
call UnitAddAbility(u, raw)
if IsUnitType(u, UNIT_TYPE_HERO) then
loop
exitwhen i > lvl
call SelectHeroSkill(u, raw)
set i = i + 1
endloop
else
call UnitAddAbility(u, raw)
call SetUnitAbilityLevel(u, raw, lvl)
endif
endfunction
function RemoveLocust takes unit u returns nothing
local boolean backup = not IsUnitHidden(u)
call ShowUnit(u,false)
call UnitRemoveAbility(u, 'Aloc')
call ShowUnit(u,backup)
endfunction
JASS:
library LLAlloc /*
************************************************************************************
*
* module LL_Alloc
*
* Description
* -------------------------
*
* This is an alternative allocation that allows you to use LinkedList
* in your struct. Linked List for allocation, destruction, iteration.
*
* Fields
* -------------------------
*
* private thistype next
* private thistype prev
*
* private static integer count
*
* debug private boolean check
*
* Methods
* -------------------------
*
* static method allocate takes nothing returns thistype
* method deallocate takes nothing returns nothing
*
* method chain takes nothing returns nothing
* ~Chain the instance in order to make the iteration iterate through it
*
* method dequeue takes nothing returns nothing
* ~Unchain the instance in order to make the iteration not iterate anymore through it
*
* method operator first takes nothing returns thistype
* ~Return the first one in the list to iterate
*
* Example of usage
* ~~~~~~~~~~~~~~~~~~
*
* private struct Test extends array
* Your
* Parameters
*
* implement LL_Alloc
*
* static method periodic takes nothing returns nothing
* local thistype this = first
* loop
* exitwhen this == 0
*
* Do
* Your
* Stuff
*
* set this = this.next
* endloop
* endmethod
*
* static method create takes nothing returns thistype
* local thistype this = thistype.allocate()
*
* Perform
* Create
* Stuff
*
* return this
* endmethod
* endstruct
************************************************************************/
module LL_Alloc
private thistype prev
private thistype next
private static integer count = 0
debug private boolean check
private method deallocate takes nothing returns nothing
set this.prev = thistype(0).prev
set thistype(0).prev = this
if thistype(0).next == 0 then
call PauseTimer(period)
endif
endmethod
private static method allocate takes nothing returns thistype
local thistype this
if thistype(0).prev == 0 then
set count = count + 1
debug if count > 8190 then
debug call BJDebugMsg("Linked List Module -> You're instanciating too much structs !!!")
debug return 0
debug endif
set this = count
else
set this = thistype(0).prev
set thistype(0).prev = thistype(0).prev.prev
endif
debug set this.check = false
return this
endmethod
private method chain takes nothing returns nothing
debug if this.check then
debug call BJDebugMsg("You're trying to chain an already chained unit")
debug return
debug endif
debug set this.check = true
if thistype(0).next == 0 then
call TimerStart(period, 0.0312500, true, function thistype.periodic)
else
set thistype(0).next.prev = this
endif
set this.next = thistype(0).next
set thistype(0).next = this
set this.prev = thistype(0)
endmethod
private method unchain takes nothing returns nothing
debug if not this.check then
debug call BJDebugMsg("You're tring to unchain a non-chained unit")
debug return
debug endif
debug set this.check = false
if this.next != 0 then
set this.next.prev = this.prev
endif
set this.prev.next = this.next
endmethod
method operator first takes nothing returns thistype
return thistype(0).next
endmethod
endmodule
endlibrary
This was how to properly allocate