• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

[vJASS] question about compiled vjass

Status
Not open for further replies.
Level 6
Joined
Oct 23, 2011
Messages
182
When static method in vjass is compiled into jass,

I notice things like

function sc__scope__struct_method takes arguments returns nothing
set f__arg_arg1 = argument 1
set f__arg_arg2 = argument 2
...
call TriggerEvaluate(st__scope__struct_method)
endfunction

in which st__scope__struct_method is a trigger with condition that runs given method with given f__arg variables.

I'm wondering why it's compiled like this using TriggerEvaluate, instead of
function sc__scope__struct method doing stuff directly with given arguments.
They just seem useless codes/triggers taking up a lot of space.

(maybe this has something to do with methods being placed 'on top' of other methods?)
 
(maybe this has something to do with methods being placed 'on top' of other methods?)

Yes. This is actually a "feature" of vJASS (which I don't really like given that they have .execute() and .evaluate() commands already). Instead of giving you an error when you place methods in the wrong order, it'll automatically build it as if it is calling the .evaluate() command.

So let's say you have two methods:
JASS:
static method A takes nothing returns nothing
    call B()
endmethod

static method B takes nothing returns nothing
endmethod

If you replaced the methods with functions, obviously this wouldn't work. However, with vJASS and methods, this will compile and *magically* work. Instead of smartly ordering them, it will just use an evaluation method. The fix is to place your methods properly so that it is always above where you're calling from.
 
Level 23
Joined
Apr 16, 2012
Messages
4,041
that is not 100% true however. JassHelper is very smart in one way, because he detects some magical conditions, and when these arent met(I never got so far with the research as to find what the magical conditions are), it will only create copy of your function above the rest of the script, even above allocation and dellocation functions of your function, so indeed code presented by you PNF will compile into function call. I think the magical condition has something to do with A calling B calling C, where C is below A and B is above C or some magic like that.
 
Level 6
Joined
Oct 23, 2011
Messages
182
Thank you for detailed explanations!

Would it be generally considered bad practice to have methods calling other methods below them? or is it sometimes an allowable thing that makes my life easier?

Also, if vJass can detect such errors and provide a workaround, why do I get an error when I compile a library that uses other library's methods but do not include the needed libraries in the requirements declaration?

JASS:
library TimerUtils

    function NewTimer takes nothing returns timer
        return CreateTimer()
    endfunction
    
endlibrary

library Camera

    struct Something extends array
    static method Blabla takes nothing returns nothing
        local timer t = NewTimer()
    endmethod
    endstruct
endlibrary

Such example gives me error saying NewTimer() is not a declared function or something.
 
Level 23
Joined
Apr 16, 2012
Messages
4,041
because it is built to handle these cases for methods of the same struct. Try declaring 2 structs and call one methods of the other, while the methods you are trying to call are below.

Basically, the library you want to call is not guaranteed to be at top, and function calls(non method calls) generate normal call, unless you use .execute() or .evaluate().

If you require/use/need the library, it should work fine
 
Just some general guidelines to write code properly:
  • If you are writing in script A and need a function from script B, wrap both of them in libraries and make library A require B.
  • Always place methods in the normal JASS ordering. If you need to call a function, put it on top of the caller. If you absolutely must call it from above, use .evaluate() or .execute() explicitly.

Overall, it is just better to know what you're feeding the compiler. You'll find yourself having a much better time. The optimizer may fix some of the repeated code and stuff, but it actually makes a big difference. I remember implementing Anachron's inventory system in for Ardent Heroes--he used his own method ordering that caused a bunch of vJASS prototype functions. I saved thousands of lines just by reordering things. No joke.
 
Level 19
Joined
Mar 18, 2012
Messages
1,716
If I use .execute(), what does jasshelper compile? Its interesting to know, because in this case I could also use ExecuteFunc().
I only use one of these, when I'm too lazy to use a timer callback and just go with
TriggerSleepAction().
I never used .eveluate() thought.
 
Level 23
Joined
Apr 16, 2012
Messages
4,041
.execute == TriggerExecute
.evaluate == TriggerEvaulate

JASS:
function a takes nothing returns nothing
	
endfunction

function f takes nothing returns nothing
	call a.execute()
endfunction

->

JASS:
globals
    // Generated
trigger gg_trg_Melee_Initialization= null
trigger gg_trg_Untitled_Trigger_001= null


//JASSHelper struct globals:
trigger array st___prototype1

endglobals

function sc___prototype1_execute takes integer i returns nothing

    call TriggerExecute(st___prototype1[i])
endfunction
function sc___prototype1_evaluate takes integer i returns nothing

    call TriggerEvaluate(st___prototype1[i])

endfunction

//===========================================================================
// 
// Just another Warcraft III map
// 
//   Warcraft III map script
//   Generated by the Warcraft III World Editor
//   Date: Wed May 20 22:49:10 2015
//   Map Author: Unknown
// 
//===========================================================================

//***************************************************************************
//*
//*  Global Variables
//*
//***************************************************************************


function InitGlobals takes nothing returns nothing
endfunction

//***************************************************************************
//*
//*  Triggers
//*
//***************************************************************************

//===========================================================================
// Trigger: Untitled Trigger 001
//===========================================================================
function a takes nothing returns nothing
	
endfunction

function f takes nothing returns nothing
	call sc___prototype1_execute(1)
endfunction
//===========================================================================
function InitCustomTriggers takes nothing returns nothing
    //Function not found: call InitTrig_Untitled_Trigger_001()
endfunction

//***************************************************************************
//*
//*  Players
//*
//***************************************************************************

function InitCustomPlayerSlots takes nothing returns nothing

    // Player 0
    call SetPlayerStartLocation(Player(0), 0)
    call SetPlayerColor(Player(0), ConvertPlayerColor(0))
    call SetPlayerRacePreference(Player(0), RACE_PREF_HUMAN)
    call SetPlayerRaceSelectable(Player(0), true)
    call SetPlayerController(Player(0), MAP_CONTROL_USER)

endfunction

function InitCustomTeams takes nothing returns nothing
    // Force: TRIGSTR_002
    call SetPlayerTeam(Player(0), 0)

endfunction

//***************************************************************************
//*
//*  Main Initialization
//*
//***************************************************************************

//===========================================================================
function main takes nothing returns nothing
    call SetCameraBounds(- 3328.0 + GetCameraMargin(CAMERA_MARGIN_LEFT), - 3584.0 + GetCameraMargin(CAMERA_MARGIN_BOTTOM), 3328.0 - GetCameraMargin(CAMERA_MARGIN_RIGHT), 3072.0 - GetCameraMargin(CAMERA_MARGIN_TOP), - 3328.0 + GetCameraMargin(CAMERA_MARGIN_LEFT), 3072.0 - GetCameraMargin(CAMERA_MARGIN_TOP), 3328.0 - GetCameraMargin(CAMERA_MARGIN_RIGHT), - 3584.0 + GetCameraMargin(CAMERA_MARGIN_BOTTOM))
    call SetDayNightModels("Environment\\DNC\\DNCLordaeron\\DNCLordaeronTerrain\\DNCLordaeronTerrain.mdl", "Environment\\DNC\\DNCLordaeron\\DNCLordaeronUnit\\DNCLordaeronUnit.mdl")
    call NewSoundEnvironment("Default")
    call SetAmbientDaySound("LordaeronSummerDay")
    call SetAmbientNightSound("LordaeronSummerNight")
    call SetMapMusic("Music", true, 0)
    call InitBlizzard()

call ExecuteFunc("jasshelper__initstructs46938922")

    call InitGlobals()
    call InitCustomTriggers()

endfunction

//***************************************************************************
//*
//*  Map Configuration
//*
//***************************************************************************

function config takes nothing returns nothing
    call SetMapName("Just another Warcraft III map")
    call SetMapDescription("Nondescript")
    call SetPlayers(1)
    call SetTeams(1)
    call SetGamePlacement(MAP_PLACEMENT_USE_MAP_SETTINGS)

    call DefineStartLocation(0, 1088.0, - 2816.0)

    // Player setup
    call InitCustomPlayerSlots()
    call SetPlayerSlotAvailable(Player(0), MAP_CONTROL_USER)
    call InitGenericPlayerSlots()
endfunction




//Struct method generated initializers/callers:
function sa___prototype1_a takes nothing returns boolean

    return true
endfunction

function jasshelper__initstructs46938922 takes nothing returns nothing
    set st___prototype1[1]=CreateTrigger()
    call TriggerAddAction(st___prototype1[1],function sa___prototype1_a)
    call TriggerAddCondition(st___prototype1[1],Condition(function sa___prototype1_a))

endfunction
 
Status
Not open for further replies.
Top