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

Damage in a line

Status
Not open for further replies.
Level 13
Joined
Oct 25, 2009
Messages
995
How can i damage units in a line? Like shockwave,but this is loop.
I WANT GUI,NOT JASS :p
+REP :goblin_boom:
EDIT: Daelin's Creating a line,that not damaging :p
EDIT 2: i want to use Pick every unit in (Unit within XXX range of XXXXXX point)
 
Level 23
Joined
Jan 1, 2009
Messages
1,608
basically you do this buy picking all units in a rect around that line (black rect) and then testing whether or not unit u is in that line-area(blue rect)
zeichnung479.jpg


A possible more performant type of checking would to only group all units in a few rects, leaving out many units to test.

zeichnung483.jpg


I only got the jass function right now...i Guess it would be kinda ugly in GUI, I suppose you use the JNGP allready, why not pasting it into the map header and using a custom script?


JASS:
library groupaddunitsnearline

globals
    //upper bound for the collision size of units
    private constant real MAX_COLLISSION = 128.
    //this is aproximately how much space of the rects is used by the line
    //a higher value yields less unnecessary checks but also more rects 
    private constant real desiredefficiency = 0.6 
    
    //---
    private rect temprect = Rect(0,0,0,0)
    private group tempenumgroup = CreateGroup()
    private group tempgroup
    private real temppx
    private real temppy
    private real tempdnx
    private real tempdny
    private real tempwidth
    private real tempd
endglobals


//returns the maximum of 4 reals
private function max4 takes real a, real b, real c, real d returns real
    local real max = a
    if b > max then
        set max = b
    endif
    if c > max then
        set max = c
    endif
    if d > max then
        set max = d
    endif
    return max
endfunction

//returns the minimum of 4 reals
private function min4 takes real a, real b, real c, real d returns real
    local real min = a
    if b < min then
        set min = b
    endif
    if c < min then
        set min = c
    endif
    if d < min then
        set min = d
    endif
    return min
endfunction

private function Add takes nothing returns boolean
    //position of unit
    local real x = GetUnitX(GetFilterUnit())
    local real y = GetUnitY(GetFilterUnit())
    //vector from the beginning of the line to the unit
    local real dx = x - temppx
    local real dy = y - temppy
    //distance from the beginning of the line to that point on the line which is closest to the unit (uses dot-product)
    local real d = dx * tempdnx + dy * tempdny
    local real cx
    local real cy
    //cut off points outside the line
    if d <= 0 then
        set d = 0
    elseif d >= tempd then
        set d = tempd
    endif
    //the closest point to the unit on the line 
    set cx = temppx + d * tempdnx
    set cy = temppy + d * tempdny 

    if IsUnitInRangeXY(GetFilterUnit(), cx, cy, tempwidth) then
        call GroupAddUnit(tempgroup, GetFilterUnit())
    endif
    return false
endfunction

function GroupAddUnitsNearLine takes group g, real px, real py, real qx, real qy, real width returns nothing
    //the line width width
    local real l1x
    local real l1y
    local real l2x
    local real l2y
    local real l3x
    local real l3y
    local real l4x
    local real l4y
    //d = from p to q
    local real dx = qx - px
    local real dy = qy - py
    local real dlen = SquareRoot(dx*dx + dy*dy)
    //normalized d
    local real dxn = dx / dlen
    local real dyn = dy / dlen
    //divisions
    local integer divisions = 1
    //bonus for correct overlapping of rects
    local real bonusx = 0.
    local real bonusy = 0.
    //integer for loop    
    local integer i
    //the outer rect
    local real rectminx
    local real rectmaxx
    local real rectminy
    local real rectmaxy
    
    
    set width = width + MAX_COLLISSION
    
    //calculate the number of divisions needed to approximately match desiredefficiency
    if dx != 0 and dy != 0 then
        set divisions = 1 + R2I(SquareRoot(desiredefficiency*desiredefficiency / (width*width/(dx*dx) + width*width/(dy*dy))))  
    endif
    
    //this calculates a bonus so that there are intersections between the different rects
    //(without this we would miss some units between the rects)
    if dy != 0 and divisions > 1 then 
        set bonusx = width / 2 * dlen / dx// ?dy
    endif
    if dx != 0 and divisions > 1 then
        set bonusy = width / 2 * dlen / dy // ? dx
    endif
    
    
    //calculate first line segment
    set l1x = - width*dyn
    set l1y =   width*dxn
    set l2x =   width*dyn
    set l2y = - width*dxn
    set l3x = l2x + dx/divisions + bonusx
    set l3y = l2y + dy/divisions + bonusy
    set l4x = l1x + dx/divisions + bonusx
    set l4y = l1y + dy/divisions + bonusy
    
    
    
    //calculate bounds of the first line segment    
    set rectminx = min4(l1x,l2x,l3x,l4x)
    set rectmaxx = max4(l1x,l2x,l3x,l4x)
    set rectminy = min4(l1y,l2y,l3y,l4y)
    set rectmaxy = max4(l1y,l2y,l3y,l4y)
    
    
    //set temp vars for groupenum
    set tempgroup = g
    set temppx = px
    set temppy = py
    set tempdnx = dxn
    set tempdny = dyn
    set tempwidth = width - MAX_COLLISSION
    set tempd = dlen
    
    
    set i = 0
    loop
        exitwhen i >= divisions
        //---
        //move rect to right position
        call SetRect(temprect, px + i * dx / divisions + rectminx, py + i * dy / divisions + rectminy, px + i * dx / divisions + rectmaxx, py + i * dy / divisions + rectmaxy)
        //enum units in rect
        call GroupEnumUnitsInRect(tempenumgroup, temprect, Condition(function Add))
        //---
        set i = i + 1
    endloop
