Starting JASS

Ayanami

칼리
Reaction score
288
Well, I saw the post by saw792 and read J4L's Tutorial on unit groups. And I decided to use that. However, I noticed that by using 1 dummy, not all units are put to sleep. Sometimes only one unit is affected, and sometimes, only a few. My dummy unit has 0.00 casting time, etc. My dummy sleep spell has no casting time and should be instant. Anything wrong here?

JASS:

library MassSleep initializer InitTrig

globals
    private constant integer BMS_ID = 'ABMS'
    private constant integer MS1_ID = 'AMS1'
    private constant integer DUMMY_ID = 'h001'
    private constant real AOE = 500.00
endglobals

globals
    private unit dummy
    private filterfunc ff
endglobals

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

private function Execute takes nothing returns boolean
    if not IsUnitType(GetFilterUnit(), UNIT_TYPE_STRUCTURE) and not IsUnitType(GetFilterUnit(), UNIT_TYPE_DEAD) and IsUnitEnemy(GetFilterUnit(), GetOwningPlayer(GetTriggerUnit())) then
        call IssueTargetOrder(dummy, "sleep", GetFilterUnit())
    endif
    return false
endfunction

private function Actions takes nothing returns nothing
    call SetUnitOwner(dummy, GetOwningPlayer(GetTriggerUnit()), false)
    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)
    set dummy = CreateUnit(Player(0), DUMMY_ID, 0, 0, 0)
    call UnitAddAbility(dummy, MS1_ID)
endfunction

endlibrary
 

hgkjfhfdsj

Active Member
Reaction score
55
btw i found the error (dummy error)
doing some tests atm
- played around with ability – no result
- tested xe's dummy & dummycaster's with yours
- xe's & yours didnt work; dummycaster's worked – not sure why atm
- im testing using GUI (on a mac atm), so it shouldnt change much

tested (and have no effect)
- locust (add on creation; default)
- blend - time
- model (archer; none.mdl, dummy.mdx from xe/dummycaster )
- ability animation names


i uploaded your map + the 2 other dummies, if you wanted to do the testing
atm im just comparing the 3 dummies, and testing out each differences

EDIT
i think i found it
Movement - Speed Base
Movement - Speed Max
Movement - Speed Min

should all be 0.
 

Ayanami

칼리
Reaction score
288
Seems like the movement speed did the trick. I wonder why though o.o.

So, anything else that I can optimize? Or is the code perfectly fine now?

And just asking, what are methods? (scopes, libraries and now methods? Strange names o.o)
 

SineCosine

I'm still looking for my Tangent
Reaction score
77
methods are functions =P
It's the 'code-name' given to them while they're in structs XD

JASS:
//This:
struct STUFF
    static method Message takes nothing returns nothing
        call BJDebugMsg("I am a function, but I am called a method <.<")
    endmethod
endstruct

//Same as:
function Message takes nothing returns nothing
    call BJDebugMsg("I am a function")
endfunction


Except, you can do this with structs and methods:
JASS:
struct DelayedMessageLOL
    string MSG
 
    private method End takes nothing returns nothing
        call BJDebugMsg(MSG)
        call this.destroy()
    endmethod

    static method Start takes string Message, real sleep returns nothing
        set thistype this = thistype.allocate()
        set MSG = Message

        call TriggerSleepAction(sleep) //Ugly, I know
        call End()
    endmethod
endstruct

//Not a very nice example and I am sure I made mistakes <.<
//It can be done easily with:
function Start takes string Message, real sleep returns nothing
    call TriggerSleepAction(sleep)
    call BJDebugMsg(Message)
endfunction

//But just wanted to show that structs can pass data easily =/
 

hgkjfhfdsj

Active Member
Reaction score
55
no idea lol
methods are like functions inside structs except they work with instances
elaborating from the previous post
JASS:
struct Data
unit u

method new takes nothing returns nothing
     call PauseUnit(this.u, true)
     call PauseUnit(.u, false) //'this' refers to the instance the method is dealing with and can be omitted
     // in a way, it makes it compatible with arrays (ie, referencing the index)
endmethod

// so when a method is called, the index is automatically set to whatever it was attached to
// and the . syntax refers to the global array with that index 
endstruct
function actions takes nothing returns nothing
     local Data d = Data.create()
     // d is an instance
     call d.new()
endfunction


static prefix functions exactly like a normal function. in a way it makes it not compatible with arrays, so they cannot reference its members since they do not have an instance (ie an index).

