• 🏆 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!

CC5-7 - basics of hashtables

Status
Not open for further replies.
Level 14
Joined
Mar 11, 2017
Messages
587

Script

Mission Description

Changelog


InitTrig_CrashCourse() is the initializer: It will call the single function required for Crash Course 5 ( cc5() ), then will go on setting up the global variables required for crash course 7.
cc7 task was accomplished with several triggers that count 3 kinds of order separately( cc7pointorder(), cc7targetorder(), cc7order() ), output the three counts upon hero selection (cc7select() ) , and clear the data upon pressing Esc ( cc7part2() )
Trigger sheet name: Crash Course
JASS:
globals
    hashtable Hash = null //cc5
    unit Hero //for cc7
endglobals

function cc5 takes nothing returns nothing
    call SaveUnitHandle(Hash,123456789,0,CreateUnit(Player(0),'hfoo',0.,0.,270.0))
    call DisplayTimedTextToPlayer(Player(0),0.,0.,30.,GetUnitName(LoadUnitHandle(Hash,123456789,0)))
    call RemoveSavedHandle(Hash,123456789,0)
endfunction

function cc7pointorder takes nothing returns boolean
    local integer n
    set n = ( LoadInteger(Hash,GetHandleId(GetTriggerUnit()),76) ) + 1
    call SaveInteger(Hash,GetHandleId(GetTriggerUnit()),76,n)
return false
endfunction

function cc7targetorder takes nothing returns boolean
    local integer n
    set n = ( LoadInteger(Hash,GetHandleId(GetTriggerUnit()),77) ) + 1
    call SaveInteger(Hash,GetHandleId(GetTriggerUnit()),77,n)
return false
endfunction

function cc7order takes nothing returns boolean
    local integer n
    set n = ( LoadInteger(Hash,GetHandleId(GetTriggerUnit()),75) ) + 1
    call SaveInteger(Hash,GetHandleId(GetTriggerUnit()),75,n)
return false
endfunction

function cc7select takes nothing returns boolean
    local string p //for point-orders
    local string t //for targeted-orders
    local string u //for untargeted-orders
 
    set p = ( "amount of point orders issued: " + I2S(LoadInteger(Hash,GetHandleId(GetTriggerUnit()),76)) + "\n" )
    call DisplayTimedTextToPlayer(Player(0),0.,0.,6.,p)
 
    set t = ( "amount of targeted orders issued: " + I2S(LoadInteger(Hash,GetHandleId(GetTriggerUnit()),77)) + "\n" )
    call DisplayTimedTextToPlayer(Player(0),0.,0.,6.,t)
 
    set u = ( "amount of untargeted orders issued: " + I2S(LoadInteger(Hash,GetHandleId(GetTriggerUnit()),75)) + "\n" )
    call DisplayTimedTextToPlayer(Player(0),0.,0.,6.,u)
 
    set p = null
    set t = null
    set u = null
 
    return false
endfunction

function cc7part2 takes nothing returns boolean
    call FlushChildHashtable(Hash, GetHandleId(Hero))
    call DisplayTimedTextToPlayer(Player(0),0.,0.,6.,"Counts reset.")
    return false
endfunction

//===========================================================================
function InitTrig_CrashCourse takes nothing returns nothing
    local trigger t = CreateTrigger()
 
    set Hash = InitHashtable() //initializing a global variable with a function here
    call cc5() //crash course 5. simplest use of a hashtable like a 2-keys array storage
 
    set Hero = CreateUnit(Player(0),'Opgh',100.,100.,270.0) //crash course 7. creating a Hero
    call SaveInteger(Hash,GetHandleId(Hero),76,0) //initialize the specific order-type counter to 0 (point)
    call SaveInteger(Hash,GetHandleId(Hero),77,0) //initialize the specific order-type counter to 0 (targeted)
    call SaveInteger(Hash,GetHandleId(Hero),75,0) //initialize the specific order-type counter to 0 (orders that use no point nor target)
 
    call TriggerRegisterUnitEvent(t,Hero,ConvertUnitEvent(76)) //cc7. point order
    call TriggerAddCondition(t, Condition(function cc7pointorder))
 
    set t = CreateTrigger()//cc7. target order
    call TriggerRegisterUnitEvent(t,Hero,ConvertUnitEvent(77))
    call TriggerAddCondition(t, Condition(function cc7targetorder))
   
    set t = CreateTrigger()//cc7. no-target, no-point order
    call TriggerRegisterUnitEvent(t,Hero,ConvertUnitEvent(75))
    call TriggerAddCondition(t, Condition(function cc7order))
  
    set t = CreateTrigger() //cc7 upon hero selection
    call TriggerRegisterUnitEvent(t,Hero,ConvertUnitEvent(57))
    call TriggerAddCondition(t, Condition(function cc7select))
 
    set t = CreateTrigger() //cc7 part 2. flush the hash
    call TriggerRegisterPlayerEvent(t,Player(0),EVENT_PLAYER_END_CINEMATIC)
    call TriggerAddCondition(t, Condition(function cc7part2))
 
    set t = null
