HomeUser Control Panel (unavailable in archive)ForumsTutorialsArt GalleryResourcesMaps

Struct based Orb System

02-10-2008, 02:33 PM#1
Themerion
Hello!

I've implemented grim's DamageDetection system for my map, and now I've been trying to extend to support orb-effects (or, onDamage effects for all units). I'd love to get some feedback on it!

The advantage of my approach is that it doesn't use ExecuteFunc or ExecuteTrigger, since it's based on vJass and structs. Adding and removing damage effects are simplified to the functions:
Collapse JASS:
function UnitAddOrbEffect(unit,orbeffect)
function UnitRemoveOrbEffect(unit,orbeffect)

Creating orb effects are done in this way:

Collapse JASS:
globals
    orbeffect Orb_LifeSteal

    private constant real LIFESTEAL_EFFECT=0.1
endglobals

struct OrbEffect_LifeSteal extends orbeffect
    public method action takes unit source, unit target, real dmg returns nothing
        call DestroyEffectTimed(AddSpecialEffectTarget("Abilities\\Spells\\Undead\\VampiricAura\\VampiricAuraTarget.mdl",source,"origin"),3.0)
        call SetWidgetLife(source,LIFESTEAL_EFFECT*dmg+GetWidgetLife(source))
    endmethod
endstruct

function InitOrbs takes nothing returns nothing
    set Orb_LifeSteal=OrbEffect_LifeSteal.create()
endfunction

And this is the core of the system:

Collapse JASS:
library Orbs needs DamageDetection, Lists

interface orbeffect
    public method action takes unit source, unit target, real dmg returns nothing defaults nothing
endinterface

function RunEffects takes unit source, unit target, real dmg, list l returns nothing
    local listnode ln=l.first
    local orbeffect oe
    loop
        exitwhen ln==0
        set oe=ln.value
        call oe.action(source,target,dmg)
        set ln=ln.next
    endloop
endfunction

// Each unit set up for damage detection has a DamageDetection struct associated with it!
// I've "subclassed" DamageDetection with my GenericDD

struct GenericDD extends DamageDetection

 boolean orb
 list orblist
 
// When a unit damages another unit,
// the damage system runs this function.
// .u is the unit dealing the damage
 method onDamage takes unit target, real dmg returns nothing
    if .orb then
        call RunEffects(.u,target,dmg,.orblist)
    endif
 endmethod

 method onDamaged takes unit damager, real dmg returns nothing
 endmethod

 method onSpellDamage takes unit target, real dmg returns nothing
 endmethod
 
 method onSpellDamaged takes unit damager, real dmg returns nothing
 endmethod
 
 method onDestroy takes nothing returns nothing
    if .orblist!=0 then
        call .orblist.destroy()
    endif
 endmethod
endstruct

function UnitAddOrbEffect takes unit u, orbeffect oe returns nothing
// This is the data struct associated with the unit.
    local GenericDD dd=unitdata[GetUnitIndex(u)]
    if dd.orblist==0 then
        set dd.orblist=list.create()
    endif
    call dd.orblist.add(oe)
    set dd.orb=true
endfunction

function UnitRemoveOrbEffect takes unit u, orbeffect oe returns nothing
// This is the data struct associated with the unit.
    local GenericDD dd=unitdata[GetUnitIndex(u)]

    debug if dd.orblist==0 then
    debug call BJDebugMsg("Trying to remove orb effects from non-existant list")
    debug return
    debug endif
    
    call dd.orblist.remove(oe)
endfunction

endlibrary
02-10-2008, 09:02 PM#2
grim001
Looks like a good use of the system, but it seems more sensible to add generic damage events to the system rather than using a generic struct. After all, the only purpose of the struct is to allow unique events for each unit, and here they're identical.

Only other comment is that the that the structure of the code could probably be improved, but it should work fine as-is, and performance won't become an issue unless this were used in a map with hundreds of constantly attacking units.
02-11-2008, 11:37 AM#3
Themerion
Quote:
Originally Posted by grim001
... it seems more sensible to add generic damage events to the system rather than using a generic struct. After all, the only purpose of the struct is to allow unique events for each unit, and here they're identical.

Yeah... I could skip GenericDD and associate the units directly with the lists containing the orb data (which is the for-each unit unique data). I didn't really want to modify your system, but you are of course right. Using only 1 subclass is sort of waste.

Quote:
Only other comment is that the that the structure of the code could probably be improved, but it should work fine as-is, and performance won't become an issue unless this were used in a map with hundreds of constantly attacking units.

But there are improvements to be made? :)