Spellpack Nevermore, the Shadowfiend

Ayanami

칼리
Introduction
Decided to make Shadowfiend's spell in vJASS for fun.

Requirements
- Timer32
- GroupUtils

The spells:
  • Shadowraze [Active]
  • Necromastery [Passive]
  • Presence of the Dark Lord [Passive]
  • Requiem of Souls [Active]


Details
- The spells are vJASS
- They should be leak-less and lag-less
- It is MUI, meaning can be cast many times at the same instance
- Shadowfiend from DoTA


Implementation
JASS:

//==============================================================================
//                      SHADOW FIELD SPELLPACK v1.2                       
//                            BY Ayanami                            
//==============================================================================

//==============================================================================
//                            REQUIREMENTS                                      
//==============================================================================
//
// - vJASS Compiler (NewGen)
// - Timer32                                                              
// - GroupUtils                                                                  
//                                                            
//==============================================================================

//==============================================================================
//                           IMPLEMENTATION                                     
//==============================================================================
//
// 1) Copy the whole "Required Systems" Trigger folder & paste in map
// 2) Save the map, it will take a bit longer than usual
// 3) After saving, close the map and re-open it
// 4) Delete or disable the trigger "Objects"
// 5) Copy all 8 abilities under "Undead" & paste in map
// 6) Copy the single buff under "Undead" & paste in map
// 7) Ensure that the following abilities have their buff set properly:
//      Presence of the Dark Lord - Presence of the Dark Lord
// 8) Copy the whole "Shadowfiend" Trigger folder
// 9) Go through all the spell Configurations
//
//==============================================================================



Spells

Shadowraze

Description:
Gives the Shadow Fiend the power to desecrate regions in front of him at varying distances (200/450/700).

Level 1 - 75 damage.
Level 2 - 150 damage.
Level 3 - 225 damage.
Level 4 - 300 damage.

Cast Range: Varies
Target Type: Instant
Cooldown: 10 seconds

Screenshot:


Code:
JASS:

scope Shadowraze initializer OnInit // requires GroupUtils

//===========================================================================
//                           CONFIGURABLES                        
//===========================================================================

globals
    private constant integer ABILID = 'ABSR' // raw code of ability "Shadowraze"
    private constant integer ABILIDZ = 'ASR0' // raw code of ability "Shadowraze (Z)"
    private constant integer ABILIDX = 'ASR1' // raw code of ability "Shadowraze (X)"
    private constant integer ABILIDC = 'ASR2' // raw code of ability "Shadowraze (C)"
    private constant integer PRELOADID = 'prel' // raw code of unit "Preloader"
    
    private constant integer DUMMYID = 'sHAD' // raw code of unit "Shadowraze Dummy", acts as the visual effect itself
    private constant real ANIMDUR = 2.0 // duration of DUMMYID
    private constant integer RED = 0 // red vertex color of DUMMYID
    private constant integer GREEN = 0 // green vertex color of DUMMYID
    private constant integer BLUE = 0 // blue vertex color of DUMMYID
    private constant integer TRANS = 255 // transparency of DUMMYID, where 0 is fully transparent
    private constant real SCALE = 1.2 // scale size of DUMMYID
    
    private constant attacktype ATK = ATTACK_TYPE_NORMAL // attack type of damage
    private constant damagetype DMG = DAMAGE_TYPE_MAGIC // damage type of damage
    private constant weapontype WEP = WEAPON_TYPE_WHOKNOWS // weapon type of damage
endglobals

private function GetDamage takes integer level returns real
    return 75.0 * level // damage dealt
endfunction

private function GetArea takes integer level returns real
    return 250.0 // area of effect
endfunction

private function GetRangeZ takes integer level returns real
    return 200.0 // range of "Shadowraze (Z)"
endfunction

private function GetRangeX takes integer level returns real
    return 450.0 // range of "Shadowraze (X)"
endfunction

private function GetRangeC takes integer level returns real
    return 700.0 // range of "Shadowraze (C)"
endfunction

//===========================================================================
//                          END CONFIGURABLES                        
//===========================================================================

native UnitAlive takes unit id returns boolean

globals
    private unit Caster
    private real Damage
endglobals