endfunction

Code:
function InitTrig_CrashCourse takes nothing returns nothing
    local trigger t = CreateTrigger()
    set Hash = InitHashtable() //initializing a global variable with a function here
    call cc5() //crash course 5. simplest use of a hashtable like a 2-keys array storage
    set Hero = CreateUnit(Player(0),'Opgh',100.,100.,270.0) //crash course 7. creating a Hero
    call SaveInteger(Hash,GetHandleId(Hero),76,0) //initialize the specific order-type counter to 0 (point)
    call SaveInteger(Hash,GetHandleId(Hero),77,0) //initialize the specific order-type counter to 0 (targeted)
    call SaveInteger(Hash,GetHandleId(Hero),75,0) //initialize the specific order-type counter to 0 (orders that use no point nor target)
    call TriggerRegisterUnitEvent(t,Hero,ConvertUnitEvent(76)) //cc7. point order
    call TriggerAddCondition(t, Condition(function cc7pointorder))
    set t = CreateTrigger()//cc7. target order
    call TriggerRegisterUnitEvent(t,Hero,ConvertUnitEvent(77))
    call TriggerAddCondition(t, Condition(function cc7targetorder))
  
    set t = CreateTrigger()//cc7. no-target, no-point order
    call TriggerRegisterUnitEvent(t,Hero,ConvertUnitEvent(75))
    call TriggerAddCondition(t, Condition(function cc7order))
 
    set t = CreateTrigger() //cc7 upon hero selection
    call TriggerRegisterUnitEvent(t,Hero,ConvertUnitEvent(57))
    call TriggerAddCondition(t, Condition(function cc7select))
    set t = CreateTrigger() //cc7 part 2. flush the hash
    call TriggerRegisterPlayerEvent(t,Player(0),EVENT_PLAYER_END_CINEMATIC)
    call TriggerAddCondition(t, Condition(function cc7part2))
    set t = null
endfunction

JASS:
function cc5 takes nothing returns nothing
    call SaveUnitHandle(Hash,123456789,0,CreateUnit(Player(0),'hfoo',0.,0.,270.0))
    call DisplayTimedTextToPlayer(Player(0),0.,0.,30.,GetUnitName(LoadUnitHandle(Hash,123456789,0)))
    call RemoveSavedHandle(Hash,123456789,0)
endfunction

JASS:
function cc7pointorder takes nothing returns boolean
    local integer n
    set n = ( LoadInteger(Hash,GetHandleId(GetTriggerUnit()),76) ) + 1
    call SaveInteger(Hash,GetHandleId(GetTriggerUnit()),76,n)
return false
endfunction

function cc7targetorder takes nothing returns boolean
    local integer n
    set n = ( LoadInteger(Hash,GetHandleId(GetTriggerUnit()),77) ) + 1
    call SaveInteger(Hash,GetHandleId(GetTriggerUnit()),77,n)
return false
endfunction

function cc7order takes nothing returns boolean
    local integer n
    set n = ( LoadInteger(Hash,GetHandleId(GetTriggerUnit()),75) ) + 1
    call SaveInteger(Hash,GetHandleId(GetTriggerUnit()),75,n)
return false
endfunction

JASS:
function cc7select takes nothing returns boolean
    local string p //for point-orders
    local string t //for targeted-orders
    local string u //for untargeted-orders
    set p = ( "amount of point orders issued: " + I2S(LoadInteger(Hash,GetHandleId(GetTriggerUnit()),76)) + "\n" )
    call DisplayTimedTextToPlayer(Player(0),0.,0.,6.,p)
    set t = ( "amount of targeted orders issued: " + I2S(LoadInteger(Hash,GetHandleId(GetTriggerUnit()),77)) + "\n" )
    call DisplayTimedTextToPlayer(Player(0),0.,0.,6.,t)
    set u = ( "amount of untargeted orders issued: " + I2S(LoadInteger(Hash,GetHandleId(GetTriggerUnit()),75)) + "\n" )
    call DisplayTimedTextToPlayer(Player(0),0.,0.,6.,u)
    set p = null
    set t = null
    set u = null
    return false
