Jass, ngôn ngữ cơ bản của War 3 - Các bạn vào tham khảo

Thảo luận trong 'World Editor' bắt đầu bởi hyaTHa_dk, 9/8/06.

  1. chomap007

    chomap007 Donkey Kong

    Tham gia ngày:
    20/11/06
    Bài viết:
    402
    sao chả ai trả lời em thế pro đâu hết gòi
     
  2. Vua_Do_Hoa

    Vua_Do_Hoa Mr & Ms Pac-Man

    Tham gia ngày:
    30/3/08
    Bài viết:
    217
    Nơi ở:
    Tp Hồ Chí Minh
    Để mình thử chỉ cho nghen >>> Vô Hive >>> vào Tools >>> rồi down cái Jass Craft về. Hết. Mình ko biết sài. bạn dùng thử nếu biết sài chỉ mình với ^^

    Hive là Hiveworkshop.com đấy nhé
     
  3. god_of_the_noob

    god_of_the_noob Mr & Ms Pac-Man

    Tham gia ngày:
    6/3/08
    Bài viết:
    188
    Nơi ở:
    Bốn bể là nhà
    ở đó có 1 đống jass..down cái nào về thì xài dễ nhất:-/:-/:-/:-/:-/
     
  4. Vua_Do_Hoa

    Vua_Do_Hoa Mr & Ms Pac-Man

    Tham gia ngày:
    30/3/08
    Bài viết:
    217
    Nơi ở:
    Tp Hồ Chí Minh
    Ở topic này có còn hoạt đồng ko nếu còn thì xin nghe lời thỉnh cầu của mình với

    jass có những thuật toán nào ... các function nào. các lệnh gì.. cách gọi... v..v.. help
     
  5. thinhlord

    thinhlord Youtube Master Race

    Tham gia ngày:
    21/6/08
    Bài viết:
    6
    hj::), cho minh gioi thieu nha tui ten thinh, tui cung thich thich cai world editor nay, tui cung bit lam may cai quest, tui co doc qua bai cua may ban nhung cung hem hieu:-* may ban co the giai thich hoan dua 1 cai clip len cho minh xem hem:D
     
  6. thinhlord

    thinhlord Youtube Master Race

    Tham gia ngày:
    21/6/08
    Bài viết:
    6
    bo may ban it len mang lem ha, sao lau wa hem tra loi toi:whew:
     
  7. chomap007

    chomap007 Donkey Kong

    Tham gia ngày:
    20/11/06
    Bài viết:
    402
    cho tui hỏi khi làm Jass thì mình phải tạo cac spell ảo ở trong We trước hay sao vậy
     
  8. Vua_Do_Hoa

    Vua_Do_Hoa Mr & Ms Pac-Man

    Tham gia ngày:
    30/3/08
    Bài viết:
    217
    Nơi ở:
    Tp Hồ Chí Minh
    mình nghĩ là phải tạo một spell bằng GUI trước rồi convent sang Jass sau đó chỉnh sửa đó bạn.:hug::D

    ###########################################################3
    Ông chủ Topic ơi làm ơn hoạt động lại đi !!! Cho em học hỏi cách làm Jass của anh với anh HyaTHa_Dk ơi. Hic hic
    vào lại đi, Please !!!:p
     
  9. Vua_Do_Hoa

    Vua_Do_Hoa Mr & Ms Pac-Man

    Tham gia ngày:
    30/3/08
    Bài viết:
    217
    Nơi ở:
    Tp Hồ Chí Minh
    Anh HyaTHa_dk ơi anh có thể giảng tiếp vài bài về jass đc ko anh... anh có thể cho em yahoo đc ko. yahooem là : maivanchauthinh=((
     
  10. hyaTHa_dk

    hyaTHa_dk Mr & Ms Pac-Man

    Tham gia ngày:
    10/4/05
    Bài viết:
    235
    Nơi ở:
    Hà Nội
    vâng, bạn cũng may quá, hôm nay tui vừa vào đổi cái avatar
    ghé vào topic xem chơi thoai nhưng thấy bạn nhiệt tình quá :D nên tui quyết định sẽ tiếp tục hướng dẫn tiếp

    Quên, Y!M của tôi là : sweet_saint_vn

    Hy vọng các bạn ủng hộ
     
  11. Vua_Do_Hoa

    Vua_Do_Hoa Mr & Ms Pac-Man

    Tham gia ngày:
    30/3/08
    Bài viết:
    217
    Nơi ở:
    Tp Hồ Chí Minh
    Sẵn vậy cho em hỏi mấy vấn đề lẻ tẻ ... Nếu anh ko thích trả lời riêng lẻ cũng đươc anh có thể đưa vấn đề em hỏi vào Tut luôn nha anh Hya.

    Vấn đề một là cách sử dụng lệnh globals
    bên trong global mình đc phép dùng cái gì.
    Vấn đề hai : Đa số các bài Tut = tiếng anh đều nhắm đến việc convert GUI trigger sang JASS thì sẽ dễ hơn trong việc học JASS...em đã làm mấy spell = GUI xong conv sang JASS. chuyển những skill đơn giản từ ko MUI sang MUI (MUI là anh Tom chỉ = trigger nhưng Trigger coi bộ khó sài nên em mò JASS) nhưng skill phức tạp thì chịu... Mấy skill có sử dụng loop, sử dụng Group , (VD như sử dụng Group thường thì khá phức tạp khi chuyển sang JASS. em đặt một lệnh UnitGroup = Unit này này ... trong vùg do với điều kiện này này kia kia thì chuyển sang JASS ... eo ơi nó hiện ra 1 trang dài đằng đẵng. Đọc thì nắm đc chút chút.. thắy mắy để chuyển sang skill có MUI thì ọc ọc lỗi cọm luôn)
    Có thể hiện giờ em học JASS chủ yếu để làm Spell vì kiến thức lập trình còn non nớt... hi vọng anh có đủ nhẫn nại để chỉ cho em :D Em sẽ rất biết ơn anh !!! :D
    .
    ___________Auto Merge________________

    .
    À còn nữa. mấy cái "real" trong JASS mình đặc ở đâu thế anh ???
     
  12. Vua_Do_Hoa

    Vua_Do_Hoa Mr & Ms Pac-Man

    Tham gia ngày:
    30/3/08
    Bài viết:
    217
    Nơi ở:
    Tp Hồ Chí Minh
    Giờ tất cả vấn đề trên đều hơi thông suốt rồi nhưng sử dụng chưa nhuyễn anh HyaTha làm ơn vẫn Post Tut tiếp nha...

    _________

    Giờ Mình xin mạng phép gữi một phiên bản tiếng anh của việc học JASS ... các bạn nào có hứng thú với JASS hoặc ko có hứng thú , miễn là giỏi tiếng anh vô đây dịch dùm mình.
    Cám ơn trước. Về phần mình thì bản dịch của mình 100% ko ai hiểu , vì thế mình mới nhờ đến Pà con cô bác trong DIễn đàn này
    _________
    Jass Tutorial

    1.Introduction
    Most of you probably heard of JASS and that it is an efficient way to develop spells. But the real question is probably, what exactly is jass and how can you learn it? Like many other programming languages, JASS is a language developed by Blizzard. If you have basic knowledge in C++, Pascal or any other non-object-oriented programming languages, then this tutorial will be piece of cake. If not, you will have some difficulties but in the end, you will make it. Before continuing with this tutorial, I suggest you first learn how to basically work with triggers. The tutorial will be based on triggering knowledge so without knowing triggers, it is most likely that you won’t get much.

    Try this tutorial about trigger enchanced spells if you don't know how to make this type of spells: http://world-editor-tutorials.thehel...php?view=28117

    Note: If you ever hear the concept of “Custom script” in Warcraft, then that’s an alternative name for JASS.

    Note 2: Before you continue, make sure you have this JASS editor.

    2.Why JASS?
    Simple, because first of all, advanced JASS can help you get multi-instanceable spells. Multi-instaceability is the only way, which can help you in case you want to do normal unit spells and you can’t make them Multi-instanceable with triggers. Multi-instaceability for those who don’t know is the capacity of a spell to be cast by more than one unit of the same player at the same time. Another use of jass is speed. Once you get jass, you can get spells much faster, and to be honest, they are sometimes more efficient. And another thing I noticed about JASS is how to obtain awesome effects like a smooth Knockback. Believe me, I’ve tried with triggers but you’ll never get the awesome effects you will get with JASS.

    Where you shouldn’t use JASS because you don’t need to use JASS at everything. During campaigns when you make quests, cinematics and other things which can be easily done with triggers. You don’t need to bother with JASS because sometimes it can be buggy.

    Where you should use JASS… In totally recommend it in spellmaking, if you want to make cool minigames in maps and of course cool effects. You have more freedom and you are no longer restricted to FOR repetitive actions. If this is not enough for you, just try it and you will not regret.

    3.Functions
    Functions are parts of a program (script) which execute a limited number of actions (they can be made to execute an unlimited number if you use an infinite for but then the script isn’t correct), one after another. Imagine them as the actions of a function, the actions following the singular action “Pick Up Every Unit In Group and do Actions” etc. To create a function you have to use the following structure:

    Mã:
    :
    function name takes nothing returns nothing
    //actions executed by the function
    endfunction
    And now to explain. The words function and endfunction start the function, respectively close it. In place of name you can put the name of the function. It can be anything as long as you don’t leave spaces. "Oz02” is a valid name while “Oz 02” is not a valid one. However, all the functions must have an unique name. If two functions have the same name in the whole map then you will get an error (this includes different scripts).

    Note: Comments in JASS must have “//” before them. Everything on the row after the “//” is ignored by the script.

    Between “function” and “endfunction” you can put all the actions you want that function to execute. Take them as the actions of a trigger by now.

    Note: You may create as many functions as you like, but keep in mind that you cannot create a function into another function. Example:

    Mã:
    function sleep takes nothing returns nothing
      function entangle takes nothing returns nothing
      endfunction
    endfunction
    This is not a valid script. A correct script would be like this:

    Code
    function entangle takes nothing returns nothing
    endfunction
    function sleep takes nothing returns nothing
    endfunction4.Executing a function
    Functions must be executed just like triggers. But unlike triggers they must be directly called and do not start to execute if a certain event takes place. Consider them as an initially off trigger which can be executed only through
    Quote:
    Run Trigger Ignoring Conditions

    action. There are exceptions of such functions, which will be mentioned later.

    To call a function, you must use the following structure:

    Code:
    call FUNCTION_NAMEAgain, name is the name of the function.

    A function can call another function but keep in mind that the function called must appear into the script before the “calling” function.

    The following script is incorrect:

    Code:
    function sleep takes nothing returns nothing
    call entangle
    endfunction
    function entangle takes nothing returns nothing
    endfunctionThe following script is correct:

    Code:
    function entangle takes nothing returns nothing
    endfunction
    function sleep takes nothing returns nothing
    call entangle
    endfunctionAll the actions you execute in triggers are functions as well. They are premade actions and can directly be called.
    Example: the function “TriggerSleepAction” is the wait function but it will be explained later.

    Note: Your functions’ name may not be the name of a premade function. To see all the premade functions look into the JASS editor.

    5.Variables
    Variables are labeled places in the memory which store a certain value. By being labeled, they obviously have a name just like functions. Like in GUI (triggers), there are many types of variables. The most important ones are:

    Quote:
    lightning – lightning in gui
    location – point in gui
    unit – unit in gui
    effect – special effect in gui
    item – item in gui
    doodad – destructable in gui
    timer – timer in gui
    group – unit group in gui
    trigger – triggers themselves in gui (this will be discussed later)

    integer – integer in gui
    real – real in gui
    boolean – boolean in gui
    force - player groups in gui

    There are two types of variables:
    a) Local variables – variables declared in functions and which can be used only in that certain function. To declare a variable you must use the following syntax:

    Code:
    local <VARIABLE_TYPE> <VARIABLE_NAME>.
    Type is the type of the variable and name is the name of the variable. Keep in mind that you can’t have more than one local variable with the same name in the same function. However, you can have local variables with the same name, as long as they are in different functions. Example:

    Code:
    function sleep takes nothing returns nothing
    local unit cast
    endfunction
    function entangle takes nothing returns nothing
    local trigger cast
    endfunction
    function arrow takes nothing returns nothing
    local unit cast
    endfunctionTo refer to local variables just use their name. We will discuss referring in the next chapter.

    Warning: locals must be declared at the beginning of the function before any other actions are executed. The following example is wrong:

    Code:
    function entangle takes nothing returns nothing
    endfunction
    function sleep takes nothing returns nothing
    local trigger t
    call entangle()
    local unit cast
    endfunctionb) Global variables – the normal GUI (trigger) variables, created just like you created them when you used triggers. To refer to global variables use the structure “udg_name” where name is the name of the global variable.

    Note: Local and Global variables can have the same name. They won’t get confused because globals are referred with the udg_ in front of them while locals are referred only through their name.

    There is also a special variable type called handlers. This type of variable exists and can be used only as local. It is special because it can store all kind of variables. I personally experimented only with doodads, items and units but it should work with most of the variable types. However, I doubt that it works with integer and real.

    6.Decisional and Repetitive structures
    Let’s talk a little bit about the decisional (if) and repetitive (loop) structures.

    a) Decisional structure
    Decisional structure in JASS is pretty simple. It has the following structure:

    Code:
    if <condition> then
    //Actions then
    else
    //Actions else
    endifNote: The condition was put between <> so you can see it better. The script itself must not include the <>.

    Ok, the condition must be a comparision. If that comparision is true, then the “actions then” are being executed. If not, the “actions else” are executed. However, keep in mind that the else is not mandatory. But if you don’t put an else, don’t put the “Actions else” either. Also, don’t forget the endif because it closes the if.

    b) Repetitive structure
    For JASS, we only have the while structure in C++ and Pascal, which here is called “loop”. It has the following syntax:

    Code:
    loop
    exitwhen <condition>
    //Actions
    endloopWARNING!: If you forget the endloop and you don’t close the loop, then the WE will cause a crash and you will lose all the data if you didn’t save before starting to work on the loop. So make sure you close each loop you start.

    Not much to say. The loop makes the actions repeat until the comparision after the “exitwhen” returns true. Until then, it will keep executing the actions.

    7.Functions which take and/or return a value
    By now we have talked only about plain functions which take and return no value. Such functions rarely exists and are usually used in triggers (yes… we are going to use triggers in JASS as well so practically the “trigger method” will be mentioned from now only as GUI so we don’t mix them up.

    Ok, I told you before that the structure of a function begins with “function name takes nothing returns nothing”. In reality, in place of the two nothings you can put one or more variable types (followed by the variable’s name in the case of the taken variables). The variables after the takes are values which are taken by the function when you call it, while the ones after return are values returned by the function.

    Note: Functions may return only one value.

    Let’s take an example of function, which takes a value. In this function we will work for good with some variables, I will show you a premade function (those functions which are actions in GUI) and show you how to call a function which takes a value.


    Code:
    function remove takes unit cast, real wait returns nothing
    call TriggerSleepAction(wait)
    call RemoveUnit(cast)
    endfunction

    function start takes nothing returns nothing
    call remove(udg_caster, 1.00)
    endfunctionLet’s analyze this jass script a bit. The start function calls the remove function and it includes the two parameters. As you can see, the parameters are placed between brackets and are separated between each other through a coma. The first parameter is another global variable, while the second one is a real constant.

    Note: Constants are values, which don’t change their value no matter what.

    Let’s have a look into the second function. As you can see the cast and wait values no longer need to be mentioned as locals. That is because all taken values are already considered locals. And now let’s look at the premade functions.

    As I mentioned before, the call TriggerSleepAction function is a wait, and makes the function wait a number of seconds before going further. The value in the brackets (a parameter) is the number of seconds you have the TriggerSleepAction waits.

    Note: the minimum parameter for the wait is 0.10. If you put lower, it will be automatically set to 0.10 when the function is executed.

    The second function “RemoveUnit” is the gui “Unit – Remove Unit’ action and like there, it removes the parameter unit. In this case, it removes the “cast” local unit.

    Warning! Everytime you call a function, which takes a value you must put mention all the parameters and the parameters must have the same type as the values taken into the function called.

    In the case of returning a value, the returned value must be either taken into consideration either into a logical expression or stored into an integer. Let’s take another example:

    Code:
    function condition takes unit cast returns boolean
    return IsUnitDeadBJ(cast)
    endfunction

    function start takes nothing returns nothing
    call TriggerSleepAction(0.01)
    if condition(udg_cast)==true
    call RemoveUnit(udg_cast)
    endif
    endfunctionWhen function start begins, it waits 0.10 seconds (because values under 0.10 in TriggerSleepAction are taken as 0.10) and then it calls the condition function. Since the function takes a value, the call has a parameter as well.

    The second function returns a boolean. This means that it will return a boolean value. It uses the function IsUnitDeadBJ(cast) which checks if an unit is dead. If that unit is dead, then it returns true. If not, if returns false. Moreover, the function returns the value returned by the IsUnitDeadBJ function itself. If it sounds too complicated, try to imagine that in place of the function, there is a boolean value, the value which is actually returned by that function.

    And lastly, you have the return followed by the value returned. This makes your function return a value. Keep in mind that the value after the return must be the same value returned by the function itself.

    Observation: Once your function returns a value, it will skip over all its further actions.

    Note: You don’t and mustn’t use the call before functions whenever you directly use the value of that function. If you don’t use the value returned by the function, you can use the call.

    Warning: Everytime a function must return a value, you must assure that it returns that value. If you don’t, it will make the WE crash. There are some strange situations in which, even though the function should always return a value, you get an error. Let’s have a look at the example below:

    Code:
    function bool takes nothing returns boolean
    if udg_a==true then
    return true
    else
    return false
    endif
    endfunctionStrangely, the WE doesn’t take in consideration that a value is returned anyway. It will crash. So you must assure that you have a return outside any FORs, Ifs and other such structures. This will prevent crashes. The IF trap is the most common and most annoying. So be careful!

    8.Working with variables
    This chapter is also very important because we are going to learn how to give variables a certain value. Let’s take the following example:

    Code:
    function entangle takes nothing returns nothing
    local unit cast
    set cast = GetTriggerUnit()
    call RemoveUnit(cast)
    endfunctionWhat does it do? We take a local unit with the name cast. Now, we can give variables a value by typing “set”, leave a blank and then the name of the variable. After that we have an “=”, and then what you give that variable. In this case we gave it the value of the function GetTriggerUnit(). This function is another premade and returns the Triggering Unit (GUI). After that we removed the cast unit.

    I wrote down the most important such premade functions which work fine with unit variables.

    Quote:
    GetTriggerUnit() = Triggering Unit
    GetEventDamageSource() = Damage Source
    GetLastCreatedUnit() = Last Created Unit
    GetAttackedUnitBJ() = Attacked Unit
    GetAttacker() = Attacking Unit
    GetSpellAbilityUnit() = Casting Unit
    GetDyingUnit() = Dying Unit
    GetEnteringUnit() = Entering Unit
    GetManipulatingUnit() = Hero Manipulating Unit
    GetKillingUnitBJ() = Killing Unit
    GetOrderedUnit() = Ordered Unit
    GetSummonedUnit() = Summoned Unit
    GetSummoningUnit() = Summoning Unit
    GetSpellTargetUnit() = Target Unit of Ability Being Cast
    GetOrderTargetUnit() = Target Unit of Issued Order

    Note: GetSpellTargetUnit(), GetOrderTargetUnit() and other such functions do not return a value after a GetTriggerSleepAction() no matter how small it is (how short it lasts). Exception is GetTriggerUnit(). That is why I suggest you store all the units you will need into local variables.

    9.Triggers
    Ok, by now we haven’t worked with real JASS scripts, but with small parts. If you would try these scripts, you would probably get a series of errors or atleast they wouldn’t work. That is because your functions must be first triggered by something. So yes, triggers exist in JASS as I said before. There are two types of triggers: Global triggers (the ones seen in GUI) and Local triggers. We will talk first about global triggers and of course, how to create your first JASS script.

    a) Global triggerss
    First thing’s first. Create a GUI trigger. Give it as an event, “An Unit Starts the Effect of an Ability” and as a condition “Ability Being Cast equal to Sleep”.

    Now, you will be amazed how simple can JASS be. Go to Edit – Convert to Custom Text and click on “Ok”. Custom script will appear in the right. Amazing, eh? Let’s have a look at it.


    Code:
    function Trig_Untitled_Trigger_001_Conditions takes nothing returns boolean
    if ( not ( GetSpellAbilityId() == 'AUsl' ) ) then
    return false
    endif
    return true
    endfunction

    function Trig_Untitled_Trigger_001_Actions takes nothing returns nothing
    endfunction

    //===========================================================================
    function InitTrig_Untitled_Trigger_001 takes nothing returns nothing
    set gg_trg_Untitled_Trigger_001 = CreateTrigger( )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_Untitled_Trigger_001, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddCondition( gg_trg_Untitled_Trigger_001, Condition( function Trig_Untitled_Trigger_001_Conditions ) )
    call TriggerAddAction( gg_trg_Untitled_Trigger_001, function Trig_Untitled_Trigger_001_Actions )
    endfunctionIt looks terrible and perhaps you don’t get a lot of stuff. So let’s have a look at it together. It starts with a conditional function, which returns a boolean. It uses a function GetSpellAbilityId() which gets the rawcode of the ability being cast. This function returns a a rawcode so imagine in place of it a rawcode. Now, if the rawcode returned is equal to ‘Ausl’ then the function will return a false value and will skip remaining actions. It doesn’t sound correct, doesn’t it? But look at the not in front of the equality. It actually negates the value of the equality. So if the equality is true, it returns a false value. Not very efficient but later I will teach you how to make it simpler. Blizzard like to complicate themselves.

    Back to the function, if it doesn’t return the false value, the function will continue, it will exit the if and will return a true value.

    The second function represents the actions of your trigger. By now it is empty because you didn’t input any actions. We will discuss this chapter later as well.

    And now the function follows some strange comment. It separates the functions with the global trigger. Let’s look beyond them. The function following is like a trigger. It activates at the initialization of the map. It must have the same name as the trigger. I haven’t manipulate such functions before so you don’t have to worry about them just by now.

    Below you will see a global trigger being created. Note that all triggers must be created before they can be used. Before that, they will simply exist as variables but they will never be used. The same goes with timers.

    Now, we have three interesting functions, which will be frequently used. The first registers an event. The second one registers conditions. The third one registers an action. They are more complicated so we will take them one by one. Before we start, open the JASS Editor.

    I. Functions registering events
    It is obvious that there are very many events but once you learn how to work with them, it will be very simple. All events start with the following syntax:

    Quote:
    TriggerRegister

    .
    The syntax is then followed by different keywords. To see all the events existent type into the JASS editor TriggerRegister. Make sure that the “functions” button is pressed. To make it easier, if you still don’t get which event is which, make a GUI trigger, put the event you want and then convert the GUI trigger. You will see the event in JASS.

    Note: You can register as many events you like. Let’s take an example:

    Code:
    function main takes nothing returns nothing
    set gg_trg_t = CreateTrigger()
    call TriggerRegisterAnyUnitEventBJ( gg_trg_t, EVENT_PLAYER_UNIT_DEATH )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_t, EVENT_PLAYER_UNIT_SPELL_EFFECTIn this trigger, we have two events: one, which activates when an unit dies and the other when an unit starts the effect of an ability. Usually all event initialization functions have as a first parameter the name of the trigger. After that it depends on the event. I cannot really tell you much about this chapter. Just experiment by converting from GUI. I am only helping you implement these.

    II. Functions registering conditions
    These functions are much simpler and much easier to explain. We have already talked about them into the “Functions which take and/or return a value” chapter. Check it if you are unsure yet.

    Now, the structure to add a condition is only one:

    Code:
    call TriggerAddCondition(trigger_name, Condition (function name))In place of trigger_name you will put the name of the trigger whose Condition it will be. In place of function name you will put the function which will check a certain condition.

    Warning: in this case, the function which will take place of the condition may not take any values (parameters). That is why you won’t be able to transfer locals from one trigger to another, atleast not yet.
    Note: the condition function MUST return a boolean value. If it doesn’t, you will get an error.

    Again, you have to experiment here before you can get good results. I will show you how to obtain efficient conditions, and not inefficient ones (like Blizzard uses). We will take a more elaborated trigger, which activates only when an unit casts a certain ability.


    Code:
    function Cond takes nothing returns boolean
    return GetSpellAbilityId() == ‘A000’
    endfunction

    function trigger takes nothing returns nothing
    set gg_trg_t = CreateTrigger()
    call TriggerRegisterAnyUnitEventBJ( gg_trg_t, EVENT_PLAYER_UNIT_SPELL_EFFECT)
    call TriggerAddCondition(gg_trg_t, Condition(function Cond))
    endfunctionExamining it is simple. The first function returns the value returned by the equality GetSpellAbilityId() == ‘A000’. About the second one, it creates the global trigger and adds the event and the condition. If you’re having problems try to

    Warning: You can add only one condition! But you can manipulate them into the function better!

    III. Functions registering Actions

    This is the shortest and simplest chapter. It works like conditions but has a slightly different syntax:

    Code:
    call TriggerAddAction(trigger_name, function name)So practically you no longer need the Condition in front of the function name. That is all. And now I will take a more complex trigger, which simply kills the target unit when attacked:


    Code:
    function Cond takes nothing returns boolean
    return GetSpellAbilityId() == ‘A000’
    endfunction

    function Act takes nothing returns nothing
    local unit targ
    set targ = GetSpellTargetUnit()
    call KillUnit(targ)
    endfunction

    function main takes nothing returns nothing
    set gg_trg_t = CreateTrigger()
    call TriggerRegisterAnyUnitEventBJ(gg_trg_t, EVENT_PLAYER_UNIT_SPELL_EFFECT)
    call TriggerAddCondition(gg_trg_t, Condition(function Cond))
    call TriggerAddAction(gg_trg_t, function Act)
    endfunctionNote: You can add only one action. Moreover, the function must not take or return any value.

    b) Local triggers
    There are triggers, which can be created and declared into functions. In this way, they can take place only for certain units, and you can make this multi-instance by using the locals. Local triggers work just like globals, which some slight differences:

    Code:
    function Remove takes nothing returns nothing
    call RemoveUnit(GetTriggerUnit())
    endfunction

    function act takes nothing returns nothing
    local trigger t
    set t = CreateTrigger()
    call TriggerRegisterUnitEvent(t, GetTriggerUnit(), EVENT_UNIT_SPELL_ENDCAST)
    call TriggerAddAction(t, function Remove)
    endfunctionNot very complex. The second function has a local trigger. It activates when the Trigger Unit of the function stops casting an ability. The action of the trigger is function Remove, which actually removes the Triggering Unit of that function, which is of course the Triggering Unit in the second function who stops casting an ability.

    10.Variable Leaking
    One disadvantage of variables (either units, doodads, items, triggers or anything else except numeric values like integers and reals) is that they leak. What does this mean? That even after they are used, if not removed properly from the memory, they will remain there and so, consume your resources. Too many JASS triggers that leak can cause extreme lag of the map, thing unwanted by any programmer. So how can we prevent leaking?

    a) Nullify variables after they have been used
    Not very suggestive the title, isn’t it? Ok, the whole idea is to actually get the variable out of the memory by setting its value to what it has initially been before the trigger was executed. That value is called “null” and it obviously means that the variable is empty, that it doesn’t contain anything. Let’s take an example;


    Code:
    function Trap takes nothing returns nothing
    local unit cast
    set cast = GetTriggerUnit()
    call TriggerSleepAction(1.50)
    call RemoveUnit(cast)
    set cast = null
    endfunctionAt the beginning of the function where we declared the variable through the syntax “local unit cast”, the cast variable received the value null. This means that it doesn’t occupy anything in the memory but its type. However, when we gave the variable a value (Triggering Unit), we stored that certain unit into the memory under a label: the name of the variable. After the wait we have removed the unit. However, the memory still contains something, even though the unit is removed. And so, we need to give it the initial value: null.

    I’m not really sure that if you remove the unit, it will still leak but one thing is clear: if you want to manipulate the “Target Unit of Ability Being Cast”, and manipulate it through waits, your only option is locals (or globals which btw, will soon be almost completely out whenever you will se JASS). If you don’t actually remove the Target Unit of Ability Being Cast, it is clear that it will remain in the memory, stored through the variable. And then the only way to remove it from the memory, is to nullify the variable.

    Note: You may not nullify integer and real variables, even if you want to. That is because they don’t leak.

    b) Destroying timers, effects, lightning and triggers
    In some cases, simply nullifying a variable is not enough. This is the case of the timers, special effects, lightning and triggers. In their case, you will have to destroy them before you can remove them. Why is that? Because for example, triggers are more than simple objects. They activate depending on certain actions and so, they don’t depend on themselves like objects do. So how do you destroy these things?

    Quote:
    Timers – call DestroyTimer(name)
    Effects – call DestroyEffect(name)
    Lightning – call DestroyLightning(name)
    Triggers – call DestroyTrigger(name)

    I can tell you that in the case of the timers for example, if they are repetitive and they call a certain action after each expiration, they will continue to repeat and call that action even if you nullify the variable in which they are stored. In case of triggers, they will start to occur even if you nullify the variable. Special Effects and Lightning cause severe lagging if they are not destroyed once they have been used. Try to use a spell with many Special Effects. Summon that spell more than once but let the effects be removed before summoning it again. You will notice that after some time the game will start to lag.

    Note: You MUST NOT nullify the variables before you destroyed what they contained. If you do so, you will not be able to destroy that anymore. Example:

    Code:
    function Remove takes nothing returns nothing
    call RemoveUnit(GetTriggerUnit())
    endfunction

    function triggy takes nothing returns nothing
    local trigger t
    set t = CreateTrigger()
    call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SPELL_EFFECT)
    call TriggerAddAction(t, function Remove)
    call TriggerSleepAction(10.00)
    set t = null
    call DestroyTrigger(t)
    endfunctionThis trigger removes any unit that starts the effect of an ability. However, usually it should be destroyed after the 10 seconds, making it to no longer exist. But in this case, you first nullified the variable and THEN you destroyed the trigger. That is why the trigger will not be destroyed because you will practically destroy something null.

    To find out more about leaks, check this Tutorial. Its the best about leaks I've ever seen.

    11.Timers
    Timers work somehow like triggers but the only difference is that they start the actions after a period of time, regardless of the circumstances. Moreover, they can start that action more than one if they are repetitive timers. And to make things greater, the timers do not take in consideration the 0.10 seconds limit which is set for TriggerSleepAction(). They can be pushed down to 0.01 and that is why you can obtain smooth effects like knockbacks, and moving units again smoothly. Let’s take the following script. It may look very complex but in reality, you mostly know what happens.


    Code:
    function Cond takes nothing returns boolean
    return GetSpellAbilityId() == 'A000'
    endfunction

    function Knockback takes nothing returns nothing
    call SetUnitPositionLoc(udg_targ, PolarProjectionBJ(GetUnitLoc(udg_cast), DistanceBetweenPoints(GetUnitLoc(udg_cast), GetUnitLoc(udg_targ))+10, AngleBetweenPoints(GetUnitLoc(udg_cast), GetUnitLoc(udg_targ))))
    endfunction

    function Start takes nothing returns nothing
    local timer t
    set udg_cast = GetTriggerUnit()
    set udg_targ = GetSpellTargetUnit()
    set t = CreateTimer()
    call TimerStart(t,0.03,true,function Knockback)
    call TriggerSleepAction(2.00)
    call DestroyTimer(t)
    set udg_cast=null
    set udg_targ=null
    set t = null
    endfunction

    function InitTrig_trigger takes nothing returns nothing
    local trigger t
    set t= CreateTrigger()
    call TriggerRegisterAnyUnitEventBJ( t, EVENT_PLAYER_UNIT_SPELL_EFFECT)
    call TriggerAddCondition(t, Condition(function Cond))
    call TriggerAddAction(t, function Start)
    endfunctionWarning: In order to make the spell work you need to follow these instructions:
    - Base your spell off cripple and make sure it is the only and first spell created in your map so it can have the rawcode ‘A000’
    - Make sure that the name of the trigger is trigger. The name is case sensitive so be careful.
    - Make sure that you have two global unit variables with the following names (they are case sensitive as well): cast and targ.

    Analysis is necessary here. You probably get the conditional function and the last one so we’ll get to action function called Start. Well, we took the two global variables and gave them the values of the target unit, respectively, triggering unit. To make this multi-instance (locals), we need to study the chapter Handlers which by now is a little bit too advanced I will update this tutorial later once I assure it is efficient and that you understand everything by now.

    Now, we have a timer which we create to last 0.03 seconds, be repetitive (the yes), and once it expires, to have him start the function Knockback. We can say that it works just like a timed trigger but which works better since it is repetitive. We then have a 2 seconds wait, so practically the timer will launch 66 times. After that, we destroy the timer to assure that it no longer launches and after that we set both the globals and the local to null, to save memory.

    As for the Knockback function, it may look bizarre but again, it is very logical. Everytime it is launched it moves the targeted unit instantly (SetUnitPosition function) using the Polar Offset (PolarProjectionBJ in JASS). The Polar Offset function also has the following parameters: The center point (position of the casting unit), the distance between the first and the second point (which in this case it is the distance between the two units + 20) and the angle between the two points (which is the same because the unit is only pushed back so it retains its angle). I hope you got it!

    12. Pick Up Every Unit
    I’ve decided to make a separate section for this function since it is very tricky and only if you take a smart alternative, you can obtain multi-instanceability. Only lately I’ve discovered it. Thanks to Vexorian to clearing things up!

    This time, we are going to use the group variable. We are going to take the following script. It is an AoE sleep, which causes all the units in an area of effect to get affected by sleep. Before we begin, I suggest you have a dummy unit, a dummy spell based off silence with 0.01 duration and a sleep spell for the dummy unit. I will consider the following rawcodes:

    Quote:
    dummy – ‘h000’
    sleep - ‘ A001’
    mass sleep (silence) – ‘A000’

    And now let’s make the script. Your trigger will be called masssleep (CASE SENSITIVE).

    Code:
    function Cond takes nothing returns boolean
    return GetSpellAbilityId()==’A000’
    endfunction

    function Mass_Sleep takes nothing returns nothing
    local group g
    local unit u
    local unit cast
    local unit dumb
    local location p

    set cast = GetTriggerUnit()
    set p = GetSpellTargetLoc()
    set g = GetUnitsInRangeOfLocAll(800.00, p)
    loop
    set u = FirstOfGroup(g)
    exitwhen u==null
    if IsUnitEnemy(u, GetOwningPlayer(cast))==true then
    call GroupRemoveUnit(g,u)
    set dumb = CreateUnitAtLoc(GetOwningPlayer(cast), ‘h000’, GetUnitLoc(u), 0.00)
    call IssueTargetOrderBJ(dumb, “sleep”, u)
    call UnitApplyTimedLifeBJ (1.50, ‘BTLF’, dumb)
    set dumb = null
    endif
    endloop

    set g = null
    set u = null
    set cast = null
    set p = null
    endfunction

    function InitTrig_masssleep takes nothing returns nothing
    local trigger t
    set t=CreateTrigger()
    call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SPELL_EFFECT)
    call TriggerAddCondition(t, Condition(function Cond))
    call TriggerAddAction(t, function Mass_Sleep)
    endfunctionMuch to explain but hopefully this information will help you. I’ll go directly to the actions. The function GetUnitInRangeOfLocAll gets all the units in the range of a point. If you wanted to select only the enemy ones, you would’ve needed to use another function, and for that you would’ve lost the target point.

    Now, FirstOfGroup gets the first unit into an unit group. It doesn’t matter which is the first unit since in the end we will get all of them. Now, you will wonder why I gave the variable u the value of FirstOfGroup(g) both outside and inside the loop. If I would’ve given it the value only inside, the unit would’ve been null when we would’ve entered the loop. And since the condition that u==null would’ve been true, the loop would’ve been skipped.

    IsUnitEnemy function checks if a certain unit is an enemy of a player. GetOwningPlayer gets the owner of a unit, in this case the Triggering Unit stored into a variable. Function GroupRemoveUnit removes an unit from a group. If I wouldn’t have done this, then everytime the loop would’ve selected the first unit into the group which would the already stored in u and so, it would keep picking u and storing it into himself. If you remove it from the group, then another first unit would appear in the group. Keep in mind that if there are no units left into the group, then u will be null. That is the trick of ending the loop when u is null.

    Now, about creating the dummy unit, CreateUnitAtLoc function doesn’t allow you to use GetLastCreatedUnit() so you can get it after it was created. The function itself returns a value but it doesn’t matter since you could’ve still used it in the form “call CreateUnitAtLoc” but in this way you wouldn’t have been able to track that unit anymore. The ExpirationTimer function assures that the unit disappears after a number of seconds. Usually this was made before to achieve multi-instanceability. In this case, keep in mind that the dummy unit cannot be detected after the loop repeats because another unit is created and another unit is stored into that variable.

    You can notice that then I nullified all variables except u because when you exited from the loop, it was already null.

    13.Arrays
    Arrays are close to any other programming language. The only problem in JASS is that you cannot have more than a unidimensional array. So you cannot obtain matrixes, atleast in the nice and classical way. Let’s see how variables are declared and used:

    Code:
    local unit array a
    set a[0]=GetTriggerUnit()
    set a[1]=GetDamageSource()So you declare them with the syntax local, variable type, array, variable name. And to get them you use the variable’s name and then the parameter where you stored the value. That’s all you have to know about arrays.

    Note: Arrays in JASS cannot be transmitted as parameters to other functions.
    Advice: Unit Groups are better than unit arrays because you already have special native functions designed for them.

    14. Conclusions

    I suggest you experiment with premade functions and JASS since this only gives you an idea of what custom script means. It’s up to you to experiment further actions. Everytime you can’t get an action, combine the JASS editor and the conversion from GUI to JASS. Even I use it sometimes since it is impossible to remember so many functions.
     
  13. hyaTHa_dk

    hyaTHa_dk Mr & Ms Pac-Man

    Tham gia ngày:
    10/4/05
    Bài viết:
    235
    Nơi ở:
    Hà Nội
    2 all

    Bắt đầu bài số 1 luôn nhé :x

    À mà quên, do lượng time của tui cũng có hạn nên tui quyết định post thử
    5 bài nhằm

    GIÚP CÁC BẠN MỚI HỌC WORLD EDITOR
    CÓ THỂ LÀM THÀNH THẠO SPELL MÌNH MONG MUỐN
    BẤT KỂ = TRIGGER, hay = JASS


    Bắt đầu bài số 1 luôn nào .....
    Lưu ý là mình sẽ cố gắng tối giản đến mức thấp nhất, câu lệnh để

    CÁC BẠN DỄ HÌNH DUNG CÁCH HOẠT ĐỘNG CỦA ĐOẠN CODE

    ------------------------------------------------------------------------
    BÀI 1: Some Trigger Base Spell
    ------------------------------------------------------------------------

    Cụ thể ở bài này chúng ta sẽ xoay quanh việc làm 1 spell

    - Cast "Chain Lightning"
    - Lightning khi jump thì mang theo những thuộc tính như: Frost Nova, Slow, Pủge ...., và nhiều cái khác nữa...

    _/_/_/_/_/_/_/
    _/CÁCH LÀM:_/
    _/_/_/_/_/_/_/

    --------------------------------------------
    Ở Jass: khá phức tạp
    + 1 là bạn phải tự động tạo lightning effect, sau đó có đồng hồ 0.01s move lightning
    + cũng phải tự động pick unit gần với unit vừa bị ăn "chain lightning" và deals damage
    + Kèm theo việc trên là 1 Caster Unit cast thêm những buff mà tôi kể ra ở trên
    ....
    --------------------------------------------

    ==> Nói chung là khá phức tạp, hơn nữa việc fix spell này đối với NEWBIE như chúng ta là rất khó vv...

    -----------------------------------------------------
    Ở Trigger thì mọi chuyện khá đơn giản:

    + Chúng ta nhờ Blizzard làm tất cả mọi chuyện từ A-Z( kể cả lightning effect, buff)

    + Blizzard sẽ cho chúng ta những event để chúng ta chỉ việc dùng dummy cast thêm buff mà chúng ta muốn

    + Việc chỉnh sửa nói chung là dễ như ăn kẹo vậy

    + Map TRIGGER về bài này có ở dưới cùng của bài viết

    -----------------------------------------------------


    _/_/_/_/_/_/_/_/_/
    _/Nội dung Map:_/
    _/_/_/_/_/_/_/_/_/

    Object Editor:

    -1 Caster spell + 1 Frost Caster

    -Chain Lightning Spell Base on Orc Hero Spell :
    ++++++Có damage = 0.01
    ++++++Chỉnh 1 số Effect Lightning, + 1 số buff


    Map gồm 2 trigger:
    + Chain Lightning 1
    + Chain Lightning 2


    Chain Lightning 1
    - Events
    - Unit - A unit Starts the effect of an ability

    - Conditions
    - (Ability being cast) Equal to Chain Lightning

    - Actions
    - Unit Group - Pick every unit in (Units within 2000.00 of (Position of (Target unit of ability being cast))) and do (Actions)
    - Loop - Actions
    - Trigger - Add to Chain Lightning 2 <gen> the event (Unit - (Picked unit) Takes damage)


    -Chain Lightning 2
    - Events - Không có

    - Conditions
    - (Damage taken) Less than or equal to 0.01
    - (Level of Chain Lightning for (Damage source)) Greater than 0

    - Actions
    - -------- Nova Frost --------
    - Unit - Create 1 Frost Caster for (Owner of (Damage source)) at (Position of (Triggering unit)) facing Default building facing degrees
    - Unit - Add Frost Nova (Neutral Hostile) to (Last created unit)
    - Unit - Order (Last created unit) to Undead Lich - Frost Nova (Last created unit)
    - -------- Nova Frost --------
    - -------- Slow --------
    - Unit - Create 1 Caster Spell for (Owner of (Damage source)) at (Position of (Triggering unit)) facing Default building facing degrees
    - Unit - Add a 2.00 second Generic expiration timer to (Last created unit)
    - Unit - Add Slow (Neutral Hostile) to (Last created unit)
    - Unit - Order (Last created unit) to Human Sorceress - Slow (Triggering unit)
    - -------- Slow --------
    - -------- Deal Chain Lightning Dam = 10 each Unit --------
    - Unit - Cause (Damage source) to damage (Triggering unit), dealing 10.00 damage of attack type Spells and damage type Normal
    - -------- Deal Chain Lightning Dam = 10 each Unit --------


    NẾU ĐỌC ĐẾN ĐÂY VẪN CHƯA HIỂU THÌ CÁC BẠN ĐỌC TIẾP :x

    <><><><><><><><><><><><><><><><><><><><><><><><><><><>
    Trigger 1: "Chain Lightning 1"

    - Event:
    Khi có Unit nào đó bắn spell

    - Condition
    Spell bắn ra là spell "Chain Lightning"

    - Action
    Lấy tất cả những Unit trong vòng bán kinh 2000 range và:
    ++++++ Thêm vào Trigger"Chain Lightning2" Event : Unit đó bị ăn damage
    <><><><><><><><><><><><><><><><><><><><><><><><><><><>

    Theo trigger trên thì spell chain lightning của chúng ta deal: 0.01 damage(coi như ko ảnh hưởng gì đến máu của unit enemy)

    Và khi nào bất kỳ unit nào xung quanh Hero bị ăn 0.01 damage suy ra ==> Unit đó bị trúng chain lightning

    Khi đó Trigger "Chain Lightning2" sẽ thực hiện những gì bạn muốn ở những unit bị trúng chain lightning, đó là lý do vì sao Trigger "Chain Lightning 2" ko có Event

    Trigger "Chain Lightning 2" sử dụng 3 biến "Damage source" (Hero gây nên damage) , "Triggering unit" (Unit bị trúng chain lightning)"Damage taken" (lượng damage mà "Triggering unit" ăn phải)


    <><><><><><><><><><><><><><><><><><><><><><><><><><><>
    Trigger 2: "Chain Lightning 2"
    - Event:
    Ko có nhưng chúng ta ngầm hiểu nó là khi Unit bị ăn damage(do trigger 1 chuyền EVENT vào)

    - Condition
    ++Lượng damage mà Unit nhận là nhỏ hơn hoặc bằng 0.01
    ++Level Chain Lightning của "hero gây dam" > 0 (tức là hero có Ability Chain Lightning)

    - Action
    ======================================================
    Dưới chỉ là dòng lệnh thường để 1 Caster Spell cast vào unit bị ăn dam
    ======================================================

    - Tạo "1" "Frost Caster" cho "Hero gây damage" tại vị trí của "Unit bị ăn dam"
    - Thêm cho "unit vừa tạo"(chính là unit frost caster ở trên) ability "Frost Nova"
    - Ra lệnh cho "unit vừa tạo" sử dùng phép "Frost Nova" vào "unit vừa tạo" (tức là cast phép lên chính mình)

    ==> 3 dòng trên là gây nên hiệu ứng frost nova đi kèm chain lightning

    -
    -
    -
    -
    4 dòng tiếp là gây nên "Slow" đi kèm chain lightning

    - dòng cuối là deal 10 dam chain lightning (vì chain lightning của chúng ta chỉ gây nên 0.01 dam thôi mà)
    <><><><><><><><><><><><><><><><><><><><><><><><><><><>


    Phần 1 của Bài 1 kết thúc :D , các bạn khi test map thì sẽ nhìn thấy trong phần TRIGGER có 3 dòng lệnh bị mờ đi

    CÁC BẠN CÓ THỂ CLICK CHUỘT PHẢI VÀO NÓ VÀ CHỌN "Enable Function"
    Dự định những dòng này cho phần 2 của bài 1 :x, nếu thích thì các bạn có thể bật nó lên và test trước :D

    Dưới là toàn bộ map của bài 1, các bạn có thể xem trước: Dùng Winrar giải nén

    Hẹn gặp lại các bạn trong 1 ngày gần đây :D chắc thứ 2 tuần sau :P
     

    Các file đính kèm:

  14. sukaraki

    sukaraki Donkey Kong

    Tham gia ngày:
    12/5/08
    Bài viết:
    356
    Nơi ở:
    Demonworld
    Xin lỗi vì đã cắt ngang.Bài viết của bạn hyaTha_dk rất hay, rất tận tình, ko có gì để nói thêm.Nhưng đọc qua một số phần ở khúc đầu, thấy bạn nói :"Jass hơn GUI ở chỗ bao nhiêu unit cast cùng 1 spell cũng không bị lỗi" và dẫn chứng là đúng trong map của bạn đã attach.Đó cũng là vấn đề DUY NHẤT mà mình phải mò qua topic Jass để tham khảo.Nhưng có một số lỗi sau :

    1- special effect khi set = null ,vẫn ko bị remove khỏi bộ nhớ : khi tôi cast thật nhiều cái chiêu đó , đợi nó cast xong , thấy rõ ràng vẫn giật máy.

    2- Cách làm của bạn là set local hero ... gì gì đó ,nói chung là với 1 trigger, thì có thể đc, nhưng đa số spell phức tạp cần đến 2~3~4 trigger thì local của bạn không dùng đc nữa, và đó là vấn đề của tôi : không bắt đc unit caster khi mà spell đó có nhiều unit sở hữu.mong bạn chỉ cách khác thiết thực hơn khi dùng nhiều trigger cho 1 spell. [ví dụ spell cho rơi mưa đá trong 9 giây, thì 1 trigger là cast phép, turn on trigger 2, trigger 2 sẽ đảm nhiệm phần effect... v..v hết thời gian thì turn off trigger 2 lại]
     
  15. Diệp Thanh

    Diệp Thanh Kirin Tor Moderator Lão Làng GVN

    Tham gia ngày:
    7/2/04
    Bài viết:
    4,249
    Cố lên Hytha..
    Nhân đây Tom với Hytha vô soát lại cái code cho spell Conversion của anh với..
    Phải làm lại từ đầu mà project đang xuông dốc...lại ghiền Jass mất rồi

    Conversion: has 2/4/6% to convert an undead creature to your side on attacks. Can only convert one creature at one time.


    Vào game nó hổng chạy..hix...
    ////////////////////////////////////////////////////
     
  16. sukaraki

    sukaraki Donkey Kong

    Tham gia ngày:
    12/5/08
    Bài viết:
    356
    Nơi ở:
    Demonworld
    - Này anh zdai : khi đó anh disable trigger rồi, nó còn tác dụng nữa đâu mà làm 2 lệnh sau đó là wait 20s và enable lại ? Disable với enable thì phải dùng trigger trung gian chứ.
     
  17. Diệp Thanh

    Diệp Thanh Kirin Tor Moderator Lão Làng GVN

    Tham gia ngày:
    7/2/04
    Bài viết:
    4,249
    Disable sau khi đã do hết các lệnh phía trên...và ngay trong function đó thì wait 20 giây rồi enable nó lại chứ Rex ko disable vĩnh viễn mà :D

    Nhưng dù sao cũng cám ơn bạn đã đóng góp ý kiến....
     
  18. Tom_Kazansky

    Tom_Kazansky

    Tham gia ngày:
    28/12/06
    Bài viết:
    3,454
    Nơi ở:
    Hà Nội
    anh Rex ơi, anh thử thêm vài cái debug message xem:

    Mã:
    call BJDebugMsg(  "    Conversion chanec = "+I2S( Int_Conversion ) )  //<- debug
    ìf ( Int_Conversion <= Int_Chance ) then
    
    xem mỗi khi attack thì nó có hiện ra ko, mà hiện ra đúng chance thì xem có effect ko.
     
  19. Vua_Do_Hoa

    Vua_Do_Hoa Mr & Ms Pac-Man

    Tham gia ngày:
    30/3/08
    Bài viết:
    217
    Nơi ở:
    Tp Hồ Chí Minh
    Không biết anh sẽ viết bài theo hướng nào, có các phần này ko nữa,cho em hỏi trước.

    Là phần: Struct , Global => 2 Cái này có liên quan nhau...
    Local :::>Rất quan trọng
    Timer :::> Quan trọng luôn
     
  20. Diệp Thanh

    Diệp Thanh Kirin Tor Moderator Lão Làng GVN

    Tham gia ngày:
    7/2/04
    Bài viết:
    4,249
    Ừ để anh thử xem..Mà để gán nhiều điều kiện thì ở function điều kiện mình nối = and phải ko Tom, anh đã fix lại rồi..Ko hiều nổi sao vẫn ko được nữa:

    p/s: ko có Jass tag nhỉ :D

    Bài viết của anh đây, Anh có kèm theo cái map Spell Testing for AOS với lại có J.Tag nhìn dễ hơn:
    http://wc3campaigns.net/showthread.php?p=1024578#post1024578

     

Chia sẻ trang này