Starting JASS

kingkingyyk3

Visitor (Welcome to the Jungle, Baby!)
Reaction score
216
Looks nice.
For preloading abilities, I suggest you to make a library which is specialized for preloading.
This can prevent too much of dummies being used to preload abilities.
 

Ayanami

칼리
Reaction score
288
Alright, now proceeding on using timers. So I decided to make a simple area knock back ability. Now the problem is, how do I actually add the units in a group and move them. I was told to use this method when handling groups, but this method only works when it isn't periodic, right? So, do I use ForGroup?
 

13lade619

is now a game developer :)
Reaction score
399
just make use of a timer system and a struct.

KeyTimers2 by Jesus4Lyf is good.

Make a struct with the caster and the group.
forward the struct to the callback function through the KT_Add() function.
retrieve the struct on the callback function.

EDIT: *easier.

grab a knockback system.
run through your unitgroup as usual,
use the knockback function on the individual units.
 

Ayanami

칼리
Reaction score
288
Hmm, although I roughly know what structs are, I didn't use them before, so It's quite confusing :/

You know in GUI action, there is a "Pick Every Unit UnitGroup and Do Actions" right? Is it inefficient to use that?
 

13lade619

is now a game developer :)
Reaction score
399
IIRC, there is no way to pass 'stuff' from one function to another.

*editing*

First, there were Global vars. But using them does not permit multi instanciability.

Then, Local Handle Vars were created. Primarily using the gamcache to 'store' stuff temporarily so that you can use them in another function.

What's used up to now is Timer-Struct attachment. Basically, you have a struct and pass it to a timer then you can retrieve the data you passed on the callback using the timer as reference.
 

Ayanami

칼리
Reaction score
288
Alright, finished the a simple area knockback using KeyTimers2. Didn't take deceleration into account yet, just need to check if the codes are okay. Here it is:

JASS:

library WarStomp initializer InitTrig

globals
    private constant integer ABIL_ID = 'ABMS'
    private constant integer DUMMY_ID = 'h001'
    private constant real AOE = 300.00
    private constant real DAMAGE = 200.00
    private constant real DISTANCE = 500.00
    private constant real TIME = 1.00
endglobals

globals
    private real x
    private real y
    private filterfunc ff
endglobals

private struct knockback
    real a
    real d
    real s
    unit u
endstruct

private function Periodic takes nothing returns boolean
    local knockback d = KT_GetData()
    if d.d <= 0 then
        call d.destroy()
        return true
    else
        set x = GetUnitX(d.u) + d.s * Cos(d.a * bj_DEGTORAD)
        set y = GetUnitY(d.u) + d.s * Sin(d.a * bj_DEGTORAD)
        call SetUnitPosition(d.u, x, y)
        set d.d = d.d - d.s
    endif
    return false
endfunction

private function Start takes unit caster, unit target, real dist, real time, real damage returns nothing
    local knockback d = knockback.create()
    local location cl = GetUnitLoc(caster)
    local location tl = GetUnitLoc(target)
    call UnitDamageTarget(caster, target, damage, true, false, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_MAGIC, WEAPON_TYPE_WHOKNOWS)
    set d.d = dist
    set d.s = dist/time * 0.03
    set d.a = AngleBetweenPoints(cl, tl)
    set d.u = target
    call KT_Add(function Periodic, d, 0.03)
    call RemoveLocation(cl)
    call RemoveLocation(tl)
    set cl = null
    set tl = null
endfunction

private function Conditions takes nothing returns boolean
    return GetSpellAbilityId() == ABIL_ID
endfunction

private function Execute takes nothing returns boolean
    local unit c = GetTriggerUnit()
    local unit u = GetFilterUnit()
    if not IsUnitType(u, UNIT_TYPE_STRUCTURE) and not IsUnitType(u, UNIT_TYPE_DEAD) and IsUnitEnemy(u, GetOwningPlayer(c)) then
        call Start(c, u, DISTANCE, TIME, DAMAGE)
    endif
    return false
endfunction

private function Actions takes nothing returns nothing
    call GroupEnumUnitsInRange(GROUP, GetUnitX(GetTriggerUnit()), GetUnitY(GetTriggerUnit()), AOE, ff)
endfunction

