• 🏆 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!

[JASS] life drain... LIGHTNING EFFECTS

Status
Not open for further replies.
Level 13
Joined
May 11, 2008
Messages
1,198
so...i was wondering how to make an ability pinning down a unit around an area. that wasn't hard to do. but now i'm wondering how to make a line from the point to the unit, an effect line. like with life drain(an example). how does the life drain effect work? it's listed among lightning effects...
i remember in dota they used a purple line for slark's chain with his pounce ability...but i don't know where to begin for duplicating something like that.
i already know how to use effects regularly somewhat. but i don't get this lightning effect stuff.
 
Level 15
Joined
Jul 6, 2009
Messages
889
http://www.playdota.com/forums/297032/trigger-descriptions/#Slark

It appears a lightning with codename "PONC" is created.

local lightning loc_lightning01=AddLightning("PONC",true,GetUnitX(loc_unit01),GetUnitY(loc_unit01),GetUnitX(loc_unit02),GetUnitY(loc_unit02))

The PONC lightning type is defined customly in some LightningData.slk thingy-ma-jig, but I can't seem to find the texture file it references.... war3mapImported\Pounce3.blp
 

Attachments

  • LightningData.rar
    829 bytes · Views: 52
Level 13
Joined
May 11, 2008
Messages
1,198
JASS:
local lightning loc_lightning01=AddLightning("PONC",true,GetUnitX(loc_unit01),GetUnitY(loc_unit01),GetUnitX(loc_unit02),GetUnitY(loc_unit02))

uhm...ljass didn't work, heh. the forum word wrapped it.

oh...so you just add the lightning that you need as a lightning variable...
i guess i didn't realize there were lightning variables.

hmm...i'm inclined to wonder, isn't the lightning that is the chain leash and not pounce?

EH...maybe not. those may just as well be shackles/fiery lasso since they are apparently used for aerial shackles. i looked at that one in war3viewer...meh

okay so whatever...i guess when you try to extract mpq every file is randomly assorted so you have to view each file one by one to find what you're looking for. and there's a lot of icons with that .blp extension...yucky trying to sort through all those. i assume you didn't find it because 1000 files is a bit much.

buttom manager v1.8.2 allows quick sorting through icons, but it doesn't view graphics unless they're square...i guess. anyway, finding the purple chain isn't a big deal i guess. i was mostly wondering how to do the link or line graphics stuff.
ok i think these would be the most useful lightning functions:
Code:
native MoveLightning takes lightning whichBolt, boolean checkVisibility, real x1, real y1, real x2, real y2 returns boolean
native SetLightningColor takes lightning whichBolt, real r, real g, real b, real a returns boolean
native DestroyLightning takes lightning whichBolt returns boolean
native AddLightning takes string codeName, boolean checkVisibility, real x1, real y1, real x2, real y2 returns lightning
HUH. I CAN'TGETIT TO WORK.

ok so i did a search in the spells section for a spell with lightnings

i went to the top for some reason looking for the "Lightning" and found rawcode...erhm...

so basically i was at first trying to use '' even though i knew it took a string, then i tried putting in "" but that didn't work either...you're supposed to input '' as "" i guess.
iow...since "ReplaceableTextures\\Weather\\DrainLightning.blp" doesn't do anything, i'm puzzled, since before that i tried 'DRAB' which doesn't compile. but apparently you need to input something like "DRAB".

http://www.hiveworkshop.com/forums/...5-a-125789/?prev=search=LIGHTNING&d=list&r=20

well, now i guess i know what string codeName means.

just tested, yup, works perfectly now. sweet.
 
Last edited:
Level 13
Joined
Jul 26, 2008
Messages
1,009
I want you to try this for your lightning name such as "DRAB"

They're actually strings like special effects. Replace "DRAB" or whatever, with:

JASS:
local integer abil = GetSpellAbilityId()