private function OnRemove takes nothing returns boolean
    local trigger t = GetTriggeringTrigger()
    
    call RemoveUnit(GetTriggerUnit())
    call TriggerClearConditions(t)
    call DestroyTrigger(t)
    set t = null
    return false
endfunction

private function FilterFunc takes nothing returns boolean
    local unit u = GetFilterUnit()
    
    if IsUnitEnemy(u, GetOwningPlayer(Caster)) and UnitAlive(u) and not IsUnitType(u, UNIT_TYPE_STRUCTURE) then
        call UnitDamageTarget(Caster, u, Damage, true, false, ATK, DMG, WEP)
    endif
    set u = null
    return false
endfunction

private function Actions takes nothing returns boolean
    local trigger t
    local unit u
    local integer spellid = GetSpellAbilityId()
    local integer level
    local real range
    local real a
    local real x
    local real y
    
    if spellid == ABILIDZ or spellid == ABILIDX or spellid == ABILIDC then
        set Caster = GetTriggerUnit()
        set level = GetUnitAbilityLevel(Caster, ABILID)
        set Damage = GetDamage(level)
        
        if spellid == ABILIDZ then
            set range = GetRangeZ(level)
        elseif spellid == ABILIDX then
            set range = GetRangeX(level)
        else
            set range = GetRangeC(level)
        endif
        
        set a = GetUnitFacing(Caster) * bj_DEGTORAD
        set x = GetUnitX(Caster) + range * Cos(a)
        set y = GetUnitY(Caster) + range * Sin(a)
        set u = CreateUnit(GetOwningPlayer(Caster), DUMMYID, x, y, a * bj_RADTODEG)
        call SetUnitVertexColor(u, RED, GREEN, BLUE, TRANS)
        call SetUnitScale(u, SCALE, SCALE, SCALE)
        call UnitApplyTimedLife(u, 'BTLF', ANIMDUR)
        set t = CreateTrigger()
        call TriggerRegisterDeathEvent(t, u)
        call TriggerAddCondition(t, Condition(function OnRemove))
        call GroupEnumUnitsInArea(ENUM_GROUP, x, y, GetArea(level), Filter(function FilterFunc))
    endif
    set t = null
    set u = null
    return false
endfunction

private function Learn takes nothing returns boolean
    local unit u
    local integer level
    
    if GetLearnedSkill() == ABILID then
        set u = GetTriggerUnit()
        set level = GetUnitAbilityLevel(u, ABILID)
        if level == 1 then
            call UnitAddAbility(u, ABILIDZ)
            call UnitAddAbility(u, ABILIDX)
            call UnitAddAbility(u, ABILIDC)
        else
            call SetUnitAbilityLevel(u, ABILIDZ, level)
            call SetUnitAbilityLevel(u, ABILIDX, level)
            call SetUnitAbilityLevel(u, ABILIDC, level)
        endif
    endif
    set u = null
    return false
endfunction

private function OnInit takes nothing returns nothing
    local trigger t = CreateTrigger()
    local unit u = CreateUnit(Player(13), PRELOADID, 0, 0, 0)
    
    call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SPELL_EFFECT)
    call TriggerAddCondition(t, Condition(function Actions))
    set t = null
    
    set t = CreateTrigger()
    call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_HERO_SKILL)
    call TriggerAddCondition(t, Condition(function Learn))
    set t = null
    
    //preload
    call UnitAddAbility(u, ABILIDZ)
    call UnitAddAbility(u, ABILIDX)
    call UnitAddAbility(u, ABILIDC)
    call RemoveUnit(CreateUnit(Player(13), DUMMYID, 0, 0, 0))
    call RemoveUnit(u)
    set u = null
endfunction

endscope


Necromastery

Description:
Whenever the Shadow Fiend kills a target, he stores the unfortunate soul inside of him. For each stored soul he gains 2 bonus damage until his own death releases half of them from bondage.

Level 1 - 16 damage limit.
Level 2 - 30 damage limit.
Level 3 - 46 damage limit.
Level 4 - 60 damage limit.

Passive

Note: The souls (black projectile) must reach the hero in before providing its bonus damage.

Screenshot:

Code:
JASS:

scope Necromastery initializer SetUp // requires Timer32