//===========================================================================
private function InitTrig takes nothing returns nothing
    local trigger t = CreateTrigger()
    call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SPELL_EFFECT)
    call TriggerAddCondition(t, Condition(function Conditions))
    call TriggerAddAction(t, function Actions)
    set ff = Filter(function Execute)
endfunction

endlibrary
 

13lade619

is now a game developer :)
Reaction score
399
1 Scopes are better for spells generally

2

would be for simplicity
JASS:
 call GroupEnumUnitsInRange(GROUP, GetUnitX(GetTriggerUnit()), GetUnitY(GetTriggerUnit()), AOE, Condition(function Execute))


3 Does triggering unit get passed to Execute? i dont recall since i dont use this method... i use the loop construct for groups generally.

4 Use real coordinates directly, not locations to avoid leak removal.

5 SetUnitPosition() interrupts orders though.
SetUnitX() and SetUnitY() would ignore pathing at first so you have to have extra checks.
 

Ayanami

칼리
Reaction score
288
3 Does triggering unit get passed to Execute? i dont recall since i dont use this method... i use the loop construct for groups generally.

Yup, it does.

4 Use real coordinates directly, not locations to avoid leak removal.

How would I work around doing AngleBetweenPoints check without using locations?

5 SetUnitPosition() interrupts orders though.
SetUnitX() and SetUnitY() would ignore pathing at first so you have to have extra checks.

So basically, use SetUnitX() and SetUnitY()?
 

hgkjfhfdsj

Active Member
Reaction score
55
How would I work around doing AngleBetweenPoints check without using locations?
JASS:
    //..
    set x = IsPathable(GetUnitX(d.u) + d.x) //some condition
    set y = IsPathable(GetUnitY(d.u) + d.y)//some condition
   
    call SetUnitX(d.u, d.x)
    call SetUnitY(d.u, d.y)
    // -----
    local real angle = Atan2(GetUnitY(target) - GetUnitY(caster), GetUnitX(target) - GetUnitX(caster)) //radian
    //can probably store calculated values since d.s & angle doesnt change
    set d.x = dist/time * 0.03 + Cos(angle)
    set d.y = dist/time * 0.03 + Sin(angle)


EDIT
+Post 81
TESH also comes with a function list
 

Bribe

vJass errors are legion
Reaction score
67
Crack open the good ol' blizzard.j file (a copy of it comes with JassHelper or JNGP, or you can use an MPQ extractor to grab it from the .mpq file). Inside of this "magical" file, you will find [ljass]AngleBetweenPoints[/ljass] to be a load of crap as that converts your locations to coordinates before doing any calculations.

Same with [ljass]PolarProjectionBJ[/ljass], [ljass]DistanceBetweenPoints[/ljass] and all the others. There are a lot of BJ functions that serve a purpose, but the majority of them are more or less useless :p
 

tooltiperror

Super Moderator
Reaction score
231
Or, you can just click on them in the (L)JASS tags and get brought to the wiki page and read the actions they call.
 

Ayanami

칼리
Reaction score
288
Just asking, how do I retrieve the damage source and the damaged unit when using J4L's Damage System?
 

Ayanami

칼리
Reaction score
288
Need help again. I have this trigger so far.

JASS:

scope ChargingStrikes initializer InitTrig

globals
    private constant integer ABIL_ID1 = 'ABCS' // raw code of Ability "Charging Strikes"
    private constant integer ABIL_ID2 = 'ACS1' // raw code of Ability "Charging Strikes (Attack Speed)"
    private constant real MINDMG = 23.00 // minimum damage dealt
    private constant real MAXDMG = 25.00 // maximum damage dealt
    private constant real TIME = 0.25 // time taken for charge
    private constant real AOE = 200.00 // area of effect of the damage
    private constant boolean STR = false // true if the hero's primary attribute is strength
    private constant boolean AGI = true // true if the hero's primary attribute is agility
    private constant boolean INT = false // true if the hero's primary attribute is intelligence
    // if all is set to false, damage dealt will be random number between MINDMG and MAXDMG
endglobals

private struct cs
    real offsetx
    real offsety
    real dist
    real speed
    unit u
endstruct