GetAbilityEffectById(abil,EFFECT_TYPE_LIGHTNING,0)

I know it's larger, but it allows you to manipulate the lightning effect directly in the object editor. So all you have to do is click the lightning you want right from the Lightning Effect field of the spell.

I also suggest doing this with your special effects. It just makes everything so much easier than looking up and typing in a path. I'm not sure why more spell coders don't do this. It allows you to easily fine-tune the graphics of your spells, and creating the same spell with different graphics is as easy as copy, paste, and change a few fields.

Hopefully you've got it down by example. Lightning has always been tricky for me. Sometimes I couldn't get it to destroy properly, but I've recently resolved that issue.

Here is an example of what I've done for a custom drain spell:

scope Drain initializer i

globals
private constant integer SPELLID = 'fren'
private constant real tick = 0.1
private constant attacktype atk = ATTACK_TYPE_PIERCE
private constant damagetype dmg = DAMAGE_TYPE_MAGIC
private constant weapontype wtype = WEAPON_TYPE_WHOKNOWS
endglobals

private struct Data
unit c
unit t
lightning lig
real dur
effect fx
timer tim

static method Timer takes nothing returns nothing
local thistype this = GetTimerData(.tim)
local real HDrain = GetWidgetLife(.c)/GetUnitState(.c, UNIT_STATE_MAX_LIFE)
local real lvl = GetUnitAbilityLevel(.c, SPELLID)
local real EHp = GetWidgetLife(.t)
local real dist = SquareRoot((GetUnitX(.t) - GetUnitX(.c)) * (GetUnitX(.t) - GetUnitX(.c)) + (GetUnitY(.t) - GetUnitY(.c)) * (GetUnitY(.t) - GetUnitY(.c)))
set HDrain = (10+25*lvl)*HDrain
call SetLightningColor(.lig, 100, 0, 0, 100)
call MoveLightning(.lig, true, GetUnitX(.c), GetUnitY(.c), GetUnitX(.t), GetUnitY(.t))
if not(IsUnitType(.t, UNIT_TYPE_DEAD) or IsUnitType(.c, UNIT_TYPE_DEAD)) and dist < 500 + 50*lvl and .dur <= 10 then//and GetUnitCurrentOrder(.c) == OrderId("magicleash") then
if IsUnitEnemy(.t, GetOwningPlayer(.c)) then
call UnitDamageTarget(.c, .t, HDrain*tick, true,false, atk, dmg, wtype)
set EHp = EHp - GetWidgetLife(.t)
call SetWidgetLife(.c, GetWidgetLife(.c)+EHp)
else
call SetWidgetLife(.c, GetWidgetLife(.c) - HDrain*tick)
call SetWidgetLife(.t, GetWidgetLife(.t) + HDrain*tick*0.75)
endif
else
call DestroyLightning(.lig)
call DestroyEffect(.fx)
set .lig = null
set .c = null
set .t = null
call ReleaseTimer(.tim)
call .destroy()
endif
set .dur = .dur + tick
endmethod

static method create takes unit caster, unit target returns thistype
local thistype this = thistype.allocate()
set .c = caster
set .t = target
set .lig = AddLightning(GetAbilityEffectById(SPELLID,EFFECT_TYPE_LIGHTNING,0), true, GetUnitX(.c), GetUnitY(.c), GetUnitX(.t), GetUnitY(.t))
set .dur = 0
set .fx = AddSpecialEffectTarget(GetAbilityEffectById(SPELLID, EFFECT_TYPE_CASTER,0), .c, "origin")
set .tim = NewTimer()
call SetTimerData(.tim,this)
call TimerStart(.tim, tick, true, function thistype.Timer)
return this
endmethod

endstruct

private function Conditions takes nothing returns boolean
if GetSpellAbilityId() == SPELLID then
call Data.create(GetTriggerUnit(), GetSpellTargetUnit())
endif
return false
endfunction