endfunction

JASS:
function cc7part2 takes nothing returns boolean
    call FlushChildHashtable(Hash, GetHandleId(Hero))
    call DisplayTimedTextToPlayer(Player(0),0.,0.,6.,"Counts reset.")
    return false
endfunction


Preparation

Following global variables must be declared and used (<type> , <name>):
  1. hashtable Hash
Part 1

Create a unit and save it into hashatble. ParentKey = 123456789 ; ChildKey = 0
Part 2

Print the name of the saved unit using the loaded value from hashtable. (you can do it in same function)
Prepration

Following global variables must be declared and used (<type> , <name>):
  1. hashtable Hash
  2. unit Hero
Extra global variables are not allowed.
Part 1

Create a (JASS) trigger that runs (only) when Hero makes a point order.
Create a (JASS) trigger that runs (only) when Hero makes a target order.
Create a (JASS) trigger that runs (only) when Hero makes an order without target.

Create a (JASS) trigger that runs when you select the Hero.
The trigger's goal is to print following values on screen:
  1. PointOrders: X
  2. TargetOrders: Y
  3. NontargetOrders: Z
... where, X, Y, Z are the correct values respectivly how much orders the Hero did (like counters).

Tip: You must use the first three triggers to count the different orders, and use hashtable to bind the values to the unit.
Part 2

Create a (JASS) trigger that runs when a player presses the 'Esc' button.
The trigger's goal is to clean the hashtable of all it's entries.

v0 - exercise submission


Seemed simple at first. I beg reviewers to point out to me the (inevitable) errors within.
 

Attachments

  • Crashcourse57.w3x
    18 KB · Views: 68
Last edited:

Jampion

Code Reviewer
Level 15
Joined
Mar 25, 2016
Messages
1,327
Please use [code=jass] [/code] tags to have syntax highlightning in your code.

cc7 order triggers:
JASS:
function cc7pointorder takes nothing returns boolean
    local integer n
    set n = ( LoadInteger(Hash,GetHandleId(GetTriggerUnit()),76) ) + 1
    call SaveInteger(Hash,GetHandleId(GetTriggerUnit()),76,n)
return false
endfunction
->
JASS:
function cc7pointorder takes nothing returns boolean
    local integer n
    local integer handleId = GetHandleId(GetTriggerUnit())
    set n = ( LoadInteger(Hash, handleId, 76) ) + 1
    call SaveInteger(Hash, handleId, 76, n)
    return false
endfunction

A little bit formatting. Please leave a space after a comma that seperates the arguments.
I would also recommend using a local variable for the handle Id in case it is needed multiple times. With this you save 2 operations: GetHandleId and GetTriggerUnit
If you want you can also initialize the local n directly.

ConvertUnitEvent(76):
I would advice against using ConvertUnitEvent. Rather use EVENT_UNIT_ISSUED_POINT_ORDER as it makes your code a lot more readable.
Also using 75, 76, 77 as keys can be confusing, if you use a lot of different keys in the hashtable. If you have like 20 seemingly random numbers for the hashtable without documentation on what they stand for, you will make more mistakes and it will take you a lot longer to fix problems or make changes to the code.

There are several options to avoid this issue:
Use constants that are defined in the globals block:

private constant integer COUNT_POINT_ORDERS = 76

This way all your keys are together and if you want to change them, you only need to change them once -> better maintainability

Even though the mission restricts which globals are allowed, I think adding constants is no problem as they don't really add any functionality. There functionality is pretty much just text replacing as you cannot change their value.

You can also use handle ids. Handle Ids are unique, so if you use them you don't have to worry about the actual number behind it.
Here you could use the handle id of the associated trigger.

part 2:
The mission wants you to flush the hashtable of all its entries. It is not even required to store the values at GetHandleId(Hero), but I would leave it like it is. Your code makes it easier to make this system MUI.
Instead of using GetTriggerUnit() you can use Hero, because your events are only registered to Hero, so GetTriggerUnit() is always Hero. But again you can make a point, that GetTriggerUnit() allows you to make it MUI more easily.


The submission looks good. From the code it looks like everything should work (did not check the map, but I assume you did and it worked).
For future projects, especially if they get bigger and more complex I would try to increase the readability and maintainability of your code. Using constants is an easy and good way to start.

Nice formatting of the hive post by the way.
Seemed simple at first.
Yes, the crash course is quite simple. If you feel like you know the basics, you can try the real missions.

Looking forward to see more submissions from you.
 
Status
Not open for further replies.
Top