private function Slide takes nothing returns boolean
    local cs d = KT_GetData()
    local real x = GetUnitX(d.u) + d.offsetx
    local real y = GetUnitY(d.u) + d.offsety
    if d.dist <= 0 then
        call SetUnitPathing(d.u, true)
        call d.destroy()
        return true
    elseif not IsTerrainPathable(x, y, PATHING_TYPE_WALKABILITY) then
        call SetUnitPathing(d.u, false)
        call SetUnitX(d.u, x)
        call SetUnitY(d.u, y)
    endif
    set d.dist = d.dist - d.speed
    return false
endfunction

private function Conditions takes nothing returns boolean
    return GetSpellAbilityId() == ABIL_ID1
endfunction

private function Actions takes nothing returns nothing
    local cs d = cs.create()
    local location t = GetSpellTargetLoc()
    local real dx = GetLocationX(t)
    local real dy = GetLocationY(t)
    local real angle
    local real x
    local real y
    set d.u = GetTriggerUnit()
    set x = GetUnitX(d.u)
    set y = GetUnitY(d.u)
    set angle = Atan2(dy - y, dx - x)
    set d.dist = SquareRoot(((x - dx) * (x - dx)) + ((y - dy) * (y - dy)))
    set d.speed = d.dist / TIME * 0.03
    set d.offsetx = d.speed * Cos(angle)
    set d.offsety = d.speed * Sin(angle)
    call KT_Add(function Slide, d, 0.03)
    call RemoveLocation(t)
    set t = null
endfunction

private function GetDamage takes unit caster returns real
    if STR then
        return GetRandomReal(MINDMG, MAXDMG) + I2R(GetHeroStr(caster, true)) 
    elseif AGI then
        return GetRandomReal(MINDMG, MAXDMG) + I2R(GetHeroAgi(caster, true)) 
    elseif INT then
        return GetRandomReal(MINDMG, MAXDMG) + I2R(GetHeroInt(caster, true)) 
    endif
    return GetRandomReal(MINDMG, MAXDMG)
endfunction

private function InitTrig takes nothing returns nothing
    local trigger t = CreateTrigger()
    call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SPELL_EFFECT)
    call TriggerAddCondition(t, Condition(function Conditions))
    call TriggerAddAction(t, function Actions)
endfunction

endscope


Now I'm having problems with the damaging part. This trigger is supposed to make the caster "slide" to the targeted point and dealing damage. However, I'm having trouble with dealing the damage as I need a method to check if the enemy has been already hit. Also, how would I deal damage without memory leaks?
 

13lade619

is now a game developer :)
Reaction score
399
I'm having trouble with dealing the damage as I need a method to check if the enemy has been already hit.
I find that using indexing systems (like AIDS, by J4L again) to perform simple integer or boolean checks for each unit works well.

like if [ljass]ChargingStrikesHit[target]==true[/ljass] or something.
 

Laiev

Hey Listen!!
Reaction score
188
instead [ljass]GetSpellTargetLoc()[/ljass] use [ljass]GetSpellTargetX()[/ljass] and [ljass]GetSpellTargetY()[/ljass] (i think is those natives)

EDIT:
JASS:
private function Actions takes nothing returns nothing
    local cs d = cs.create()
    local location t = GetSpellTargetLoc()
    local real dx = GetLocationX(t)
    local real dy = GetLocationY(t)
    local real angle
    local real x
    local real y
    set d.u = GetTriggerUnit()
    set x = GetUnitX(d.u)
    set y = GetUnitY(d.u)
    set angle = Atan2(dy - y, dx - x)
    set d.dist = SquareRoot(((x - dx) * (x - dx)) + ((y - dy) * (y - dy)))
    set d.speed = d.dist / TIME * 0.03
    set d.offsetx = d.speed * Cos(angle)
    set d.offsety = d.speed * Sin(angle)
    call KT_Add(function Slide, d, 0.03)
    call RemoveLocation(t)
    set t = null
endfunction

>>
JASS:
private function Actions takes nothing returns nothing
    local cs d = cs.create()
    local real dx = GetSpellTargetX()
    local real dy = GetSpellTargetY()
    local real x = GetUnitX(d.u)
    local real y = GetUnitY(d.u)
    local real = angle Atan2(dy - y, dx - x)

    set d.u = GetTriggerUnit()
    set d.dist = SquareRoot(((x - dx) * (x - dx)) + ((y - dy) * (y - dy)))
    set d.speed = d.dist / TIME * 0.03
    set d.offsetx = d.speed * Cos(angle)
    set d.offsety = d.speed * Sin(angle)

    call KT_Add(function Slide, d, 0.03)