globals
    private integer array DAMAGEID[4]
endglobals

//===========================================================================
//                           CONFIGURABLES                        
//===========================================================================

globals
    private constant integer ABILID = 'ABNe' // raw code of ability "Necromastery"
    public constant integer DUMABILID = 'ANe0' // raw code of ability "Necromastery (Display)"
    private constant integer DUMMYID = 'nECD' // raw code of unit "Necromastery Dummy"
    private constant integer PRELOADID = 'prel' // raw code of unit "Preloader"
    
    private constant integer DAMAGE = 2 // damage bonus per soul
    
    private constant real COL = 50.0 // collision size of the soul
    private constant real SPEED = 500.0 // distance traveled by the soul per second
    private constant real TRUESPEED = SPEED * T32_PERIOD // distance traveled by the soul per period
    private constant string DEATHART = "Abilities\\Weapons\\AvengerMissile\\AvengerMissile.mdl" // death art used upon soul expiration
    private constant string DEATHARTPOINT = "chest" // attachment point of DEATHART
endglobals

private function SetUp takes nothing returns nothing
    local integer i = 0
    local unit u = CreateUnit(Player(13), PRELOADID, 0, 0, 0)

    set DAMAGEID[0] = 'dmg0' // raw code of ability "Damage (10000's) (Necromastery)"
    set DAMAGEID[1] = 'dmg1' // raw code of ability "Damage (1000's) (Necromastery)"
    set DAMAGEID[2] = 'dmg2' // raw code of ability "Damage (100's) (Necromastery)"
    set DAMAGEID[3] = 'dmg3' // raw code of ability "Damage (10's) (Necromastery)"
    set DAMAGEID[4] = 'dmg4' // raw code of ability "Damage (1's) (Necromastery)"
    
    //preload
    loop
        exitwhen i > 4
        call UnitAddAbility(u, DAMAGEID<i>)
        set i = i + 1
    endloop
    call UnitAddAbility(u, DUMABILID)
    call RemoveUnit(CreateUnit(Player(13), DUMMYID, 0, 0, 0))
    call RemoveUnit(u)
    set u = null
endfunction

private function GetMaxSoul takes integer level returns integer // maximum number of souls
    if level == 1 then
        return 8
    elseif level == 2 then
        return 15
    elseif level == 3 then
        return 23
    elseif level == 4 then
        return 30
    endif
    return 0
endfunction

private function GetSoulLost takes integer level returns real
    return 0.50 // amount of souls lost on death, where 1.0 = 100%
endfunction

//===========================================================================
//                          END CONFIGURABLES                        
//===========================================================================

