the Immortal
I know, I know...
- Reaction score
- 51
Mm, saw it requested a few times (more specifically Crusher's tread out there that got unanswered for weeks) and decided to create 2 versions of the DotA-like basher:
1) Non-stackable basher.
Really simple, just multiple bashers don't stack. Uses hashtables (requiring unit indexing for such a snippet-like spell is.. pointless imo), vJASS, is MUI and should be leakless. Needs 2 abilities (actual bash spell and a spell book to hide it inside.. easily creatable via ObjectMerger). Once again, it's damn simple and straightforward.
2) Non-stackable Basher with cooldown
Kinda harder to implement since bash behaves strangely (seems decision whether to bash or not is made at UNIT_ATTACKED event, meaning I can't just remove it then since it'll chainbash).
But in short, adds the 100% bash abil on the unit if it's not on cooldown, removes it when the unit takes damage by attacker and is stunned, and also creates a timer to count cooldown.
Again uses hashtables, vJASS, is MUI and should be leakless. Requires 2 abilities (100% bash spell and a spell book to hide it inside, again easily creatable via ObjectMerger). Still uses a simple and straightforward method, and is kinda sloppy thou it works as intended. (If you suspect it does not, write me, I have 2 more ideas how to implement it.. thou for me it works perfectly)
Blahblah, haven't put any resources here or coded seriously in vJASS for almost 2 years, so if something isn't how it should be, please say so. =P
PS. add an [Item] prefix, lols?
PPS. And forgot to add the test map.. how typical of me, eh -.-
EDIT: Removed that minor leak that skipp'd through and abilities are now added via ObjectMerger.
1) Non-stackable basher.
Really simple, just multiple bashers don't stack. Uses hashtables (requiring unit indexing for such a snippet-like spell is.. pointless imo), vJASS, is MUI and should be leakless. Needs 2 abilities (actual bash spell and a spell book to hide it inside.. easily creatable via ObjectMerger). Once again, it's damn simple and straightforward.
JASS:
/*
Non-stackable Basher w/o cooldown
To import:
- Create a new trigger, name it something like 'Basher' and copy all that shiet to it.
- Uncomment the next two lines, save the map, close it, open it, and COMMENT them again. */
// //! external ObjectMerger w3a AHbh aFdS alev 1 ahdu 1 1.40 adur 1 1.40 Hbh1 1 25 anam "Basher Stun"
// //! external ObjectMerger w3a Aspb aFdT spb1 1 aFdS anam "Basher Spellbook"
/* - Now go to Object Editor -> Items -> Custom -> Basher Stun
and set the Chance / Duration / Bonus Dmg as you want them to be
- If your desired item has bash on it, REMOVE it.
- Write the item Id of your basher and modify the filter function as you wish.. right down there they are.
- Mmm, that should be everything ^_-
made by Ixtreon (a.k.a. the Immortal)
*/
scope Basher initializer init
globals
private constant integer BASHER_ID = 039;I000039; //the item with bash. (it must NOT have bash ability at all)
private constant integer BASHER_SPELLBOOK_ABIL = 039;aFdT039; //SpellBook ability rawcode. Do NOT change unless you know what ya'r doing
endglobals
private function ToBashOrNot takes unit Bashing returns boolean
//return true //will bash.. everytime
return GetUnitAbilityLevel(Bashing, 039;AHbh039;) == 0 //won't bash if unit has ability bash
endfunction
//==============================================================
globals
private constant hashtable ht = InitHashtable()
endglobals
private function onPickup takes nothing returns nothing
local unit u = GetTriggerUnit()
local integer i = LoadInteger(ht, 0, GetHandleId(u))
if i == 0 then
call UnitAddAbility(u, BASHER_SPELLBOOK_ABIL)
endif
call SaveInteger(ht, 0, GetHandleId(u), i + 1)
set u = null
endfunction
private function onPickupCond takes nothing returns boolean
if GetItemTypeId(GetManipulatedItem()) == BASHER_ID then
call onPickup()
endif
return false
endfunction
private function onDrop takes nothing returns nothing
local unit u = GetTriggerUnit()
local integer i = LoadInteger(ht, 0, GetHandleId(u))
if i == 1 then
call UnitRemoveAbility(u, BASHER_SPELLBOOK_ABIL)
endif
call SaveInteger(ht, 0, GetHandleId(u), i-1)
set u = null
endfunction
private function onDropCond takes nothing returns boolean
if GetItemTypeId(GetManipulatedItem()) == BASHER_ID then
call onDrop()
endif
return false
endfunction
private function init takes nothing returns nothing
local trigger t = CreateTrigger()
local trigger t2 = CreateTrigger()
local integer i = 0
loop
call SetPlayerAbilityAvailable(Player(i), BASHER_SPELLBOOK_ABIL, false)
call TriggerRegisterPlayerUnitEvent(t, Player(i), EVENT_PLAYER_UNIT_DROP_ITEM, null)
call TriggerRegisterPlayerUnitEvent(t2, Player(i), EVENT_PLAYER_UNIT_PICKUP_ITEM, null)
set i = i + 1
exitwhen i == bj_MAX_PLAYER_SLOTS
endloop
call TriggerAddCondition(t, Condition(function onDropCond))
call TriggerAddCondition(t2, Condition(function onPickupCond))
set t = null
set t2 = null
endfunction
endscope
2) Non-stackable Basher with cooldown
Kinda harder to implement since bash behaves strangely (seems decision whether to bash or not is made at UNIT_ATTACKED event, meaning I can't just remove it then since it'll chainbash).
But in short, adds the 100% bash abil on the unit if it's not on cooldown, removes it when the unit takes damage by attacker and is stunned, and also creates a timer to count cooldown.
Again uses hashtables, vJASS, is MUI and should be leakless. Requires 2 abilities (100% bash spell and a spell book to hide it inside, again easily creatable via ObjectMerger). Still uses a simple and straightforward method, and is kinda sloppy thou it works as intended. (If you suspect it does not, write me, I have 2 more ideas how to implement it.. thou for me it works perfectly)
JASS:
/*
Non-stackable Basher with cooldown
To import:
- Create a new trigger, name it something like 'Basher' and copy all that shiet to it.
- Uncomment the next two lines, save the map, close it, open it, and COMMENT them again. */
// //! external ObjectMerger w3a AHbh aFdU alev 1 ahdu 1 1.40 adur 1 1.40 Hbh1 1 100 anam "Basher Stun (100%)"
// //! external ObjectMerger w3a Aspb aFdV spb1 1 aFdU anam "Basher Spellbook (100%)"
/* - Now go to Object Editor -> Items -> Custom -> Basher Stun
and set the Duration / Bonus damage as you want them to be. Do NOT touch the % chance!
- If your desired item has bash on it, REMOVE it.
- Write the item Id of your basher and modify the filter function as you wish.. right down there they are.
- Mmm, that should be everything ^_-
made by Ixtreon (a.k.a. the Immortal)
*/
scope CDBasher initializer init
globals
private constant integer BASHER_ID = 039;I001039; //the item with bash. (it must NOT have bash ability at all)
private constant integer BASHER_SPELLBOOK_ABIL = 039;aFdV039; //The spellbook's Id. Do NOT change this line unless you know what ya'r doing
private constant integer CHANCE_TO_PROC = 25 //% chance to bash
private constant real COOLDOWN = 2.0 //basher's cooldown
private constant integer STUNNED_BUFF = 039;BPSE039; //the buff when a unit is stunnd (usually no reason to change it)
endglobals
private function ToBashOrNot takes unit Bashing returns boolean
//return true //will bash.. everytime
return GetUnitAbilityLevel(Bashing, 039;AHbh039;) == 0 //won't bash if unit has ability bash
endfunction
//==============================================================
globals
private constant hashtable ht = InitHashtable()
endglobals
private function RemoveCd takes nothing returns nothing
local timer t = GetExpiredTimer()
local integer ui = LoadInteger(ht, 0, GetHandleId(t))
call RemoveSavedBoolean(ht, 1, ui) //no cd
call RemoveSavedInteger(ht, 0, GetHandleId(t)) //flush timer data
call DestroyTimer(t)
set t = null
endfunction
private function onDamage takes nothing returns boolean
local trigger t = GetTriggeringTrigger()
if LoadUnitHandle(ht, 0, GetHandleId(t)) == GetEventDamageSource() then
if GetUnitAbilityLevel(GetTriggerUnit(), STUNNED_BUFF) > 0 then
call UnitRemoveAbility(GetEventDamageSource(), BASHER_SPELLBOOK_ABIL)
call RemoveSavedHandle(ht, 0, GetHandleId(t))
call DestroyTrigger(t)
endif
endif
set t = null
return false
endfunction
private function Actions takes nothing returns nothing
local unit a = GetAttacker()
local timer t
local trigger trg
local boolean OnCd = LoadBoolean(ht, 1, GetHandleId(a))
if not OnCd then
call UnitAddAbility(a, BASHER_SPELLBOOK_ABIL)
set trg = CreateTrigger()
call TriggerRegisterUnitEvent(trg, GetTriggerUnit(), EVENT_UNIT_DAMAGED)
call TriggerAddCondition(trg, function onDamage)
call SaveUnitHandle(ht, 0, GetHandleId(trg), a)
call SaveBoolean(ht, 1, GetHandleId(a), true) //is OnCD
set t = CreateTimer()
call TimerStart(t, COOLDOWN, false, function RemoveCd)
call SaveInteger(ht, 0, GetHandleId(t), GetHandleId(a))
set t = null
set trg = null
endif
set a = null
endfunction
private function Cond takes nothing returns boolean
local integer i = 0
if GetRandomInt(0, 99) < CHANCE_TO_PROC and ToBashOrNot(GetAttacker()) then
loop
if GetItemTypeId(UnitItemInSlot(GetAttacker(), i)) == BASHER_ID then
call Actions()
return false
endif
exitwhen i == 5
set i = i + 1
endloop
endif
return false
endfunction
private function init takes nothing returns nothing
local trigger t = CreateTrigger()
local integer i = 0
loop
call SetPlayerAbilityAvailable(Player(i), BASHER_SPELLBOOK_ABIL, false)
call TriggerRegisterPlayerUnitEvent(t, Player(i), EVENT_PLAYER_UNIT_ATTACKED, null)
set i = i + 1
exitwhen i == bj_MAX_PLAYER_SLOTS
endloop
call TriggerAddCondition(t, Condition(function Cond))
set t = null
endfunction
endscope
Blahblah, haven't put any resources here or coded seriously in vJASS for almost 2 years, so if something isn't how it should be, please say so. =P
PS. add an [Item] prefix, lols?
PPS. And forgot to add the test map.. how typical of me, eh -.-
EDIT: Removed that minor leak that skipp'd through and abilities are now added via ObjectMerger.