private/public prefix also works with both structs & methods. eg if new was private
JASS:
private method new takes nothing returns nothing
endmethod

then
d.new() will not compile since new is private to the struct, (can only be called in a struct's instance)
 

Nestharus

o-o
Reaction score
84
Ok, I'm going to write this all out so that you can understand structs with ease ; P.


JASS:
method hello takes nothing returns nothing
endmethod


translates into

JASS:
function hello takes integer this returns nothing
endfunction


JASS:
struct Hi
    public method hello takes nothing returns nothing
    endmethod
endstruct


[ljass]call Hi(0).hello()[/ljass]

translates into

[ljass]call hello(0)[/ljass]

JASS:
public static method hello takes nothing returns nothing
endmethod


translates into

JASS:
function hello takes nothing returns nothing
endfunction



Object Orientated programming just uses parallel arrays (your fields in your structs) with functions that take an instance.

JASS:
struct Hi
    public integer boo
    public integer cheese

    public method setBoo takes nothing returns nothing
        set boo = 5
    endmethod
endstruct

function bleh takes nothing returns nothing
    local Hi hi = Hi.create()
    call hi.setBoo()
endfunction


translates into
JASS:
globals
    integer array boo
    integer array cheese
endglobals

function setBoo takes integer this returns nothing
    set boo[this] = 5
endfunction

function bleh takes nothing returns nothing
    local integer hi = create()
    call setBoo(hi)
endfunction



Stub methods use trigger arrays and stores an instance of which trigger to use when calling a method

JASS:
trigger array stubmethods
constant integer stubMethodInstance


Interfaces use trigger arrays and have a constant integer variable within the struct to tell it which trigger in the array to use


structs that extend other structs use delegates to do so (ugly I know). The allocation is a chained allocation rather than basing your own instance off of your root's instance-


instance1 extends instance2 extends instance3 //etc, allocation done at each
vs
instance1 extends instance1A extends instance 1B //allocation done at B

Because of these facts and other facts with vJASS, I always write my stuff from scratch using [ljass]struct NAME extends array[/ljass] to achieve the precise results I want.

To accomplish the same style as extending, use delegates (one extra field I know, but w/e)
[ljass]delegate STRUCT_TYPE name[/ljass]

setting it to an instance of a struct is pretty much like making your struct extend that other struct

JASS:
struct Hello extends array
endstruct

struct Boo extends array
    private delegate Hello helloDel

    public static method create takes nothing returns thistype
        local thistype this = Hello.create()
        set helloDel = this
        return this
    endmethod
endstruct


For multi extension, just pick a delegate to use for your instance.

more edits
After understanding some of the structure to OO programming, you can begin coding OO style collections and what not as well =), but that will be for another day ; P.

final edits
Used to offer free JASS lessons, but someone drove me mad after trying to explain what a variable was to him for like 20 hours straight : D, so now I charge ;o.
 

Ayanami

칼리
Reaction score
288
final edits
Used to offer free JASS lessons, but someone drove me mad after trying to explain what a variable was to him for like 20 hours straight : D, so now I charge ;o.

A variable?! @_@

Anyways, I guess I'll avoid methods and structs for now. I couldn't understand most of your post :p
 

Laiev

Hey Listen!!
Reaction score
188
Nestharus is trying to teach a depth study of struct for one which learn jass now Oo' go slow Nestharus ><
 

Nestharus

o-o
Reaction score
84
A variable?! @_@

Anyways, I guess I'll avoid methods and structs for now. I couldn't understand most of your post :p

Don't avoid structs and methods, they are a great tool and are even better if you can avoid their faults = ).

You do understand that vJASS just translates your code into plain old JASS right?

All of the structs, interfaces, methods, and etc are all translated into plain old JASS. JASS has no structs or methods or anything and it's not magic, lol.

I guess the best way to understand structs would be to take it from the top, allocation and deallocation.
If you want to be able to create new variables and destroy them, how would you do it? Well, you'd probably want an array to start off with so that you could store these variables somewhere = ).

[ljass]integer array intVars[/ljass]

Think of each index on the array as a variable. The above would be 8192 different integer variables.

What if you wanted to create and destroy array variables?

Something like the below?
[ljass]set intVars[instance, index] = 5[/ljass]


Which translates into this common 2D matrix formula
ARRAY_INSTANCE*ARRAY_SIZE+INDEX