private struct Data
    unit killer
    unit dummy

    private static method setDamage takes unit u returns nothing
        local integer damage = DAMAGE * (GetUnitAbilityLevel(u, DUMABILID) - 1)
        local integer factor = 10000
        local integer level
        local integer i = 0
        
        loop
            exitwhen i &gt; 4
            set level = damage / factor
            call SetUnitAbilityLevel(u, DAMAGEID<i>, level + 1)
            set damage = damage - (level * factor)
            set factor = factor / 10
            set i = i + 1
        endloop
    endmethod
    
    private method periodic takes nothing returns nothing
        local integer level
        local real x = GetUnitX(this.dummy)
        local real y = GetUnitY(this.dummy)
        local real dx = GetUnitX(this.killer) - x
        local real dy = GetUnitY(this.killer) - y
        local real a
        local real height
        local real dist = SquareRoot(dx * dx + dy * dy)
        
        if dist &lt;= 50.0 then
            set level = GetUnitAbilityLevel(this.killer, DUMABILID)
            if level &lt; GetMaxSoul(GetUnitAbilityLevel(this.killer, ABILID)) + 1 then
                call UnitRemoveAbility(this.killer, DUMABILID)
                call UnitAddAbility(this.killer, DUMABILID)
                call SetUnitAbilityLevel(this.killer, DUMABILID, level + 1)
                call setDamage(this.killer)
            endif
            call DestroyEffect(AddSpecialEffectTarget(DEATHART, this.killer, DEATHARTPOINT))
            call RemoveUnit(this.dummy)
            call this.stopPeriodic()
            call this.deallocate()
        else
            set a = Atan2(dy, dx)
            call SetUnitX(this.dummy, x + TRUESPEED * Cos(a))
            call SetUnitY(this.dummy, y + TRUESPEED * Sin(a))
            set height = GetUnitFlyHeight(this.dummy)
            call SetUnitFlyHeight(this.dummy, height + ((GetUnitFlyHeight(this.killer) + 100) - height) / (dist / TRUESPEED), 0)
        endif
    endmethod
    implement T32x

    private static method actions takes nothing returns boolean
        local thistype this
        local unit u = GetTriggerUnit()
        local unit killer = GetKillingUnit()
        local integer ulevel = GetUnitAbilityLevel(u, ABILID)
        local integer klevel = GetUnitAbilityLevel(killer, ABILID)
        local integer i
        local real x
        local real y
        
        if ulevel &gt; 0 then
            set i = R2I((GetUnitAbilityLevel(u, DUMABILID) - 1) * GetSoulLost(ulevel))
            call UnitRemoveAbility(u, DUMABILID)
            call UnitAddAbility(u, DUMABILID)
            call SetUnitAbilityLevel(u, DUMABILID, i + 1)
            call thistype.setDamage(u)
        elseif klevel &gt; 0 then
            set this = this.allocate()
            set x = GetUnitX(u)
            set y = GetUnitY(u)
            set this.killer = killer
            set this.dummy = CreateUnit(Player(13), DUMMYID, x, y, Atan2(GetUnitY(this.killer) - y, GetUnitX(this.killer) - x) * bj_RADTODEG)
            
            call this.startPeriodic()
        endif
        set u = null
        set killer = null
        return false
    endmethod

    private static method learn takes nothing returns boolean
        local unit u = GetTriggerUnit()
        local integer i
        
        if GetLearnedSkill() == ABILID and GetUnitAbilityLevel(u, DUMABILID) == 0 then
            call UnitAddAbility(u, DUMABILID)
            
            set i = 0
            loop
                exitwhen i &gt; 4
                call UnitAddAbility(u, DAMAGEID<i>)
                set i = i + 1
            endloop
        endif
        set u = null
        return false
    endmethod
    
    private static method onInit takes nothing returns nothing
        local trigger t = CreateTrigger()
        
        call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_DEATH)
        call TriggerAddCondition(t, Condition(function thistype.actions))
        set t = null
        
        set t = CreateTrigger()
        call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_HERO_SKILL)
        call TriggerAddCondition(t, Condition(function thistype.learn))
        set t = null
    endmethod
endstruct

endscope
</i></i></i>




Presence of the Dark Lord

Description:
The presence of such a horrible creature terrifies nearby enemies, reducing their armor.

Level 1 - 2 armor reduction.
Level 2 - 3 armor reduction.
Level 3 - 4 armor reduction.
Level 4 - 5 armor reduction.

Passive

Screenshot:


Requiem of Souls

Description:
Summons evil spirits around you dealing damage to units in the area. Number of spirits is related to the number of souls stored and the movement/damage reduction is related to the distance from the Shadow Fiend. Lowers movement speed and damage of nearby units. The closer the units are the greater the effect. Reduction lasts 5 seconds.

Level 1 - 80 damage for each line, 15% reduction.
Level 2 - 120 damage for each line, 20% reduction.
Level 3 - 160 damage for each line, 25% reduction.

Cast Range: Self
Target Type: Instant
Cast Time: 1 second
Cooldown: 120/110/100 seconds

Note: I believe DoTA actually uses multiple carrion swarms for Requiem of Souls. However, for configuration purposes and better visual effects, I did not.

Screenshot:

Code:
JASS:

scope RequiemOfSouls // requires Timer32, GroupUtils

//===========================================================================
//                           CONFIGURABLES                        
//===========================================================================