endfunction

endlibrary


using this function would be to call GroupAddUnitsNearLine with the needed parameters.
 
Level 19
Joined
Feb 4, 2009
Messages
1,313
like this?
http://www.hiveworkshop.com/forums/...-98/take-damage-lightning-194892/#post1911382
I'll translate this to GUI in a few minutes

edit:
done
  • Ini
    • Events
      • Map initialization
    • Conditions
    • Actions
      • Set zLoc = (Point(0.00, 0.00))
  • DeathGaze_Cast
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Death Gaze
    • Actions
      • Set DeathGaze_Count = (DeathGaze_Count + 1)
      • Set DeathGaze_Caster[DeathGaze_Count] = (Triggering unit)
      • Set DeathGaze_Damage[DeathGaze_Count] = 10.00
      • Set DeathGaze_Distance[DeathGaze_Count] = 800.00
      • Set DeathGaze_Duration[DeathGaze_Count] = 5.00
      • Set DeathGaze_Time[DeathGaze_Count] = 0.00
      • Set DeathGaze_Width[DeathGaze_Count] = 80.00
      • Set DeathGaze_LightningStartZ[DeathGaze_Count] = 100.00
      • Set DeathGaze_LightningEndZ[DeathGaze_Count] = 35.00
      • Custom script: call MoveLocation(udg_zLoc, GetUnitX(GetTriggerUnit()), GetUnitY(GetTriggerUnit()))
      • For each (Integer DeathGaze_Index) from 0 to 4, do (Actions)
        • Loop - Actions
          • Lightning - Create a Finger of Death lightning effect from source zLoc to target zLoc
          • Set DeathGaze_Lightning[((DeathGaze_Count x 5) + DeathGaze_Index)] = (Last created lightning effect)
      • Trigger - Turn on DeathGaze_Loop <gen>
  • DeathGaze_Loop
    • Events
      • Time - Every 0.03 seconds of game time
    • Conditions
    • Actions
      • For each (Integer DeathGaze_Index) from 1 to DeathGaze_Count, do (Actions)
        • Loop - Actions
          • Set u = DeathGaze_Caster[DeathGaze_Index]
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • u Not equal to No unit
              • (Life of u) Greater than 0.00
              • DeathGaze_Time[DeathGaze_Index] Less than DeathGaze_Duration[DeathGaze_Index]
            • Then - Actions
              • Set DeathGaze_Time[DeathGaze_Index] = (DeathGaze_Time[DeathGaze_Index] + 0.03)
              • Set r = DeathGaze_Distance[DeathGaze_Index]
              • Custom script: set udg_x = GetUnitX(udg_u)
              • Custom script: set udg_y = GetUnitY(udg_u)
              • Set a = (Facing of u)
              • Set x2 = (x + ((Cos(a)) x r))
              • Set y2 = (y + ((Sin(a)) x r))
              • Custom script: call MoveLocation(udg_zLoc, udg_x, udg_y)
              • Custom script: set udg_z = GetLocationZ(udg_zLoc)
              • Set z = (z + (DeathGaze_LightningStartZ[DeathGaze_Index] + (Current flying height of u)))
              • Custom script: call MoveLocation(udg_zLoc, udg_x2, udg_y2)
              • Custom script: set udg_z2 = GetLocationZ(udg_zLoc)
              • Set z2 = (z2 + DeathGaze_LightningEndZ[DeathGaze_Index])
              • For each (Integer DeathGaze_Index2) from 0 to 4, do (Actions)
                • Loop - Actions
                  • Custom script: call MoveLightningEx(udg_DeathGaze_Lightning[udg_DeathGaze_Index*5+udg_DeathGaze_Index2], true, udg_x, udg_y, udg_z, udg_x2, udg_y2, udg_z2)
              • Set p = (Owner of u)
              • Set r2 = DeathGaze_Damage[DeathGaze_Index]
              • Set r3 = (r x DeathGaze_Width[DeathGaze_Index])
              • Custom script: call GroupEnumUnitsInRange(udg_g, udg_x, udg_y, udg_r, null)
              • Unit Group - Pick every unit in g and do (Actions)
                • Loop - Actions
                  • Set u2 = (Picked unit)
                  • Custom script: set udg_x3 = GetUnitX(udg_u2)
                  • Custom script: set udg_y3 = GetUnitY(udg_u2)
                  • Set dx = (x2 - x3)
                  • Set dy = (y2 - y3)
                  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    • If - Conditions
                      • (Life of u2) Greater than 0.00
                      • ((dx x dx) + (dy x dy)) Less than or equal to (r x r)
                      • (u2 belongs to an enemy of p) Equal to True
                      • (Abs((((x2 - x) x (y - y3)) - ((x - x3) x (y2 - y))))) Less than or equal to r3
                    • Then - Actions
                      • Unit - Cause u to damage u2, dealing r2 damage of attack type Spells and damage type Normal
                    • Else - Actions
            • Else - Actions
              • For each (Integer DeathGaze_Index2) from 0 to 4, do (Actions)
                • Loop - Actions
                  • Lightning - Destroy DeathGaze_Lightning[((DeathGaze_Index x 5) + DeathGaze_Index2)]
                  • Set DeathGaze_Lightning[((DeathGaze_Index x 5) + DeathGaze_Index2)] = DeathGaze_Lightning[((DeathGaze_Count x 5) + DeathGaze_Index2)]
              • Lightning - Destroy DeathGaze_Lightning[DeathGaze_Index]
              • Lightning - Destroy DeathGaze_Lightning[DeathGaze_Index]
              • Lightning - Destroy DeathGaze_Lightning[DeathGaze_Index]
              • Lightning - Destroy DeathGaze_Lightning[DeathGaze_Index]
              • Set DeathGaze_Caster[DeathGaze_Index] = DeathGaze_Caster[DeathGaze_Count]
              • Set DeathGaze_Damage[DeathGaze_Index] = DeathGaze_Damage[DeathGaze_Count]
              • Set DeathGaze_Distance[DeathGaze_Index] = DeathGaze_Distance[DeathGaze_Count]
              • Set DeathGaze_Duration[DeathGaze_Index] = DeathGaze_Duration[DeathGaze_Count]
              • Set DeathGaze_LightningEndZ[DeathGaze_Index] = DeathGaze_LightningEndZ[DeathGaze_Count]
              • Set DeathGaze_LightningStartZ[DeathGaze_Index] = DeathGaze_LightningStartZ[DeathGaze_Count]
              • Set DeathGaze_Time[DeathGaze_Index] = DeathGaze_Time[DeathGaze_Count]
              • Set DeathGaze_Width[DeathGaze_Index] = DeathGaze_Width[DeathGaze_Count]
              • Set DeathGaze_Count = (DeathGaze_Count - 1)
              • Set DeathGaze_Index = (DeathGaze_Index - 1)
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • DeathGaze_Count Less than 1
                • Then - Actions
                  • Trigger - Turn off (This trigger)
                • Else - Actions
the math behind it is explained here
http://mathworld.wolfram.com/Point-LineDistance2-Dimensional.html (14)
 

Attachments

  • UltimateLightningPenis.w3x
    17.9 KB · Views: 70
Last edited:
Status
Not open for further replies.
Top