HomeUser Control Panel (unavailable in archive)ForumsTutorialsArt GalleryResourcesMaps

Need Some Guidance on How to do this Efficiently..

04-04-2010, 10:22 PM#1
PsycoMarauder
Alright, so in my map, I'm tracking a lot of data via the MMD system by Strilanc. The info is then displayed on my website for users to see their stats and whatnot. Anyways, it'd be nice to track more specific unit data. For example, the number of units trained of multiple types of unit, the number of units killed of multiple types of units, and, if possible, the number of units killed by particular unit types. Sorry if that sounded confusing, but hopefully it makes sense.

For example:
Number of Riflemen by Player X trained: X
Number of Riflemen by Player X killed: Y
Number of Units killed by your Riflemen: Z
I've tried doing it via a few different methods, but the map is a risk type map, and in some cases there are hundreds of units fighting all across the map.

Things like If unit type of dying unit = to X then set variable to Y +1 seem to cause lag during huge battles. IS there a way this can be done efficiently? Currently I have the "point value" for each unit set to a number based upon their gold value, so when a unit dies, the owner of the killing units kills go up + their gold value/custom point value. Would it be more effective to do something related to that, for example, using a function to get their gold value and then if gold value is = to x, doing y?

Honestly, I'm not sure if it's possible to do this efficiently without causing a ton of lag, but any or advice suggestions would definitely be appreciated.
04-05-2010, 09:13 AM#2
Tot
I'd try
Collapse JASS:
scope PlayerKillTypeCounter initializer Init

     globals
          private hashtable ht
     endglobals

     private function OnUnitDeath takes nothing returns nothing
          local integer playerId=GetPlayerId(GetOwningPlayer(GetKillingUnit()))
          local integer unitId=GetUnitTypeId(GetTriggerUnit())
          call SaveInteger(ht,playerId,unitId,LoadInteger(ht,playerId,unitId)+1)
     endfunction

     private function Init takes nothing returns nothing
          local trigger t=CreateTrigger()
          set ht=InitHashtable()
          call TriggerRegisterAnyUnitEventBJ(t,EVENT_PLAYER_UNIT_DEATH)
          call TriggerAddAction(t,function OnUnitDeath)
          set t=null
     endfunction
endscope
04-06-2010, 05:24 AM#3
PsycoMarauder
Edit: Nevermind, for the second time...Jesus, it JUST worked the last time it was able to compile successfully. I know the code is terrible, but can any of you help me find why no text is even being outputted in game anymore? (it does compile properly)

