|
|
#1 |
|
User
|
Before you continue:
__________________First of all please forgive me for anything unclear in this article because English is not my native language. Purpose of this tutorials: 1. Is to provide a useful code to other “Ability makers”, which has been tested in a map that works; 2. To show some advantage of vJass. Preparation: Tools: All codes are written in vJass, kindly prepare the relative tools. I recommend Jass New Gen Pack. Knowledge: At least you have to know how vJass & Jass works, otherwise don’t waste time on this tutorials. Please ignore all sentences start with debug, it’s only for debugging. Other statement: I will provide: Answering of any questions followed; Code problems fixing. But will not provide: Code migrating; Take responsibility for maps destruction by code misuse or map tools. Have you been tired of creating a set of units then remove them one by one after that, or repeat loop/ endloop million times? Here is an example: When a unit cast “Flame Strike”, create a “Flame line” on the ground from <TriggerUnit>’s location to <SpellTarget> location. What do we do in a typical way? 1, Calculate the distance between <TriggerUnit>’s location & <SpellTarget> location; 2, Create a set of dummy units attached special effects(or directly special effects without units) along the path between this two locations, by loop/ endloop; 3, Wait a little bit time; 4, Delete these sets of units, by an other loop/ endloop of course. Yes you may think of a custom function to perform it, but how do you reach each of the elements? Again you may say global variables, and if this is in a melee game, you have to use array for different players. This is “millions of works.” Now try to imagine that we have “unitsline” type object in the game which we can declare and use at any time, what happen if we can do this? Read the trigger below: Trigger: Draw
![]() Actions
![]() ![]() Custom script: local unitsline line = DrawUnitsline( GetOwningPlayer( GetTriggerUnit()), GetUnitLoc( GetTriggerUnit()), GetSpellTargetLoc())
![]() ![]() Custom script: local real length = GetUnitslineLength( line )
![]() ![]() Wait 3.00 seconds
![]() ![]() Custom script: call DestroyUnitsline( line )
![]() ![]() Unit - Set mana of (Triggering unit) to 100.00%
![]() ![]() Unit - Reset ability cooldowns for (Triggering unit)DrawUnitsline() is a custom function that returns “unitsline”, so we can easily use a local var to save it, then “Get” its length or “Destroy” it, such as what we normally do to a “lightning”, or “effect”, or “unit”. This can be completely accomplished with our new friend, vJass. I have to say that even now I am not so clear about how vJass works, anyway here is what we need to do: Build a “struct” named unitsline, inclusive a real “length”, group “members”. "length” is a sub-var that save the length of line, “members” is actually a group that save all units we created. Code: JASS:
struct unitsline
real length
group members
endstruct
Then we start our work, create a custom function. You may see that it’s just as normal as creating a custom function, but please pay attention to that how we save data in “unitsline” var: Code: JASS:// You may skip this part it’s just a private struct used in function. struct linedata real ox real oy real tx real ty real dx real dy real face endstruct // You may skip this part it’s just a private struct used in function. //-------------------------------------------------------------------------- function DrawUnitsline takes player who, location startPoint, location endPoint returns unitsline local unit u local linedata line = linedata.create() local unitsline units_line = unitsline.create() local integer num local integer f = 1 //! textmacro generaldebug debug local string message debug local string head debug local string mid debug local string end //! endtextmacro //! runtextmacro generaldebug() set line.ox = GetLocationX( startPoint ) set line.oy = GetLocationY( startPoint ) set line.tx = GetLocationX( endPoint ) set line.ty = GetLocationY( endPoint ) set line.face = Atan2( line.ty - line.oy, line.tx - line.ox ) set units_line.members = CreateGroup() // Here we save the length to lin.length, it’s not must. It’s particular and only for //GetUnitslineLength(), that a function will introduce below. set units_line.length = SquareRoot(( line.tx - line.ox ) * ( line.tx - line.ox ) + ( line.ty - line.oy ) * ( line.ty - line.oy )) set num = R2I( units_line.length ) / R2I( line_step ) debug set head = "function call: " + SetTextColor( "Drawline()", "Yellow" ) + " " debug set mid = "by " + SetTextColor( "Player " +I2S( GetPlayerId( who ) + 1 ), "Red" ) + ", " debug set end = SetTextColor( I2S( num ), "Yellow" ) + " units been placed." debug set message = head + mid + end loop exitwhen f > num set line.dx = line.ox + I2R(f) * line_step * Cos( line.face ) set line.dy = line.oy + I2R(f) * line_step * Sin( line.face ) set u = CreateUnit( who, Dummysetting_DummyU, line.dx, line.dy, 0.0 ) call SetUnitPathing( u, false ) call SetUnitFlyHeight( u, 0.00, 0.00 ) call AddSpecialEffectTarget( Dummysetting_FireModel, u, "origin" ) // We save all units into line.members group, so we can reach them later. call GroupAddUnit( units_line.members, u ) set u = null set f = f + 1 endloop debug call BJDebugMsg( message ) call linedata.destroy( line ) return units_line endfunction Now we already have a function that can create and return a “unitsline”, we still need more functions to reach the data that contain in this type of object. Of course the most important 1 is Destroy, we can’t just create something and then let it run forever without anyway to destroy. Another function I can think of is to get a unitsline’s length, actually it’s not necessary because you may use whichLine.length to get it simply, I create this function for an example purpose that how it works only. Code: JASS:
function DestroyUnitsline takes unitsline whichLine returns nothing
local unit u
debug local integer num = 0
//! runtextmacro generaldebug()
// Yes this is the same, we have to use a loop/ endloop to get each element in the group, // then destroy 1 by 1.
loop
set u = FirstOfGroup( whichLine.members )
exitwhen u == null
call RemoveUnit( u )
debug set num = num + 1
call GroupRemoveUnit( whichLine.members, u )
endloop
debug set head = "function call: " + SetTextColor( "DestroyUnitsline()", "Yellow" ) + " "
debug set mid = SetTextColor( I2S(num), "Yellow" ) + " units been destroyed."
debug set message = head + mid
debug call BJDebugMsg( message )
// Destroy the struct
call whichLine.destroy()
endfunction
//--------------------------------------------------------------------------
function GetUnitslineLength takes unitsline whichLine returns real
//! runtextmacro generaldebug()
debug local integer num = CountUnitsInGroup( whichLine.members )
debug set head = "function call: " + SetTextColor( "GetUnitslineLength()", "Yellow" ) + " "
debug set mid = "= " + SetTextColor( R2S( whichLine.length ), "Yellow" ) + "; "
debug set end = SetTextColor( I2S(num), "Yellow" ) + " x " + SetTextColor( R2S(line_step), "Yellow" ) + " = " + SetTextColor( R2S( I2R(num) * line_step ), "Yellow" )
debug set message = head + mid + end
debug call BJDebugMsg( message )
if ( whichLine.members == null ) then
return 0.0
endif
// This is simple, just get the length from it’s sub var.
return whichLine.length
endfunction
And here is the complete code, in case you don't have interest with researching it you can just paste it to your map and use: Code: JASS://========================================================================== //-------------------------------------------------------------------------- //- - //-------------------------------------------------------------------------- //========================================================================== library Dummysetting globals public constant integer DummyU = 'u000' public constant string FireModel = "Abilities\\Spells\\Human\\FlameStrike\\FlameStrikeDamageTarget.mdl" //public constant string FireModel = "Abilities\\Spells\\Other\\Doom\\DoomDeath.mdl" //public constant string FireModel = "Doodads\\Cinematic\\FrostTrapUp\\FrostTrapUp.mdl" endglobals struct unitsline real length group members endstruct scope Debugfunctions //========================================================================== //-------------------------------------------------------------------------- function SetTextColor takes string txt, string color returns string //! textmacro settextcolorfunction takes color, colorcode if ( color == "$color$" ) then set color = "$colorcode$" endif //! endtextmacro //! runtextmacro settextcolorfunction ( "White", "|cFFFFFFFF" ) //! runtextmacro settextcolorfunction ( "Red", "|c00ff0000" ) //! runtextmacro settextcolorfunction ( "Blue", "|c000000ff" ) //! runtextmacro settextcolorfunction ( "Teal", "|c0000ffff" ) //! runtextmacro settextcolorfunction ( "Purple", "|c00800080" ) //! runtextmacro settextcolorfunction ( "Yellow", "|c00ffff00" ) //! runtextmacro settextcolorfunction ( "Green", "|c0000ff00" ) //! runtextmacro settextcolorfunction ( "Pink", "|c00ff00ff" ) //! runtextmacro settextcolorfunction ( "Gray", "|cFF808080" ) //! runtextmacro settextcolorfunction ( "LightBlue", "|cFFC0FFFF" ) //! runtextmacro settextcolorfunction ( "DarkGreen", "|cFF004000" ) //! runtextmacro settextcolorfunction ( "Brown", "|cFF400000" ) //! runtextmacro settextcolorfunction ( "Black", "|cFF000000" ) return color + txt + "|r" endfunction //-------------------------------------------------------------------------- //========================================================================== endscope endlibrary //========================================================================== //-------------------------------------------------------------------------- //- - //-------------------------------------------------------------------------- //========================================================================== library Drawfunctions requires Dummysetting globals private constant real line_step = 30.0 private constant real letter_verticle = 400.0 private constant real letter_horizon = letter_verticle * 2.0 private constant real effect_lifetime = 5.00 private constant real angle_step = 3.00 endglobals scope UnitslineFunctions //========================================================================== //-------------------------------------------------------------------------- struct linedata real ox real oy real tx real ty real dx real dy real face endstruct //-------------------------------------------------------------------------- function DrawUnitsline takes player who, location startPoint, location endPoint returns unitsline local unit u local linedata line = linedata.create() local unitsline units_line = unitsline.create() local integer num local integer f = 1 //! textmacro generaldebug debug local string message debug local string head debug local string mid debug local string end //! endtextmacro //! runtextmacro generaldebug() set line.ox = GetLocationX( startPoint ) set line.oy = GetLocationY( startPoint ) set line.tx = GetLocationX( endPoint ) set line.ty = GetLocationY( endPoint ) set line.face = Atan2( line.ty - line.oy, line.tx - line.ox ) set units_line.members = CreateGroup() set units_line.length = SquareRoot(( line.tx - line.ox ) * ( line.tx - line.ox ) + ( line.ty - line.oy ) * ( line.ty - line.oy )) set num = R2I( units_line.length ) / R2I( line_step ) debug set head = "function call: " + SetTextColor( "Drawline()", "Yellow" ) + " " debug set mid = "by " + SetTextColor( "Player " +I2S( GetPlayerId( who ) + 1 ), "Red" ) + ", " debug set end = SetTextColor( I2S( num ), "Yellow" ) + " units been placed." debug set message = head + mid + end loop exitwhen f > num set line.dx = line.ox + I2R(f) * line_step * Cos( line.face ) set line.dy = line.oy + I2R(f) * line_step * Sin( line.face ) set u = CreateUnit( who, Dummysetting_DummyU, line.dx, line.dy, 0.0 ) call SetUnitPathing( u, false ) call SetUnitFlyHeight( u, 0.00, 0.00 ) call AddSpecialEffectTarget( Dummysetting_FireModel, u, "origin" ) call GroupAddUnit( units_line.members, u ) set u = null set f = f + 1 endloop debug call BJDebugMsg( message ) call linedata.destroy( line ) return units_line endfunction //-------------------------------------------------------------------------- function DestroyUnitsline takes unitsline whichLine returns nothing local unit u debug local integer num = 0 //! runtextmacro generaldebug() loop set u = FirstOfGroup( whichLine.members ) exitwhen u == null call RemoveUnit( u ) debug set num = num + 1 call GroupRemoveUnit( whichLine.members, u ) endloop debug set head = "function call: " + SetTextColor( "DestroyUnitsline()", "Yellow" ) + " " debug set mid = SetTextColor( I2S(num), "Yellow" ) + " units been destroyed." debug set message = head + mid debug call BJDebugMsg( message ) call whichLine.destroy() endfunction //-------------------------------------------------------------------------- function GetUnitslineLength takes unitsline whichLine returns real //! runtextmacro generaldebug() debug local integer num = CountUnitsInGroup( whichLine.members ) debug set head = "function call: " + SetTextColor( "GetUnitslineLength()", "Yellow" ) + " " debug set mid = "= " + SetTextColor( R2S( whichLine.length ), "Yellow" ) + "; " debug set end = SetTextColor( I2S(num), "Yellow" ) + " x " + SetTextColor( R2S(line_step), "Yellow" ) + " = " + SetTextColor( R2S( I2R(num) * line_step ), "Yellow" ) debug set message = head + mid + end debug call BJDebugMsg( message ) if ( whichLine.members == null ) then return 0.0 endif return whichLine.length endfunction //========================================================================== endscope endlibrary |
|
|
|
| Sponsored Links - Login to hide this ad! |
|
|
|
|
#2 |
|
Alcopops
Tools & Tutorials Moderator
|
Quite for good for a first post.
__________________Your indentation and naming conventions are really weird, but the content of the tutorial is alright. I approve. |
|
|
|
|
|
#3 |
|
Galaxy Scripter
|
couldnt u just use type unitsline extends handle
__________________ |
|
|
|
|
|
#4 |
|
Moderator
RP Section Moderator
|
So this is one way of making one of those spells that uses a line in front of the caster... Man, have I needed one of these. But, I need to understand how vJass works...
__________________ |
|
|
|
|
|
#5 | ||
|
User
|
Quote:
Reeeeeally simple, don't worry ;) SlyRabbit, you keep adding _ in unitsline name for no reason, units_line.members for example. The struct name is wrong, and it won't work. Omg, locations! It surprises me a person that uses vJass uses locations. But then again, you use coordinates inside the function so I would say that you made it for GUI users. JASS://! textmacro generaldebug debug local string message debug local string head debug local string mid debug local string end //! endtextmacro Wtf is this??? I totally don't understand those debugs. Anways a fine tut, but I think everybody can make one of those functions for himself if he needs it. Not that my Knockback function is any better :P. Quote:
Million times is not necessary, just make one function (like you did) and call it every time. +REP!!! Last edited by Silvenon : 08-24-2007 at 07:20 PM. |
||
|
|
|
![]() |
| Thread Tools | Search this Thread |
|
|
|
Donate |