globals
    private constant integer ABILID = 'ABRS' // raw code of ability &quot;Requiem of Souls&quot;
    private constant integer DUMABILID = 'ARS0' // raw code of ability &quot;Requiem of Souls (Reduction)&quot;
    private constant integer DUMMYID = 'rOSD' // raw code of unit &quot;Requiem of Souls Dummy&quot;
    private constant integer CASTERID = 'cAST' // raw code of unit &quot;Caster Dummy&quot;
    
    private constant integer SOULCOUNT = 2 // number of souls required to create a &quot;line&quot;
    private constant real SOULAOE = 150.0 // area of effect of each &quot;line&quot;
    private constant real SPEED = 1000.0 // distance travelled by &quot;line&quot; per second
    private constant real TRUESPEED = SPEED * T32_PERIOD // distance travelled by &quot;line&quot; per period
    
    private constant real REDUCTIONAOE = 675.0 // area of effect where units will be affected by damage and move speed reduction
    
    private constant real INTERVAL = 200.0 // distance interval where effect is spawned
    private constant string EFFECT = &quot;Objects\\Spawnmodels\\Undead\\UndeadDissipate\\UndeadDissipate.mdl&quot; // effect spawned every interval
    
    private constant attacktype ATK = ATTACK_TYPE_NORMAL // attack type of damage
    private constant damagetype DMG = DAMAGE_TYPE_MAGIC // damage type of damage
    private constant weapontype WEP = WEAPON_TYPE_WHOKNOWS // weapon type of damage
endglobals

private function GetDamage takes integer level returns real
    return 40.0 + (40.0 * level) // damage dealt per line of soul
endfunction

private function GetArea takes integer level returns real
    return 1350.0 + (25.0 * level) // area of effect
endfunction

//===========================================================================
//                          END CONFIGURABLES                        
//===========================================================================

native UnitAlive takes unit id returns boolean

private struct Data
    unit caster
    unit dummy
    group damagedgroup
    real damage
    real dist
    real angle
    real interval = INTERVAL
    static thistype tempData
    static unit tempUnit
    
    private static method reductionFilter takes nothing returns boolean
        local unit u = GetFilterUnit()
        
        if IsUnitEnemy(u, GetOwningPlayer(tempUnit)) and UnitAlive(u) and not IsUnitType(u, UNIT_TYPE_STRUCTURE) then
            call IssueTargetOrder(tempUnit, &quot;cripple&quot;, u)
        endif
        set u = null
        return false
    endmethod
    
    private static method filterFunc takes nothing returns boolean
        local thistype this = tempData
        local unit u = GetFilterUnit()
        
        if IsUnitEnemy(u, GetOwningPlayer(this.caster)) and UnitAlive(u) and not IsUnitInGroup(u, this.damagedgroup) and not IsUnitType(u, UNIT_TYPE_STRUCTURE) then
            call UnitDamageTarget(this.caster, u, this.damage, true, false, ATK, DMG, WEP)
            call GroupAddUnit(this.damagedgroup, u)
        endif
        set u = null
        return false
    endmethod
    
    private method periodic takes nothing returns nothing
        local real x = GetUnitX(this.dummy)
        local real y = GetUnitY(this.dummy)
        
        if this.dist &lt;= 0 then
            call DestroyEffect(AddSpecialEffect(EFFECT, x, y))
            call RemoveUnit(this.dummy)
            call ReleaseGroup(this.damagedgroup)
            call this.stopPeriodic()
            call this.deallocate()
        else
            if this.interval &lt;= 0 then
                call DestroyEffect(AddSpecialEffect(EFFECT, x, y))
                set this.interval = INTERVAL
            else
                set this.interval = this.interval - TRUESPEED
            endif
            call SetUnitPosition(this.dummy, x + TRUESPEED * Cos(this.angle), y + TRUESPEED * Sin(this.angle))
            set tempData = this
            call GroupEnumUnitsInArea(ENUM_GROUP, x, y, SOULAOE, Filter(function thistype.filterFunc))
            set this.dist = this.dist - TRUESPEED
        endif
    endmethod
    implement T32x
    
    private static method actions takes nothing returns boolean
        local thistype this
        local unit u
        local integer level
        local integer i
        local real angle
        local real anglerate
        local real x
        local real y
    
        if GetSpellAbilityId() == ABILID then
            set u = GetTriggerUnit()
            set level = GetUnitAbilityLevel(u, ABILID)
            set i = (GetUnitAbilityLevel(u, Necromastery_DUMABILID) - 1) / SOULCOUNT
            set angle = 0
            if i != 0 then
                set anglerate = (2 * bj_PI) / i
            endif
            set x = GetUnitX(u)
            set y = GetUnitY(u)
            
            loop
                exitwhen i == 0
                set this = thistype.allocate()
                set this.caster = u
                set this.damagedgroup = NewGroup()
                set this.damage = GetDamage(level)
                set this.dist = GetArea(level)
                set this.angle = angle
                set this.dummy = CreateUnit(GetOwningPlayer(this.caster), DUMMYID, x, y, angle)
                
                call this.startPeriodic()
                set angle = angle + anglerate
                set i = i - 1
            endloop
            
            set tempUnit = CreateUnit(GetOwningPlayer(u), CASTERID, x, y, 0)
            call UnitAddAbility(tempUnit, DUMABILID)
            call SetUnitAbilityLevel(tempUnit, DUMABILID, level)
            call GroupEnumUnitsInArea(ENUM_GROUP, x, y, REDUCTIONAOE, Filter(function thistype.reductionFilter))
            call RemoveUnit(tempUnit)
        endif
        set u = null
        return false
    endmethod

    private static method onInit takes nothing returns nothing
        local trigger t = CreateTrigger()
        
        call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SPELL_EFFECT)
        call TriggerAddCondition(t, Condition(function thistype.actions))
        set t = null
    endmethod