//===========================================================================
public function i takes nothing returns nothing
local trigger t = CreateTrigger( )
call TriggerRegisterAnyUnitEventBJ( t, EVENT_PLAYER_UNIT_SPELL_EFFECT )
call TriggerAddCondition( t, Condition( function Conditions ) )
endfunction

endscope[/code]


The commented out part determines if it's a channeling spell or not. Perhaps this example may help you optimize your current code.
 
Last edited:
Level 13
Joined
May 11, 2008
Messages
1,198
i don't think your suggestion has any merit in improving code, but it has merit in improving ease of importing. when i was testing your spell it was an easy thing to import.

anyways, yeah, the suggestion works fine. i actually don't really know how to properly use the function. what purpose does the integer at the end serve? is it in case i have multiple lightning effects? 0 is first, 1 is second, and so on?
 
Level 13
Joined
Jul 26, 2008
Messages
1,009
Yup, that's correct. You could use a series of lightning effects.

The same goes for the other fields. One trick to simplify your life in the object editor is to shift click certain fields to see their rawcodes and paths.

I use this to put Hero skills on non-hero units, to easily create a series of data with commas and values, and to avoid the GUI, especially for unit and ability selection.

These tips will help you greatly down the line, especially if you want to copy a spell from one map into another.
 
Level 13
Joined
May 11, 2008
Messages
1,198
Yup, that's correct. You could use a series of lightning effects.

The same goes for the other fields. One trick to simplify your life in the object editor is to shift click certain fields to see their rawcodes and paths.

I use this to put Hero skills on non-hero units, to easily create a series of data with commas and values, and to avoid the GUI, especially for unit and ability selection.

These tips will help you greatly down the line, especially if you want to copy a spell from one map into another.

yes, i already knew that bit about shift click.

nevertheless, thanks for the tip, then...as it did what i supposed it might.
this goes to explain a few things...

"o_O, and I thought you just wanted to recreate the purple lightning effect o-o "

well, no, that was not the intent of the thread, although, yes, i would like to get that purple lightning if possible. what was going on in my head was i wanted to duplicate the slark spell. but i didn't know how to code for that, but i thought i knew. so i tried it, and it worked...well, the leash part(except visual). i don't know how to combine the jump with the leash part. but i'm unconcerned with that. what i was more concerned with was the visual aspect of the leash.

do you know anything about creating custom lightning effects?

and fyi i figure mostly the reason i don't know how to code a jump with the leash is because i don't know how to code the jump to begin with, haha. it seems complicated.
 
Level 13
Joined
Jul 26, 2008
Messages
1,009
You're going to want to grab Shadow something's Jump Parabola. That's a good start. You should be able to find a simple tutorial with it on how to set it up.

It takes 2 variables, the distance between where it started and where it ends, and the distance between it's current position and it's end position. You then plug in those variables into the formula and set the Z of the object to the end result.

The example spell at the end of this post will illustrate what I'm talking about.

As for making a lightning effect, it's basically a picture, I forgot the length and width, with a line going through it. The line is then altereted with special effects and variations in it. The picture looks a lot like actual lightning.