Heres the current code:
Collapse JASS:
scope PlayerKillTypeCounter initializer InitTrig_PlayerKillTypeCounter

     globals
          private hashtable ht
     endglobals

     private function OnUnitDeath takes nothing returns nothing
          local string playername=GetPlayerName(GetOwningPlayer(GetKillingUnit()))
          local string dieunitname=GetUnitName(GetDyingUnit())
          local string killingunitname=GetUnitName(GetKillingUnit())
          local integer killingunitnumber//=(udg_killingunitnumber[( GetConvertedPlayerId(GetOwningPlayer(GetKillingUnit())) * GetUnitPointValueByType(GetUnitTypeId(GetKillingUnit())) ) + GetUnitPointValue(GetKillingUnit())])
          local integer killingunitnumberbytype//=(udg_killingunitnumberbytype[( GetConvertedPlayerId(GetOwningPlayer(GetKillingUnit())) * GetUnitPointValueByType(GetUnitTypeId(GetKillingUnit())) ) + GetUnitPointValue(GetKillingUnit())])
          local integer dyingunitnumber//=(udg_dyingunitnumber[( GetConvertedPlayerId(GetOwningPlayer(GetDyingUnit())) * GetUnitPointValueByType(GetUnitTypeId(GetDyingUnit())) ) + GetUnitGPointValue(GetDyingUnit())])
          //local integer killunitnumberbytype
         // set integer dyingunitnumber[( GetConvertedPlayerId(GetOwningPlayer(GetDyingUnit())) * GetUnitPointValueByType(GetUnitTypeId(GetDyingUnit())) )] = (dyingunitnumber[( GetConvertedPlayerId(GetOwningPlayer(GetDyingUnit())) * GetUnitPointValueByType(GetUnitTypeId(GetDyingUnit())) )] + GetUnit
          //PointValue(GetDyingUnit()) )
 
          //set integer killingunitnumber[( GetConvertedPlayerId(GetOwningPlayer(GetKillingUnit())) * GetUnitPointValueByType(GetUnitTypeId(GetKillingUnit())) )] = (killingunitnumber[( GetConvertedPlayerId(GetOwningPlayer(GetKillingUnit())) * GetUnitPointValueByType(GetUnitTypeId(GetKillingUnit())) )] + GetUnit
         // PointValue(GetKillingUnit()) )
          //set integer killingunitnumberbytype[( GetConvertedPlayerId(GetOwningPlayer(GetKillingUnit())) * GetUnitPointValueByType(GetUnitTypeId(GetKillingUnit())) )] = (killingunitnumberbytype[( GetConvertedPlayerId(GetOwningPlayer(GetKillingUnit())) * GetUnitPointValueByType(GetUnitTypeId(GetKillingUnit())) )] + GetUnit
          //PointValue(GetKillingUnit()) )
          set udg_killingunitnumber[( GetConvertedPlayerId(GetOwningPlayer(GetKillingUnit())) * GetUnitPointValueByType(GetUnitTypeId(GetKillingUnit())) )] =(udg_killingunitnumber[( GetConvertedPlayerId(GetOwningPlayer(GetKillingUnit())) * GetUnitPointValueByType(GetUnitTypeId(GetKillingUnit())) ) + GetUnitPointValue(GetKillingUnit())])
          set udg_killingunitnumberbytype[( GetConvertedPlayerId(GetOwningPlayer(GetKillingUnit())) * GetUnitPointValueByType(GetUnitTypeId(GetKillingUnit())) )] = (udg_killingunitnumberbytype[( GetConvertedPlayerId(GetOwningPlayer(GetKillingUnit())) * GetUnitPointValueByType(GetUnitTypeId(GetKillingUnit())) ) + GetUnitPointValue(GetKillingUnit())])
          set udg_dyingunitnumber[( GetConvertedPlayerId(GetOwningPlayer(GetDyingUnit())) * GetUnitPointValueByType(GetUnitTypeId(GetDyingUnit())) )] =(udg_dyingunitnumber[( GetConvertedPlayerId(GetOwningPlayer(GetDyingUnit())) * GetUnitPointValueByType(GetUnitTypeId(GetDyingUnit())) ) + GetUnitPointValue(GetDyingUnit())])
          call SaveInteger(ht,killingunitnumber, killingunitnumberbytype, dyingunitnumber,LoadInteger(ht,killingunitnumber, killingunitnumberbytype, dyingunitnumber))
          call DisplayTextToForce( GetPlayersAll(), ( ( "==================================" )))
          call DisplayTextToForce( GetPlayersAll(), udg_PlayerColors[GetConvertedPlayerId(GetOwningPlayer(GetKillingUnit()))] +GetPlayerName(GetOwningPlayer(GetKillingUnit())) + "'s Total Kills by: " + (killingunitname) + "s are- " + I2S(udg_killingunitnumber[( GetConvertedPlayerId(GetOwningPlayer(GetKillingUnit())) * GetUnitPointValueByType(GetUnitTypeId(GetKillingUnit())) )]) )
          call DisplayTextToForce( GetPlayersAll(), udg_PlayerColors[GetConvertedPlayerId(GetOwningPlayer(GetKillingUnit()))] +GetPlayerName(GetOwningPlayer(GetKillingUnit())) + "'s Kills by Unit Type: " + (killingunitname) + "s of " + (dieunitname) + " are- " + I2S(udg_killingunitnumberbytype[( GetConvertedPlayerId(GetOwningPlayer(GetKillingUnit())) * GetUnitPointValueByType(GetUnitTypeId(GetKillingUnit())) )] ))
          call DisplayTextToForce( GetPlayersAll(), udg_PlayerColors[GetConvertedPlayerId(GetOwningPlayer(GetDyingUnit()))] +GetPlayerName(GetOwningPlayer(GetDyingUnit())) + "'s Deaths by Unit Type: " + (dieunitname) + "s are- " + I2S(udg_dyingunitnumber[( GetConvertedPlayerId(GetOwningPlayer(GetDyingUnit())) * GetUnitPointValueByType(GetUnitTypeId(GetDyingUnit())) )] ) )
          call DisplayTextToForce( GetPlayersAll(), ( ( "==================================" )))
 endfunction

     private function InitTrig_PlayerKillTypeCounter takes nothing returns nothing
          local trigger t=CreateTrigger()
          set ht=InitHashtable()
          call TriggerRegisterAnyUnitEventBJ(t,EVENT_PLAYER_UNIT_DEATH)
          call TriggerAddAction(t,function OnUnitDeath)
          set t=null
     endfunction