endstruct

endscope


Credits
Code:
Jesus4Lyf - [URL="http://www.thehelper.net/forums/showthread.php/132538-Timer32?highlight=Timer32"]Timer32[/URL]
Rising_Dusk - [URL="http://www.wc3c.net/showthread.php?t=104464"]GroupUtils[/URL]

Changelogs
Code:
Version 1.0
- Initial relase
Version 1.1
- Optimized code
- Made Attack Type, Weapon Type and Damage Type configurable for Shadowraze and Requiem of Souls
Version 1.2
- Rewrote codes using Timer32 and GroupUtils, instead of KT2 and Recycle
Feedback will be appreciated.
 

Attachments

BlackRose

Forum User
Shadowraze
  • I like how you name the variables relative to their hotkey in DotA. It's easy for people to modify.
  1. In the Learn function, variable u should be set after the if GetLearnedSkill() == ABILID then. Why? Incase the learned skill was not ABILID, then you save one GetTriggerUnit call.
  2. In the Actions function, variable a can be set as a = GetUnitFacing( u ) * bj_DEGTORAD to save one multiplication.
  3. In the GroupFunc function, you should make the attacktype, damagetype, and weapontypes configurable at the top.
 

Ayanami

칼리
Shadowraze
  • I like how you name the variables relative to their hotkey in DotA. It's easy for people to modify.
  1. In the Learn function, variable u should be set after the if GetLearnedSkill() == ABILID then. Why? Incase the learned skill was not ABILID, then you save one GetTriggerUnit call.
  2. In the Actions function, variable a can be set as a = GetUnitFacing( u ) * bj_DEGTORAD to save one multiplication.
  3. In the GroupFunc function, you should make the attacktype, damagetype, and weapontypes configurable at the top.
Thanks for the feedback. Will make the necessary changes.

EDIT
Done.
 

BlackRose

Forum User
Doesn't DotA use purge for Requiem of Souls?