This picture is then sort of reeled in a loop on screen (Though I'm not 100%) to make it look like it's changing. You may have to over-write a lightning effect, or go through some complex means to add it in as an additional effect.

http://world-editor-tutorials.thehelper.net/cat_usersubmit.php?view=73625

http://www.wc3c.net/showthread.php?t=62725
JASS:
scope Molotov initializer Init

globals
    private constant integer SPELLID = 'bomb'
    private constant attacktype atk     = ATTACK_TYPE_PIERCE
    private constant damagetype dmg     = DAMAGE_TYPE_MAGIC
    private constant weapontype wtype   = WEAPON_TYPE_WHOKNOWS
    private constant real tick          = 1
    private unit TEMP
endglobals

private struct Data extends xecollider

    unit c
    timer tim
    real dur
    real maxDist
    real tX
    real tY
    real sX
    real sY
    effect fx

    static method Timer takes nothing returns nothing
     local thistype this = GetTimerData(GetExpiredTimer())
     local integer lvl = GetUnitAbilityLevel(.c, SPELLID)
     local xedamage xd = xedamage.create()
     local real dam = 1 + 3*lvl

        call xd.useSpecialEffect(GetAbilityEffectById(SPELLID, EFFECT_TYPE_SPECIAL, 0),"origin")
        set xd.exception = UNIT_TYPE_FLYING
        call xd.factor ( UNIT_TYPE_STRUCTURE, 0.5)
        set xd.dtype = dmg
        set xd.atype = atk
        set xd.damageAllies = true
        set xd.damageSelf   = true
        set xd.allyfactor = 0.4
        call xd.damageAOE(.c, .tX, .tY, 95 + 40. * lvl, dam)
        call xd.destroy()

        call DestroyEffect(.fx)

        set .dur = .dur + tick
        if .dur >= 5 then
            call ReleaseTimer(.tim)
            call .terminate()
        else
            set .fx = AddSpecialEffect(GetAbilityEffectById(SPELLID, EFFECT_TYPE_AREA_EFFECT, 0), .tX, .tY)
        endif
    endmethod

    method onDestroy takes nothing returns nothing

    endmethod

    method loopControl takes nothing returns nothing
     local xedamage xd
     local integer lvl = GetUnitAbilityLevel(.c, SPELLID)
     local real dist        = SquareRoot((.tX-.x)*(.tX-.x)+(.tY-.y)*(.tY-.y))
     local real maxDist     = SquareRoot((.sX-.x)*(.sX-.x)+(.sY-.y)*(.sY-.y))
     local real maxHeight   = 225
     local real t = (dist*2)/maxDist-1
     local real dam = 70 + 55*lvl
        set .z = (-t*t+1)*maxHeight
        if dist < 25 then
            set .tim = NewTimer()
            set xd = xedamage.create()
            set xd.exception = UNIT_TYPE_FLYING
            call xd.factor ( UNIT_TYPE_STRUCTURE, 0.5)
            set xd.dtype = dmg
            set xd.atype = atk
            set xd.damageAllies = true
            set xd.allyfactor = 0.4
            call DestroyEffect(AddSpecialEffect(GetAbilityEffectById(SPELLID, EFFECT_TYPE_AREA_EFFECT, 1), .x, .y))
            call xd.damageAOE(.c, .x, .y, 95 + 40. * lvl, dam)
            call xd.destroy()
            call .hiddenDestroy()
            call SetTimerData(.tim,this)
            call TimerStart(.tim, tick, true, function Data.Timer)
        endif
    endmethod

endstruct

private function Actions takes unit c returns nothing
 local real ang = Atan2(GetSpellTargetY() - GetUnitY(c), GetSpellTargetX() - GetUnitX(c)) 
 local Data xc

    set xc                  = Data.create(GetUnitX(c), GetUnitY(c), ang)
    set xc.fxpath           = GetAbilityEffectById(SPELLID,EFFECT_TYPE_MISSILE, 0)
    set xc.tX               = GetSpellTargetX()
    set xc.tY               = GetSpellTargetY()
    set xc.sX               = xc.x
    set xc.sY               = xc.y
    set xc.speed            = 555.0
    set xc.expirationTime   = 2
    set xc.z                = 50.0
    set xc.c                = c
    set xc.dur              = 0
endfunction

private function Conditions takes nothing returns nothing
    if GetSpellAbilityId() == SPELLID then
        call Actions(GetTriggerUnit())
    endif
endfunction

//===========================================================================
public function Init takes nothing returns nothing
 local trigger t = CreateTrigger()
    call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddAction(t, function Conditions )
    call XE_PreloadAbility(SPELLID)
endfunction

endscope
 
Status
Not open for further replies.
Top