endscope


Hidden information:
EDIT:
Comment Below is outdated, found the errors in the code.
Hidden information:

Hey, tried to expand upon what you were doing and print out some messages. I have almost no experience with jass... I tried to make it work, but keep failing. After many different code alterations and several compiling issues, the compiling issue I last ended up with with this code:
Hidden information:
Collapse JASS:
scope PlayerKillTypeCounter initializer Init

     globals
          private hashtable ht
     endglobals

     private function OnUnitDeath takes nothing returns nothing
          local string playername=GetPlayerName(GetOwningPlayer(GetKillingUnit()))
          local string dieunitname=GetUnitName(GetDyingUnit())
          local string killingunitname=GetUnitName(GetKillingUnit())
        local integer killingunitnumber= (udg_killingunitnumber[( GetConvertedPlayerId(GetOwningPlayer(GetKillingUnit())) * GetUnitPointValueByType(GetUnitTypeId(GetKillingUnit())) ) + GetUnit
        PointValue(GetKillingUnit())])
       local integer killingunitnumberbytype= (udg_killingunitbynumbertype[( GetConvertedPlayerId(GetOwningPlayer(GetKillingUnit())) * GetUnitPointValueByType(GetUnitTypeId(GetKillingUnit())) )] + GetUnitPointValue(GetKillingUnit()) )
        local integer dyingunitnumber= udg_dyingunitnumber[( GetConvertedPlayerId(GetOwningPlayer(GetDyingUnit())) * GetUnitPointValueByType(GetUnitTypeId(GetDyingUnit())) )] + GetUnit
          PointValue(GetDyingUnit()) )
          //local integer killunitnumberbytype
         // set integer dyingunitnumber[( GetConvertedPlayerId(GetOwningPlayer(GetDyingUnit())) * GetUnitPointValueByType(GetUnitTypeId(GetDyingUnit())) )] = (dyingunitnumber[( GetConvertedPlayerId(GetOwningPlayer(GetDyingUnit())) * GetUnitPointValueByType(GetUnitTypeId(GetDyingUnit())) )] + GetUnit
          //PointValue(GetDyingUnit()) )
 
          //set integer killingunitnumber[( GetConvertedPlayerId(GetOwningPlayer(GetKillingUnit())) * GetUnitPointValueByType(GetUnitTypeId(GetKillingUnit())) )] = (killingunitnumber[( GetConvertedPlayerId(GetOwningPlayer(GetKillingUnit())) * GetUnitPointValueByType(GetUnitTypeId(GetKillingUnit())) )] + GetUnit
         // PointValue(GetKillingUnit()) )
          //set integer killingunitnumberbytype[( GetConvertedPlayerId(GetOwningPlayer(GetKillingUnit())) * GetUnitPointValueByType(GetUnitTypeId(GetKillingUnit())) )] = (killingunitnumberbytype[( GetConvertedPlayerId(GetOwningPlayer(GetKillingUnit())) * GetUnitPointValueByType(GetUnitTypeId(GetKillingUnit())) )] + GetUnit
          //PointValue(GetKillingUnit()) )
          set udg_killingunitnumber= killingunitnumber
          set udg_killingunitnumberbytype= killingunitbytype
          set udg_dyiungunitnumber= dyingunitnumber
          call SaveInteger(ht,killingunitnumber, killingunitnumberbytype, dyingunitnumber,LoadInteger(htkillingunitnumber, killingunitnumberbytype, dyingunitnumber)
          call DisplayTextToForce( GetPlayersAll(), ( ( "==================================" )))
          call DisplayTextToForce( GetPlayersAll(), udg_PlayerColors[GetConvertedPlayerId(GetOwningPlayer(GetKillingUnit()))] +GetPlayerName(GetOwningPlayer(GetKillingUnit())) + "'s Total Kills by: " + (killingunitname) + "s are- " + I2S(killingunitnumber) )))
          call DisplayTextToForce( GetPlayersAll(), udg_PlayerColors[GetConvertedPlayerId(GetOwningPlayer(GetKillingUnit()))] +GetPlayerName(GetOwningPlayer(GetKillingUnit())) + "'s Kills by Unit Type: " + (killingunitname) + "s of" + (dieunitname) + "are- " + I2S(killingunitnumberbytype) )))
          call DisplayTextToForce( GetPlayersAll(), udg_PlayerColors[GetConvertedPlayerId(GetOwningPlayer(GetDyingUnit()))] +GetPlayerName(GetOwningPlayer(GetDyingUnit())) + "'s Deaths by Unit Type: " + (dieunitname) + "s are- " + I2S(dyingunitnumber) )))
          call DisplayTextToForce( GetPlayersAll(), ( ( "==================================" )))
 endfunction

     private function Init takes nothing returns nothing
          local trigger t=CreateTrigger()
          set ht=InitHashtable()
          call TriggerRegisterAnyUnitEventBJ(t,EVENT_PLAYER_UNIT_DEATH)
          call TriggerAddAction(t,function OnUnitDeath)
          set t=null
     endfunction
