• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

[Wurst] Lightning

Chaosy

Tutorial Reviewer
Level 40
Joined
Jun 9, 2011
Messages
13,183
A lightning library I am working on.

Features
  • lightning . extensions
  • enum representing all lightning types
  • Lightning class with bonus functionality
    • Getting lightning source and target location in either x/y or vec2
    • attaching between location to unit
    • attaching between unit to unit
wurstbin

Wurst:
package Lightning

import TimerUtils
import Table
import RegisterEvents

Table hash

enum LightningType
    CHAIN_LIGHTNING_PRIMARY
    CHAIN_LIGHTNING_SECONDARY
    DRAIN
    DRAIN_LIFE
    DRAIN_MANA
    FINGER_OF_DEATH
    FORKED_LIGHTNING
    HEALING_WAVE_PRIMARY
    HEALING_WAGVE_SECONDARY
    LIGHTNING_ATTACK
    MAGIC_LEASH
    MANA_BURN
    MANA_FLARE
    SPIRIT_LINK


function getLightningType(LightningType lt) returns string
    switch(lt)
        case CHAIN_LIGHTNING_PRIMARY
            return "CLPB"
        case CHAIN_LIGHTNING_SECONDARY
            return "CLSB"
        case DRAIN
            return "DRAB"
        case DRAIN_LIFE
            return "DRAL"
        case DRAIN_MANA
            return "DRAM"
        case FINGER_OF_DEATH
            return "AFOD"
        case FORKED_LIGHTNING
            return "FORK"
        case HEALING_WAVE_PRIMARY
            return "HWPB"
        case HEALING_WAGVE_SECONDARY
            return "HWSB"
        case LIGHTNING_ATTACK
            return "CHIM"
        case MAGIC_LEASH
            return "LEAS"
        case MANA_BURN
            return "MBUR"
        case MANA_FLARE
            return "MFPB"
        case SPIRIT_LINK
            return "SPLK"
        default
            return ""

function lightning.move(vec3 one, vec3 two)
    MoveLightningEx(this, true, one.x, one.y, one.z, two.x, two.y, two.z)

function lightning.move(vec2 one, vec2 two)
    MoveLightning(this, true, one.x, one.y, two.x, two.y)

function lightning.move(boolean vis, vec2 one, vec2 two)
    MoveLightning(this, vis, one.x, one.y, two.x, two.y)

function lightning.move(boolean vis, real x1, real y1, real x2, real y2)
    MoveLightning(this, vis, x1, y1, x2, y2)

function lightning.setColor(real r, real g, real b, real a)
    SetLightningColor(this, r, g, b, a)

function lightning.getColorR() returns real
    return GetLightningColorR(this)

function lightning.getColorG() returns real
    return GetLightningColorG(this)

function lightning.getColorB() returns real
    return GetLightningColorB(this)

function lightning.getColorA() returns real
    return GetLightningColorA(this)

function lightning.getColor() returns color
    integer r = R2I(this.getColorR())
    integer g = R2I(this.getColorG())
    integer b = R2I(this.getColorB())

    return color(r, g, b)

function lightning.Destroy()
    DestroyLightning(this)