(By the way, it's DotA: Defence of the Ancients, not DoTA: Defence of The Ancients.)
 

BlackRose

Forum User
I was wrong, I checked myself, it's all Cripple. Thinking from memory, I thought it used Purge :p

Does your Requiem of Souls follow this though: The closer the units are the greater the effect.? The Cripple that is, I noticed DotA uses three Cripple abilities: "Far", "Moderate", and "Close".
 

Ayanami

칼리
I was wrong, I checked myself, it's all Cripple. Thinking from memory, I thought it used Purge :p

Does your Requiem of Souls follow this though: The closer the units are the greater the effect.? The Cripple that is, I noticed DotA uses three Cripple abilities: "Far", "Moderate", and "Close".
Well, nope. I guess I should do that though. Lol.
 

Ayanami

칼리
Updated to version 1.2

Code:
[B]Version 1.2[/B]
- Rewrote codes using Timer32 and GroupUtils, instead of KT2 and Recycle
 

Sevion

The DIY Ninja
Weird. I thought I posted this yesterday. Anyways. I think Recycle would be a better system to use than GroupUtils. Less overhead.
 

chobibo

Level 1 Crypt Lord
Weird. I thought I posted this yesterday. Anyways. I think Recycle would be a better system to use than GroupUtils. Less overhead.
You did. Dunno why it's not there anymore though.
 

tooltiperror

Super Moderator
Why are you even using groups? I thought dynamic groups were considered bad now.

>It is MUI, meaning can be cast many times at the same instance
8190 to be precise.

>function GetMaxSoul
That could be [LJASS]I2R(R2I(- 0.333 * level * level * level + 2.5 * level * level + 1.75 * level + 4.083))[/LJASS] and comment in the values. The I2R/R2I should round it up (untested).
 

tooltiperror

Super Moderator
GetMaxSoul change would probably slow down for more than it's worth.

Approved.
 

super_nova

Member
Excuse me, i want to ask some question
I'm trying to copy the necromastery skill you made here, and modify its name
But it doesnt work and error when i save it to my map, i did what you said to copy step by step...
Can you help me?
lorokabeh.jpg
I dont know how to upload a picture, so i just attach it..
 
General chit-chat
Help Users
  • No one is chatting at the moment.
  • jonas jonas:
    cool! do you have a video?
  • tom_mai78101 tom_mai78101:
    I have a GIF though
  • tom_mai78101 tom_mai78101:
    In the GIF, I've configured it so the lower the "Main Value" is, the better. I had to compress it pretty far down though.
  • tom_mai78101 tom_mai78101:
    And this is the thread with the video that shows the wall clip. https://tasvideos.org/Forum/Topics/23453
    +2
  • tom_mai78101 tom_mai78101:
    Hmm, about the Headline News, I noticed threads are being moved into the subforum (Health News, Environmental News, etc.). When that happens, the TH Forum Home page loses the articles, and instead would show old articles posted 1 or 2 weeks ago.
  • tom_mai78101 tom_mai78101:
    What do we do with the Home page?
  • Ghan Ghan:
    I added those forums to the filter for that widget.
  • tom_mai78101 tom_mai78101:
    Oh nice. They're back. Thanks.
  • tom_mai78101 tom_mai78101:
    Now I think it makes more sense for me to put news in their own subforums, without worry.
  • The Helper The Helper:
    Awesome Ghan thanks! I was purposely not moving the first 15 news articles in Headline news to the different subforums but I guess I don't have to do that now?
  • tom_mai78101 tom_mai78101:
    Question: Is there a way to remove thread redirects? It creates a copy of the moved thread and takes up space, and I am leaning towards wanting to remove them in the Headline News. But if they have an expiration date, I guess I'm fine with it.
  • The Helper The Helper:
    If you move a thread please leave a permanent redirect. You can delete any redirects after 6 months. The redirects are left to help Search Engines find the moved content.
  • tom_mai78101 tom_mai78101:
    What if you move the permanent redirect, not the thread?
  • The Helper The Helper:
    I think that works but I have not messed with it. You can delete redirects though if you have to that will not delete the original thread
  • The Helper The Helper:
    if a redirect ends up in the same forum as the post it goes to though I think the redirect drops or fails or something but they are not bugged out and when you are working on an indirect the original post is safe.
  • The Helper The Helper:
    Happy Early Friday :)
    +1
  • V-SNES V-SNES:
    Happy Friday :)
  • tom_mai78101 tom_mai78101:
    Fun Friday for me
  • tom_mai78101 tom_mai78101:
    Happy Fun Friday to all.
    +2
  • The Helper The Helper:
    Happy Sunday everyone!!!
  • V-SNES V-SNES:
    Happy Sunday!!!
    +1
  • jonas jonas:
    Happy monday :p
  • jonas jonas:
    Everyone hates mondays?
    +1
  • The Helper The Helper:
    Happy Tuesday!

    Staff online

    Members online

    Affiliates

    Hive Workshop NUON Dome World Editor Tutorials

    Network Sponsors

    Apex Steel Pipe - Buys and sells Steel Pipe.
    Top