endscope


was this:
Hidden information:
Syntax error, unexpected end of line?
Code:
        local integer killingunitnumber= (udg_killingunitnumber[( GetConvertedPlayerId(GetOwningPlayer(GetKillingUnit())) * GetUnitPointValueByType(GetUnitTypeId(GetKillingUnit())) ) + GetUnit
04-06-2010, 07:37 AM#4
Fluff
This is probably not the cause of the problem but...

I'm guessing you are using your udg_PlayerColors variable to store the color code strings like "|cffffcc00" but you don't have the ending "|r" in there.
04-06-2010, 10:42 AM#5
0zyx0
The following variables are not initialized:
killingunitnumber
killingunitnumberbytype
dyingunitnumber
That means they contain no value, and then some bad stuff happen when you pass them as arguments.

Anyway, there are many ways you can make your code more efficient. For example, you can use this, and maybe this. You also call the same functions many times with the same arguments, for example GetConvertedPlayerId(GetOwningPlayer(GetKillingUnit())). You only have to do those calls once, and then store the results in variables, to be used later. Also, some functions you use are not very efficient, for example GetConvertedPlayerId() can be replaced with [ljass]GetPlayerId()/LJASS], which does the same thing, except red is player 0, blue is player 1, etc. There are many other ways you can make your code faster and cleaner, just ask me if you would like to know more.
04-06-2010, 06:02 PM#6
PsycoMarauder
Fluff, I just kinda liked the whole line being the color of the player. Not the prob, lol. Oz, why do they have to be initialized if I didn't actually even use them? Oh well, removed em anyways., because I didnt actually even use them for anything. I was going to, but then just used regular ol' gui variables. Ok, so I fixed up that script to show the text all nicely and stuff, and optimized it... somewhat. Keep in mind I've never really messed with jass, but damn typing feels nicer than clicking. Also, I'm already using AutoIndex and Table for something else in the map, but it's for a system written by someone else, and I have no idea how I could properly use either of the two for this situation.

Aaanyways, now I have a new problem. So, obviously storing integers the way I am currently doing it is going to overlap. Player Number x Killing Unit's Point Value x Dying Unit's Point Value is going to overlap in many instances. Please bear in mind that I'm slightly smarter than a legally retarded person. I think using a hash table might be able to fix the issue, but I don't really know where to begin with that.

What about multidimensional arrays? Never had to use them, but could that be used to solve the overlapping integer issue? I'm just taking a guess at what a multidimensional array is, but could I specify a variable to be something like Variable[1,2,3]? I thought that that might be the case, but it doesn't appear to be, at least not in GUI... If so, I could just do killingunitnumber[PlayerNumber, KillingUnitPointValue, DyingUnitPointValue] = x. So yeah... thats my current question; is that how multidimensional arrays work, or would be doing Variable[1,2,3] just be referencing like Variable array numbers 1, 2, and 3?
04-06-2010, 07:49 PM#7
0zyx0
You can't have multidimensional arrays in jass. 2D arrays are emulated by vJass, using regular arrays. So what you should do is this:

X is the number of possible killing/dying unit types.
y is the point-value of the dying unit
z is the point-value of the killing unit
p is the player number of the owner of the killing unit
Then use the array index [p*X*X + y*X + z]

There's a limit to the size of arrays at 8191, so if (number of players)*X*X is greater than or equal to that number (for example, the max number of possible killing types is 26 if theres 12 players) , you will have to use a hashtable instead. That would be done (kind of) efficiently as:
Collapse JASS:
SaveInteger(ht, p, y*X + z, value)
LoadInteger(ht, p, y*X + z)
04-06-2010, 08:45 PM#8
Strilanc
That code isn't printing anything because you're using the values of uninitialized locals. It crashes before it gets anywhere useful. I can also see that it's very bug-prone. You're repeating yourself *a lot*. I see "GetConvertedPlayerId(GetOwningPlayer(GetKillingUnit()))" like 10 times. Assign it to a local and use that instead!

You should be using a hash table to store this information. An array is woefully inadequate, because you have to worry about not causing accidental collisions and things like that.
04-06-2010, 11:02 PM#9
PsycoMarauder
Thanks for the help. I actually did fix the code up and got it to work though. Looks like the integers would exceed the 8191 limit, so I'm going to have to use hash tables. Is there any tutorials or anything I can read up on about hash tables? I mean, a lot of stuff comes up when I search for it, but nothing that seems to explain how to use them. I'm guessing it just doesn't make sense to me because I'm just beginning to learn how to use jass.
04-07-2010, 01:36 AM#10
Strilanc
Hashtables are also available in GUI. You can use that to familiarize yourself with them, if you're still not comfortable with JASS.

You can think of a hashtable as an array, except it has two indexes and the indexes aren't limited to being below 8192. The hashtable also stores any type instead of a specified one (you use different functions for different types is all). The lack of a limit on the index is great, because it means you can use almost anything as an index. Unit types? Yep. Strings? Yep, use HashString. Units? Yep, use GetHandleId.

In a more general sense (outside of just JASS) a hashtable is a particular type of dictionary, which is a thing that indexes values using a key. The key and value can be almost anything (eg. you could have a hashtable which stored people's phone numbers [the value] based on their first name [the key]).