The above would be a 2D array, that is the first index would be your regular variable and the second index the index of the array.

[ljass]set intVars[instance*ARRAY_SIZE+index] = 5[/ljass]

What about multi dimensional array vars? Check out how to convert between bases on numbers.


So, back to allocation. For structs, vJASS automatically generates code very similar to this (I leave out isAllocated booleans and what not)

JASS:
//this first one handles struct instances. For example, if you create
//a new instance, the counter is increased and returned.
//If you created 3 instances, this would return 1, 2, and 3
private static integer instanceCount = 0
//this recycles destroyed instances for re use with the same counter
//idea as above. If you destroyed 2, it&#039;d go into recycle[recycleCount]
//and recycleCount would be increased. If recycleCount isn&#039;t 0, 
//then recycleCount is decreased and recycle[recycleCount] is returned
//This means that destroying 2 and then creating a new instance would
//return 2.
private static integer array recycle
private static integer recycleCount = 0

private static method allocate takes nothing returns thistype
    if (recycleCount != 0) then
        set recycleCount = recycleCount - 1
        return recycle[recycleCount]
    endif
    set instanceCount = instanceCount + 1
    return instanceCount
endmethod

private method deallocate takes nothing returns nothing
    set recycle[recycleCount] = this
    set recycleCount = recycleCount + 1
endmethod


The above code would be able to handle your common array instancing.

Now, the above code translated into JASS would look more like (excluding scoping names like STRUCT___var)

JASS:
globals
    integer instanceCount = 0
    integer array recycle
    integer recycleCount = 0
endglobals

function allocate takes nothing returns integer
    if (recycleCount != 0) then
        set recycleCount = recycleCount - 1
        return recycle[recycleCount]
    endif
    set instanceCount = instanceCount + 1
    return instanceCount
endfunction

function deallocate takes integer this returns nothing
    set recycle[recycleCount] = this
    set recycleCount = recycleCount + 1
endfunction

Now from here, we have a unique index for the struct fields (the arrays in the struct)

JASS:
struct bleh
    public integer a
    public integer b
    public integer c
endstruct


to JASS

JASS:
globals
    integer array a
    integer array b
    integer array c
endglobals


The instance we get from allocation is used to manipulate specific indexes for the arrays (remember each array can be treated as 8192 different variables).

So if we wanted to get to variable 1 of a, it'd be a[1], and etc.

When a method is used like this

JASS:
struct bleh
    public integer a
    public integer b
    public integer c

    //struct names makes the index access a specific set of parallel arrays
    //thistype makes it access its own type, like in this case it&#039;d be bleh
    public static method create takes nothing returns thistype
        return allocate() //use allocation method
    endmethod

    public method test takes nothing returns nothing
        set a = 5
    endmethod
endstruct

function tester takes nothing returns nothing
    call create.test()
endfunction


would translate to this

JASS:
globals
    integer array a
    integer array b
    integer array c
endglobals

function create takes nothing returns integer
    return allocate() //use allocation method
endfunction

function test takes integer this returns nothing
    set a[this] = 5
endfunction

function tester takes nothing returns nothing
    call test(create())
endfunction


And that's how structs work in vJASS = p.

This may be a lot to take in, but it'll give you a fantastic understanding of how vjass operates.

Again, vJASS has extra crap and does weird chained instancing, so I always use [ljass]struct NAME extends array[/ljass]. All that does is get rid of everything, meaning you have to code everything from scratch (allocation, deallocation, etc). To me, it's well worth it = ).


Now after this point, we start getting into complicated composite objects as well as billions of collections.

edits
Now I'm sure that any vet programmer and most beginners could have told you what I told you above = ), so keep in mind that these are the absolute basics. I'm no master myself and I do continuously learn new things = D.

There are 1001 ways to do something and each way has its pros and cons.
 

tooltiperror

Super Moderator
Reaction score
231
Or, we can make stucts even simpler and explain them the way they are "supposed" (note the quotes,) to be used.

JASS:

//! fix alignment
  struct Human
      integer age
      string ShirtColor
  endstruct
  function Example takes nothing returns nothing
      local Human Jeff=human.create() // .create is how you make them.
      local Human Bill=human.create() // This creates a new human, Bill.
      set Jeff.age=34 // Setting a variable declared in the struct.
      set Bill.age=23
      set Jeff.ShirtColor=&quot;red&quot;
  endfunction
  /*
        Think of structs just like arrays, because that is all they are.  Each
        human, Jeff and Bill, are integers, just numbers.  Let&#039;s say Jeff is
        human 1, and Bill is human 2.  Jeff.age is age[1].
        Bill.age is age[2], because Bill is the second human.  vJASS compiler,
        JassHelper, takes care of all of this for you.

        The next thing to understand with structs is methods.
  */
  struct Human
      integer age
      string ShirtColor
      boolean alive=true // Setting a variable in the struct changes the default.
      method kill takes Human whichHuman returns nothing // Take a human argument
          set whichHuman.alive=false // Set the argument&#039;s boolean to false
      endmethod // End the method <img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" class="smilie smilie--sprite smilie--sprite1" alt=":)" title="Smile    :)" loading="lazy" data-shortname=":)" />
  endstruct
  // To use the method:
  function Example takes nothing returns nothing
      local Human Tucker=Human.create()
      call Tucker.kill(Tucker)
  endfunction
  /*
        Now, you&#039;re probably thinking, why do I need to take an argument?
        The truth is, you don&#039;t.  That&#039;s why you can use &#039;this&#039; instead.  &#039;this&#039;
        just pretends to be whatever Human you&#039;re using.
  */
  struct Human
      integer age
      string ShirtColor
      boolean alive=true // Setting a variable in the struct changes the default.
      method kill takes nothing returns nothing
          set this.alive=false // Set the used human to dead.
      endmethod // End the method <img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" class="smilie smilie--sprite smilie--sprite1" alt=":)" title="Smile    :)" loading="lazy" data-shortname=":)" />
  endstruct
  function Example takes nothing returns nothing
      local Human Jesus=Human.create()
      call Jesus.kill()
      // Another kill fact: You can destroy any struct with .destroy!
      call Jesus.destroy()
  endfunction
 

Ayanami

칼리
Reaction score
288
Thanks for the explanation Nestharus and ToolTipError. After staring at the wall of text for 30 minutes, I finally digested them.
 

kingkingyyk3

Visitor (Welcome to the Jungle, Baby!)
Reaction score
216
Extra tip for you, use better naming convention, good for your and others' eyes.
Use CAPITAL_LETTER and _ for constant globals.
Use Capital letter for globals and functions. (First alphabets)
Use small letter for locals. (Some will just use globals as locals(Can ignore nulling :p), like Jesus4Lyf, then just put them as small letters.)
Use camelCase for struct members, methods.
 

Ayanami

칼리
Reaction score
288
Extra tip for you, use better naming convention, good for your and others' eyes.
Use CAPITAL_LETTER and _ for constant globals.
Use Capital letter for globals and functions. (First alphabets)
Use small letter for locals. (Some will just use globals as locals(Can ignore nulling :p), like Jesus4Lyf, then just put them as small letters.)
Use camelCase for struct members, methods.

Noted.

And by the way I noticed "static" struct. What's the different between struct and static struct?

And just asking out of curiosity, what does GetHandleInt do?
 

tooltiperror

Super Moderator
Reaction score
231
Static variables in structs are variables that are consistent throughout all instances of the struct.

JASS:
//! fix alignment
  struct Dog
      static boolean DoDogsHaveWings=false
  endstruct
  function Example takes nothing returns nothing
      if Dog.DoDogsHaveWings then
          call BJDebugMsg(&quot;Dogs have wings.&quot;)
      elseif
          call BJDebugMsg(&quot;Dogs lack wings.&quot;)
      endif
      set Dog.DoDogsHaveWings=true
  endfunction


Edit: Also, go on MSN :>
 

Lyerae

I keep popping up on this site from time to time.
Reaction score
105
Static variables in structs are variables that are consistent throughout all instances of the struct.


And in the case of methods, you don't need to create an instance of the struct to call the method.
Just use "structName.methodName" (without quotes).

:thup:
 

tooltiperror

Super Moderator
Reaction score
231
And in the case of methods, you don't need to create an instance of the struct to call the method. Just use structName.methodName, and your good, :thup:

Why not use [LJASS]thistype[/LJASS], instead?
 
General chit-chat
Help Users
  • No one is chatting at the moment.

      The Helper Discord

      Members online

      No members online now.

      Affiliates

      Hive Workshop NUON Dome World Editor Tutorials

      Network Sponsors

      Apex Steel Pipe - Buys and sells Steel Pipe.
      Top