public class Lightning
    lightning l
    LightningType sort
    LightningType defaultType = LightningType.DRAIN_LIFE
    boolean vis = true
    boolean attached = false

    timer attachTimer
    unit attachTarget
    unit attachSource

    real sx
    real sy
    real sz
    real tx
    real ty
    real tz

    vec2 source
    vec2 target

    construct(vec2 v1, vec2 v2)
        sort = defaultType
        l = AddLightning(getLightningType(sort), vis, v1.x, v1.y, v2.x, v2.y)

    construct(real x1, real x2, real y1, real y2)
        sort = defaultType
        savePos(x1, x2, y1, y2)
        l = AddLightning(getLightningType(sort), vis, x1, y1, x2, y2)

    construct(boolean show, vec2 v1, vec2 v2)
        sort = defaultType
        vis = show
        saveVec(v1, v2)
        l = AddLightning(getLightningType(sort), vis, v1.x, v1.y, v2.x, v2.y)

    construct(boolean show, real x1, real x2, real y1, real y2)
        sort = defaultType
        vis = show
        savePos(x1, x2, y1, y2)
        l = AddLightning(getLightningType(sort), vis, x1, y1, x2, y2)

    construct(LightningType lt,vec2 v1, vec2 v2)
        sort = lt
        saveVec(v1, v2)
        l = AddLightning(getLightningType(sort), vis, v1.x, v1.y, v2.x, v2.y)

    construct(LightningType lt, real x1, real x2, real y1, real y2)
        sort = lt
        savePos(x1, x2, y1, y2)
        l = AddLightning(getLightningType(sort), vis, x1, y1, x2, y2)

    function savePos(real x1, real x2, real y1, real y2)
        sx = x1
        sy = y1
        tx = x2
        ty = y2

    function saveVec(vec2 s, vec2 t)
        source = s
        target = t

    function getLightning() returns lightning
        return l

    function getType() returns LightningType
        return sort

    function move(real x1, real y1, real x2, real y2)
        l.move(vis, x1, y1, x2, y2)

    function getColor() returns color
        return l.getColor()

    function setColor(real r, real g, real b, real a)
        l.setColor(r, g, b, a)

    function getSource() returns vec2
        return source

    function getTarget() returns vec2
        return target

    function getSourceX() returns real
        return sx

    function getSourceY() returns real
        return sy

    function getTargetX() returns real
        return tx

    function getTargetY() returns real
        return ty

    function isAttached() returns boolean
        return attached

    function onAttachInit()
        attached = true
        attachTimer = getTimer()
        attachTimer.setData(this castTo int)

    function isUnitValid(unit u) returns boolean
        return u != null and u.isAlive()

    function attach(unit u1)
        if(isUnitValid(u1) == false)
            print("The unit you're trying to attach is equal to null")
            return
        else if(isAttached() == false)
            integer h = GetHandleId(u1)
            attachTarget = u1
            hash.saveBoolean(h, true)
            hash.saveInt(h, this castTo int)
            onAttachInit()
            TimerStart(attachTimer, 0.03, true, () -> begin
                Lightning instance = GetExpiredTimer().getData() castTo Lightning
                instance.l.move(instance.source, instance.attachTarget.getPos())
            end)

    function attach(unit u1, unit u2)
        if(isUnitValid(u1) == false and isUnitValid(u2) == false)
            print("The unit you're trying to attach is equal to null")
            return
        else if(isAttached() == false)
            integer h = GetHandleId(u1)
            attachSource = u1
            attachTarget = u2
            hash.saveBoolean(GetHandleId(u1), true)
            hash.saveInt(h, this castTo int)
            h = GetHandleId(u2)
            hash.saveBoolean(GetHandleId(u2), true)
            hash.saveInt(h, this castTo int)
            onAttachInit()
            TimerStart(attachTimer, 0.03, true, () -> begin
                Lightning instance = GetExpiredTimer().getData() castTo Lightning
                instance.l.move(instance.attachSource.getPos(), instance.attachTarget.getPos())
            end)

    function flushUnit(unit u)
        integer h = GetHandleId(u)
        hash.removeInt(h)
        hash.removeBoolean(h)

    function deAttach()
        attachTimer.release()
        boolean isAttached = attachTarget != null ? true : false
        flushUnit(attachSource)
        if(isAttached)
            flushUnit(attachTarget)

    ondestroy
        if isAttached()
            deAttach()
        l.Destroy()

function isUnitAttached(unit u) returns boolean
    return hash.loadBoolean(GetHandleId(u))

function onDeath()
    unit u = GetTriggerUnit()
    integer h = GetHandleId(u)
    destroy hash.loadInt(h) castTo Lightning

function onDeathFilter() returns boolean
    return isUnitAttached(GetTriggerUnit())

init
    hash = new Table()
    CreateTrigger()
    ..registerAnyUnitEvent(EVENT_PLAYER_UNIT_DEATH)
    ..addCondition(Condition(function onDeathFilter))
    ..addAction(function onDeath)
   

[/wurst][/hidden]

Demo:
Wurst:
unit u
unit u2

init
    u = CreateUnit(players[0], 'Hpal', 99, 99, 0)
    u2 = CreateUnit(players[0], 'hfoo', 0, 0, 0)
    TimerStart(CreateTimer(), 1, false, () -> begin
        vec2 v1 = vec2(0, 0)
        vec2 v2 = vec2(99, 99)
        new Lightning(v1, v2)
        ..attach(u, u2)
    end)
 

Attachments

  • WurstRunMap.w3x
    31 KB · Views: 85
Last edited:
Level 8
Joined
Jan 23, 2015
Messages
121
Hey, most of this your package were added in recent stdlib2 update as a new handle wrapper package. The rest of your code - the struct - is useful though I feel it need some perfection.
For example, I'd recommend you use HashMap instead of Table.
Well, anyway, it's nice to see another man into wurst, so, welcome home :)
 

Cokemonkey11

Spell Reviewer
Level 29
Joined
May 9, 2006
Messages
3,534
This looks pretty useful, maybe throw it in a PR for others to contribute to if you don't feel like finishing it up?

My feedback:

- move into standard library what is clearly meant for stdlib (helper fns, etc)
- [optional] consider changing the unit-attach and on-death behaviours to consume closures, to make them more generic, e.g.

```
let u = createUnit(...)
let v = createUnit(...)

new Lightning(
vec2(0., 0.),
vec2(512., 0.),
(lgt) -> lgt.move(u.getPos), v.getPos()),
() -> u.isAlive() and v.isAlive()
)
```
 
Top