endfunction
 

kingkingyyk3

Visitor (Welcome to the Jungle, Baby!)
Reaction score
216
Because it is static method, just like normal functions.
Can you put call BJDebugMsg(R2S(this)) in normal functions?
I think you know the answer..
Methods are actually
JASS:
static method my takes thistype this returns nothing
endmethod

That's why you can call the debug msg in methods.
 
General chit-chat
Help Users
  • No one is chatting at the moment.
  • The Helper The Helper:
    The bots will show up as users online in the forum software but they do not show up in my stats tracking. I am sure there are bots in the stats but the way alot of the bots treat the site do not show up on the stats
  • Varine Varine:
    I want to build a filtration system for my 3d printer, and that shit is so much more complicated than I thought it would be
  • Varine Varine:
    Apparently ABS emits styrene particulates which can be like .2 micrometers, which idk if the VOC detectors I have can even catch that
  • Varine Varine:
    Anyway I need to get some of those sensors and two air pressure sensors installed before an after the filters, which I need to figure out how to calculate the necessary pressure for and I have yet to find anything that tells me how to actually do that, just the cfm ratings
  • Varine Varine:
    And then I have to set up an arduino board to read those sensors, which I also don't know very much about but I have a whole bunch of crash course things for that
  • Varine Varine:
    These sensors are also a lot more than I thought they would be. Like 5 to 10 each, idk why but I assumed they would be like 2 dollars
  • Varine Varine:
    Another issue I'm learning is that a lot of the air quality sensors don't work at very high ambient temperatures. I'm planning on heating this enclosure to like 60C or so, and that's the upper limit of their functionality
  • Varine Varine:
    Although I don't know if I need to actually actively heat it or just let the plate and hotend bring the ambient temp to whatever it will, but even then I need to figure out an exfiltration for hot air. I think I kind of know what to do but it's still fucking confusing
  • The Helper The Helper:
    Maybe you could find some of that information from AC tech - like how they detect freon and such
  • Varine Varine:
    That's mostly what I've been looking at
  • Varine Varine:
    I don't think I'm dealing with quite the same pressures though, at the very least its a significantly smaller system. For the time being I'm just going to put together a quick scrubby box though and hope it works good enough to not make my house toxic
  • Varine Varine:
    I mean I don't use this enough to pose any significant danger I don't think, but I would still rather not be throwing styrene all over the air
  • The Helper The Helper:
    New dessert added to recipes Southern Pecan Praline Cake https://www.thehelper.net/threads/recipe-southern-pecan-praline-cake.193555/
  • The Helper The Helper:
    Another bot invasion 493 members online most of them bots that do not show up on stats
  • Varine Varine:
    I'm looking at a solid 378 guests, but 3 members. Of which two are me and VSNES. The third is unlisted, which makes me think its a ghost.
    +1
  • The Helper The Helper:
    Some members choose invisibility mode
    +1
  • The Helper The Helper:
    I bitch about Xenforo sometimes but it really is full featured you just have to really know what you are doing to get the most out of it.
  • The Helper The Helper:
    It is just not easy to fix styles and customize but it definitely can be done
  • The Helper The Helper:
    I do know this - xenforo dropped the ball by not keeping the vbulletin reputation comments as a feature. The loss of the Reputation comments data when we switched to Xenforo really was the death knell for the site when it came to all the users that left. I know I missed it so much and I got way less interested in the site when that feature was gone and I run the site.
  • Blackveiled Blackveiled:
    People love rep, lol
    +1
  • The Helper The Helper:
    The recipe today is Sloppy Joe Casserole - one of my faves LOL https://www.thehelper.net/threads/sloppy-joe-casserole-with-manwich.193585/
  • The Helper The Helper:
    Decided to put up a healthier type recipe to mix it up - Honey Garlic Shrimp Stir-Fry https://www.thehelper.net/threads/recipe-honey-garlic-shrimp-stir-fry.193595/
  • The Helper The Helper:
    Here is another comfort food favorite - Million Dollar Casserole - https://www.thehelper.net/threads/recipe-million-dollar-casserole.193614/

      The Helper Discord

      Members online

      Affiliates

      Hive Workshop NUON Dome World Editor Tutorials

      Network Sponsors

      Apex Steel Pipe - Buys and sells Steel Pipe.
      Top