| 02-18-2013, 01:58 AM | #1 | |
Background: When making some spells for my map, I discovered that I needed to create my own lightning, I looked around wc3c but couldn't find any released resources. I made my own one which just connected lightning between units as I didn't really need anything else. I then looked deeper in wc3c and found Kueken's abandoned AdvLightning thread. I liked the idea of making a proper library to deal with lightning so I did. Then Anitarf bullied me until I made it use struct syntax. And here we are. Requirements:
Credits:
Code: Library:library Lightning requires optional ARGB //****************************************************************************** //* Author: Fledermaus //* Version: 1.02 //* //* This library is intended to replace the native lightning type. //* It uses a Lightning struct to provide better functionality (and a nicer //* syntax if you're that way inclined). //* //****************************************************************************** //* //* Configuration constants that you can alter however you like: //* //* TIMEOUT is the timer speed for updating the position of lightning and //* the alpha for fading in/out. //* //****************************************************************************** //* //* List of methods: //* //* static method create takes string codeName, boolean checkVisibility, real fadeTime returns Lightning //* //* Creates a new Lightning for you to use. //* - codeName: Determines what the Lightning looks like. I'm even so nice as //* to include a constant list of them in the global constant section for //* you! //* - checkVisibility: As with normal lightning, this determines if a player //* needs to have vision of the Lightning (start or end point/unit) in //* order to see it. If set to true, the Lightning becomes invisible when //* players lose vision of it. //* - fadeTime: Makes the Lightning fade into existence. A value of 0 is an //* instant fade in. //* Note that it wont initially be attached to anything, that's where the next //* two methods come in: //* //* //* method attachToPoint takes boolean atStart, real x, real y, real z, boolean considerTerrain returns boolean //* method attachToUnit takes boolean atStart, unit u, real zOffset returns boolean //* //* They should be pretty self-explanatory, they attach the Lightning to either //* the startPoint or startUnit, or the endPoint or endUnit. //* The two constants LIGHTNING_START and LIGHTNING_END can be used here to //* help make your code easier to read. //* Lightning attached to a unit(s) will follow it around. //* The boolean considerTerrain in attachToPoint determines if the z value is //* measured from the terrain or an absolute value. //* If you don't attach to both a start and end point/unit, the Lightning will //* connect to 0, 0. So you should attach to both as soon as it's created. //* //* //* method recolor takes real r, real g, real b, real a returns boolean //* method ARGBrecolor takes ARGB color returns nothing //* method operator color= takes ARGB color returns nothing //* //* Used to set the colour of Lightning. Should only use values between 0.00 //* and 1.00. //* ARGBrecolor and color= will obviously only work if you have ARGB. //* //* //* method operator red takes nothing returns real //* method operator green takes nothing returns real //* method operator blue takes nothing returns real //* method operator alpha takes nothing returns real //* method operator color takes nothing returns ARGB //* //* Method operators to get the colour components of the Lightning. Pretty //* self explanatory. //* Again, color will only work if you have ARGB. //* //* //* method destroy takes nothing returns nothing //* method release takes real fadeTime returns nothing //* method releaseDelayed takes real delay, real fadeTime returns nothing //* //* Again, pretty self explanatory. destroy will dispose of a Lightning //* instantly, while release will fade it out over time. releaseDelayed lets //* you release it after a delay. //* //****************************************************************************** //* //* There is the inherent limit that you can only have 8191 Lightning at once. //* However, if you ever get this high, your map will have worse problems than //* this system working improperly. //* //****************************************************************************** //* //* Credits: Thanks to Vexorian for ARGB and vJass. Kueken for the work he //* previously did which helped me create this library. Anitarf for //* motivating me to update it and helping me with some of the //* ideas. Oh and Dusk for being sexy ;) //* //* If you have any further questions regarding Lightning or how to use it, //* feel free to visit [url]www.wc3c.net[/url] and ask questions there. This library should //* only ever be released at WC3C and at no other site. Please give credits if //* this library finds its way into your maps, and otherwise thanks for reading! //* globals private constant real TIMEOUT = 0.03125 //32 fps //* Do not edit below here //Lightning type constants constant string LIGHTNING_AERIAL_SHACKLES = "LEAS" constant string LIGHTNING_CHAIN_LIGHTNING_PRIMARY = "CLPB" constant string LIGHTNING_CHAIN_LIGHTNING_SECONDARY = "CLSB" constant string LIGHTNING_DRAIN_LIFE = "DRAL" constant string LIGHTNING_DRAIN_LIFE_AND_MANA = "DRAB" constant string LIGHTNING_DRAIN_MANA = "DRAM" constant string LIGHTNING_FINGER_OF_DEATH = "AFOD" constant string LIGHTNING_FORKED_LIGHTNING = "FORK" constant string LIGHTNING_HEALING_WAVE_PRIMARY = "HWPB" constant string LIGHTNING_HEALING_WAVE_SECONDARY = "HWSB" constant string LIGHTNING_LIGHTNING_ATTACK = "CHIM" constant string LIGHTNING_MANA_BURN = "MBUR" constant string LIGHTNING_MANA_FLARE = "MFPB" constant string LIGHTNING_SPIRIT_LINK = "SPLK" constant boolean LIGHTNING_START = true constant boolean LIGHTNING_END = false private location Loc = Location(0., 0.) private Lightning array Array private integer Index = 0 private timer Timer = CreateTimer() endglobals //! textmacro LightningDebugTextmacro takes TYPE, RETURN if .released then debug call BJDebugMsg(SCOPE_PREFIX + " Error: Trying to $TYPE$ a lightning that is fading out of existance") return $RETURN$ endif //! endtextmacro //! textmacro LightningRecolourDebugTextmacro takes VARIABLE, COLOUR if $VARIABLE$ < 0. then debug call BJDebugMsg(SCOPE_PREFIX + " Error: $COLOUR$ value passed to recolor is less than 0.") set $VARIABLE$ = 0. elseif $VARIABLE$ > 1. then debug call BJDebugMsg(SCOPE_PREFIX + " Error: $COLOUR$ value passed to recolor is greater than 1.") set $VARIABLE$ = 1. endif //! endtextmacro //****************************************************************************** struct Lightning private lightning lightning private boolean checkVisibility private boolean updatePosition private boolean released private boolean canSee private boolean startSet private boolean endSet private unit startUnit private unit endUnit private real startX private real startY private real startZ private real startZOffset private real endX private real endY private real endZ private real endZOffset private real redColour private real greenColour private real blueColour private real alphaColour private real fadingAlpha private real fadingAlphaInc private real releaseDelay private static method Update takes nothing returns nothing local integer i = 0 local real a local Lightning l loop exitwhen i >= Index set l = Array[i] if l.updatePosition then //Update the lightning's position if it's attached to a unit if l.startUnit != null and GetUnitTypeId(l.startUnit) != 0 then set l.startX = GetUnitX(l.startUnit) set l.startY = GetUnitY(l.startUnit) call MoveLocation(Loc, l.startX, l.startY) set l.startZ = GetLocationZ(Loc) + GetUnitFlyHeight(l.startUnit) + l.startZOffset endif if l.endUnit != null and GetUnitTypeId(l.endUnit) != 0 then set l.endX = GetUnitX(l.endUnit) set l.endY = GetUnitY(l.endUnit) call MoveLocation(Loc, l.endX, l.endY) set l.endZ = GetLocationZ(Loc) + GetUnitFlyHeight(l.endUnit) + l.endZOffset endif //Check if the lightning can be seen (will locally change the variable for each player) set l.canSee = MoveLightningEx(l.lightning, l.checkVisibility, l.startX, l.startY, l.startZ, l.endX, l.endY, l.endZ) if l.canSee then //If it can be seen, make sure you change the alpha back to l.alpha //because this could have been the first time it's visiable again set a = l.alphaColour else //Otherwise make the alpha 0 so it's invisiable set a = 0. endif //Check if the lightning has been delay released if l.releaseDelay > 0. and not l.released then //Count down the delay set l.releaseDelay = l.releaseDelay - TIMEOUT if l.releaseDelay <= 0. then //Time to release it set l.released = true if l.fadingAlphaInc < 1. then //Increase the fadingAlpha by fadingAlphaInc to account for this cycle set l.fadingAlpha = 1. + l.fadingAlphaInc else //If the fade time from the delayed release was 0., release it instantly set l.fadingAlpha = 0. endif endif endif if l.released then if l.fadingAlpha > 0. then //Lightning is still fading out set l.fadingAlpha = l.fadingAlpha - l.fadingAlphaInc if l.fadingAlpha < 0. then set l.fadingAlpha = 0. endif set a = a * l.fadingAlpha else //Lightning has finished fading out and should be destroyed call DestroyLightning(l.lightning) set l.lightning = null set l.startUnit = null set l.endUnit = null call l.deallocate() set Index = Index - 1 if Index > 0 then set Array[i] = Array[Index] set i = i - 1 else call PauseTimer(Timer) endif endif elseif l.fadingAlpha < 1. then //Lightning is fading in set l.fadingAlpha = l.fadingAlpha + l.fadingAlphaInc if l.fadingAlpha >= 1. then set l.fadingAlpha = 1. //Check if we need to keep updating the lightning set l.updatePosition = l.checkVisibility or l.startUnit != null or l.endUnit != null or l.releaseDelay > 0. if not l.updatePosition then set Index = Index - 1 if Index > 0 then set Array[i] = Array[Index] set i = i - 1 else call PauseTimer(Timer) endif endif endif set a = a * l.fadingAlpha endif //If the lightning still exists, update it's alpha value if l.lightning != null then call SetLightningColor(l.lightning, l.redColour, l.greenColour, l.blueColour, a) endif set i = i + 1 else set Index = Index - 1 if Index > 0 then set Array[i] = Array[Index] else call PauseTimer(Timer) endif endif endloop endmethod static method create takes string codeName, boolean checkVisibility, real fadeTime returns Lightning local Lightning this = Lightning.allocate() set .checkVisibility = checkVisibility set .updatePosition = checkVisibility or fadeTime > 0. set .released = false set .canSee = true //The lightning needs to first be create so that noone can see it but without checking that players //can see it (checkVisibitiy set to false and at (0, 0) (0, 0)) so that it will not be null for //players that cannot see it as it's created. It can then be moved to the correct location and have //the proper visibility setting. set .lightning = AddLightning(codeName, false, 0., 0., 0., 0.) set .redColour = GetLightningColorR(.lightning) set .greenColour = GetLightningColorG(.lightning) set .blueColour = GetLightningColorB(.lightning) set .alphaColour = GetLightningColorA(.lightning) set .startSet = false set .endSet = false set .releaseDelay = 0. if fadeTime > 0. then set .fadingAlpha = 0. set .fadingAlphaInc = TIMEOUT / fadeTime call SetLightningColor(.lightning, .redColour, .greenColour, .blueColour, 0.) else debug if fadeTime != 0. then debug call BJDebugMsg(SCOPE_PREFIX + " Error: Trying to create a lightning with a negative fade time") debug endif set .fadingAlpha = 1. endif if .updatePosition then if Index == 0 then call TimerStart(Timer, TIMEOUT, true, function Lightning.Update) endif set Array[Index] = this set Index = Index + 1 endif return this endmethod method attachToPoint takes boolean atStart, real x, real y, real z, boolean considerTerrain returns boolean //! runtextmacro LightningDebugTextmacro("change the attached point of", "false") call MoveLocation(Loc, x, y) if atStart then set .startUnit = null set .startX = x set .startY = y if considerTerrain then set .startZ = GetLocationZ(Loc) + z else set .startZ = z endif set .startSet = true else set .endUnit = null set .endX = x set .endY = y if considerTerrain then set .endZ = GetLocationZ(Loc) + z else set .endZ = z endif set .endSet = true endif if .startSet and .endSet then set .canSee = MoveLightningEx(.lightning, .checkVisibility, .startX, .startY, .startZ, .endX, .endY, .endZ) endif if .updatePosition and not .checkVisibility and .fadingAlpha == 1. and .startUnit == null and .endUnit == null and .releaseDelay <= 0. then set .updatePosition = false endif return true endmethod method attachToUnit takes boolean atStart, unit u, real zOffset returns boolean //! runtextmacro LightningDebugTextmacro("change the attached unit of", "false") if atStart then set .startUnit = u set .startZOffset = zOffset set .startSet = true if u != null then set .startX = GetUnitX(u) set .startY = GetUnitY(u) call MoveLocation(Loc, .startX, .startY) set .startZ = GetLocationZ(Loc) + GetUnitFlyHeight(u) + zOffset endif else set .endUnit = u set .endZOffset = zOffset set .endSet = true if u != null then set .endX = GetUnitX(u) set .endY = GetUnitY(u) call MoveLocation(Loc, .endX, .endY) set .endZ = GetLocationZ(Loc) + GetUnitFlyHeight(.endUnit) + zOffset endif endif if .startSet and .endSet then set .canSee = MoveLightningEx(.lightning, .checkVisibility, .startX, .startY, .startZ, .endX, .endY, .endZ) endif if .updatePosition == false then if Index == 0 then call TimerStart(Timer, TIMEOUT, true, function Lightning.Update) endif set Array[Index] = this set Index = Index + 1 set .updatePosition = true endif return true endmethod method operator red takes nothing returns real return .redColour endmethod method operator green takes nothing returns real return .greenColour endmethod method operator blue takes nothing returns real return .blueColour endmethod method operator alpha takes nothing returns real return .alphaColour endmethod method recolor takes real r, real g, real b, real a returns boolean //! runtextmacro LightningDebugTextmacro("recolor", "false") //! runtextmacro LightningRecolourDebugTextmacro("r", "red") //! runtextmacro LightningRecolourDebugTextmacro("g", "green") //! runtextmacro LightningRecolourDebugTextmacro("b", "blue") //! runtextmacro LightningRecolourDebugTextmacro("a", "alpha") set .redColour = r set .greenColour = g set .blueColour = b set .alphaColour = a if .canSee == false then set a = 0. endif return SetLightningColor(.lightning, r, g, b, a * .fadingAlpha) endmethod static if LIBRARY_ARGB then method ARGBrecolor takes ARGB color returns nothing local integer col = integer(color) local integer a local integer r local integer g local integer b local real alpha if col < 0 then set col = -(-col + 0x80000000) set a = 0x80 + col / 0x1000000 set col = col - (a - 0x80) * 0x1000000 else set a = col / 0x1000000 set col = col - a * 0x1000000 endif set r = col / 0x10000 set col = col - r * 0x10000 set g = col / 0x100 set b = col - g * 0x100 set .redColour = I2R(r) / 255. set .greenColour = I2R(g) / 255. set .blueColour = I2R(b) / 255. set .alphaColour = I2R(a) / 255. if .canSee then set alpha = .alphaColour else set alpha = 0. endif call SetLightningColor(.lightning, .redColour, .greenColour, .blueColour, alpha * .fadingAlpha) endmethod method operator color takes nothing returns ARGB return ARGB.create(R2I(.alphaColour * 255.), R2I(.redColour * 255.), R2I(.blueColour * 255.), R2I(.greenColour * 255.)) endmethod method operator color= takes ARGB color returns nothing call .ARGBrecolor(color) endmethod endif method release takes real fadeTime returns nothing //! runtextmacro LightningDebugTextmacro("release", "") if fadeTime < 0. then debug call BJDebugMsg(SCOPE_PREFIX + " Error: Trying to release a lightning with a negative fade time") set fadeTime = 0. endif set .released = true if fadeTime > 0. then set .fadingAlpha = 1. set .fadingAlphaInc = TIMEOUT / fadeTime //Add it to the Update Loop if it's not already in there if not .updatePosition then if Index == 0 then call TimerStart(Timer, TIMEOUT, true, function Lightning.Update) endif set Array[Index] = this set Index = Index + 1 set .updatePosition = true endif elseif .updatePosition then //It's already updating so just make it invisible now and it'll get cleaned up in the next loop set .fadingAlpha = 0. call SetLightningColor(.lightning, .redColour, .blueColour, .greenColour, 0.) else //It's not updating so it can be cleaned up now call DestroyLightning(.lightning) set .lightning = null set .startUnit = null set .endUnit = null call .deallocate() endif endmethod method destroy takes nothing returns nothing call .release(0.) endmethod method releaseDelayed takes real delay, real fadeTime returns nothing //! runtextmacro LightningDebugTextmacro("delayed release", "") if delay <= 0. then debug call BJDebugMsg(SCOPE_PREFIX + " Error: Trying to delayed release a lightning with a delay not greater than 0.") set delay = 0.01 endif if fadeTime < 0. then debug call BJDebugMsg(SCOPE_PREFIX + " Error: Trying to delayed release a lightning with a negative fade time") set fadeTime = 0. endif set .releaseDelay = delay if fadeTime > 0. then set .fadingAlphaInc = TIMEOUT / fadeTime else //Don't want to divide by 0! set .fadingAlphaInc = 1. endif //Add it to the Update Loop if it's not already in there if not .updatePosition then if Index == 0 then call TimerStart(Timer, TIMEOUT, true, function Lightning.Update) endif set Array[Index] = this set Index = Index + 1 set .updatePosition = true endif endmethod endstruct endlibrary
|
| 02-18-2013, 09:22 AM | #2 |
So, this already got approved once during the past year but then got lost in the crash, so let me approve it again. It's a neat library that adds very useful features to lightnings such as attaching them to units and updating their visibility. Good job. |
