• 🏆 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!
  • 🏆 Hive's 6th HD Modeling Contest: Mechanical is now open! Design and model a mechanical creature, mechanized animal, a futuristic robotic being, or anything else your imagination can tinker with! 📅 Submissions close on June 30, 2024. Don't miss this opportunity to let your creativity shine! Enter now and show us your mechanical masterpiece! 🔗 Click here to enter!

Couple of questions

Status
Not open for further replies.
Level 10
Joined
Mar 31, 2009
Messages
732
Question 1:

How can I make this work?

JASS:
call PlaySound( "Sounds/Internal/Sound/Interface/Warning.wav" )
I want to be able to play a sound from the MPQs without registering it as a variable.

Question 2:

How can I force an item to be dropped when the unit carrying it dies? Ties into question 3...

Question 3:

What event should I use for "Any unit drops specific item"? Should cover the item being dropped because that unit died, the user telling that unit to drop the item on the ground (I've covered that with EVENT_PLAYER_UNIT_DROP_ITEM), and some other trigger forcing the item being dropped for some other reason.

Question 4:

How can I control who can pick up a specific item?
Like say I only want Red and Blue to be able to pick up a specific item I've created, how would I go about that?
 
Level 8
Joined
Jan 8, 2010
Messages
493
<-- JASS noob :p

2. I know there's a Stats - Dropped When Carrier Dies field in the Item Tab of the Object Editor. If that doesn't work, there's also a Item - Make Item Drop From Heroes Upon Death in the Trigger Editor.

3. i think if this is connected to number 4 you can just create an item (make that item carried by the dying unit not droppable?) so you can set it to a variable and use that Change Owner thing. or if not, there a GUI condition, Boolean -> Hero - Hero Has Item and Boolean -> Hero - Hero Has Item of Type. by using it alongside the event Unit - Unit Dies, i believe it will detect what unit dies and if it has that item, but of course making sure that the item in the condition is the one droppable.

4. There's an action Item - Change Owner. I suggested that you just create an item if the item dropped is the one you want to be picked because it can be easily tied to variable via Last Created Item with the Item - Change Owner. then when a player picks the item, with condition Player Comparison - Owner of (Item) Equal To (Player), you can drop it if it is not Red or Blue.
 
Level 10
Joined
Mar 31, 2009
Messages
732
Hmmm.

Boolean -> Hero - Hero Has Item and Boolean -> Hero - Hero Has Item of Type
I also want it to work when non-hero units pick up the item though. Will this still cover that situation?


Another question:

Event Unit - Unit within range "A unit comes within xx of (Unit)".
"Use Event Response - Triggering Unit to refer to the unit coming within range of the unit", but how do I refer to the unit it came within range of?
 
Level 18
Joined
Jan 21, 2006
Messages
2,552
Is this the type of thing you're looking for:

JASS:
function PlaySoundEx takes string soundpath returns nothing
    local sound s = CreateSoundFromLabel(soundpath, false, true, true, 0, 0)
    call StartSound(s)
    call KillSoundWhenDone(s)
    set s=null
endfunction

Teelo said:
I also want it to work when non-hero units pick up the item though. Will this still cover that situation?

The function Hero - Hero has Item of Type uses the function UnitHasItemOfTypeBJ. In other words, yes, that will cover that situation.

Teelo said:
but how do I refer to the unit it came within range of?

There are a few options.
JASS:
native GroupEnumUnitsInRange takes group whichGroup, real x, real y, real radius, boolexpr filter returns nothing

At first I didn't realize these functions were included in the API, so I'll make sure you do to:

JASS:
constant native IsUnitInRange takes unit whichUnit, unit otherUnit, real distance returns boolean
constant native IsUnitInRangeLoc takes unit whichUnit, location whichLocation, real distance returns boolean
constant native IsUnitInRangeXY takes unit whichUnit, real x, real y, real distance returns boolean

This may work. It might be a little too much though for such a measly task.

JASS:
function UnitInRange takes unit main, unit other returns nothing
//************************
//* Unit Within Range
//* ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
//* When you use "unitinrange.create( someUnit, rangeCheck )" it will register a "TriggerRegisterUnitInRange" event and
//* cause a response whenever a unit comes within range of that specified unit.
//*
//* Once this happens, the structure automatically retrieves the necessary data and calls the function "UnitInRange", which
//* you'll notice has two unit parameters. These parameters represent the unit that the trigger was registered to (main)
//* and the unit that would normally be referenced as "GetTriggerUnit" (other).
//*
endfunction

struct unitinrange
    public unit     inRangeSource   = null
    public trigger  inRange         = CreateTrigger()
    
    private static hashtable    table       = InitHashtable()
    
    // The .destroy() method really should never need to be called, but in case you wanted to for some reason I
    // included the necessary "cleaning up" junk.
    method onDestroy takes nothing returns nothing
        call RemoveSavedInteger(thistype.table, GetHandleId(.inRange), 1)
        call DestroyTrigger(.inRange)
    endmethod
    
    static method onUnitInRange takes nothing returns nothing
        local thistype dat=LoadInteger(.table, GetHandleId(GetTriggeringTrigger()), 1)
        call UnitInRange(dat.inRangeSource, GetTriggerUnit())
    endmethod
    
    static method create takes unit main, real range returns thistype
        local thistype dat=.allocate()
        set dat.inRangeSource=main
        call TriggerRegisterUnitInRange(dat.inRange, main, range, null)
        call TriggerAddAction(dat.inRange, function .onUnitInRange)
        call SaveInteger(.table, GetHandleId(dat.inRange), 1, dat)
        return dat
    endmethod
endstruct
 
Last edited:
Level 18
Joined
Jan 21, 2006
Messages
2,552
When I paste the code you just showed me in my blank map (along with the function) it does not crash.

I think you may need to use double "\"s.

To be honest there really is no good information on sounds. I've been searching for awhile now trying to piece it together.

It would seem that Sounds only work when they are marked as "Use As Sound in the Sound editor.

I came across this tutorial at The Hive's tutorials bank.

I immediately retract my statement about having to "Use As Sound". There are quite a few things to be careful of however when you are creating a sound, such as the channel

Here:

JASS:
function DoSound takes string path returns nothing
    local sound s=CreateSound(path, false, false, false, 10, 10, "")
    call StartSound(s)
    call KillSoundWhenDone(s)
    set s=null
endfunction

...
    call DoSound("Sound\\Interface\\Error.wav")
...

This will create a completely default sound of "error.wav".

If you're trying to make a 3D sound, then you'll need to call this functions before-hand.

JASS:
native SetSoundPosition takes sound soundHandle, real x, real y, real z returns nothing
 
Last edited:
Level 10
Joined
Mar 31, 2009
Messages
732
I just want to play one of the sounds from the MPQ files, and want to keep it to the triggers so I can port my code around to different maps.

My code is crashing somewhere in here, I assume its the play sound:

JASS:
function Trig_CTF_Flag_Picked_Up_Actions takes nothing returns nothing requires minorLibs
    local integer playerID = 0
    local item pickedUpItem = GetManipulatedItem()
    local unit pickedUpUnit = GetTriggerUnit()
    local player picker = GetOwningPlayer(pickedUpUnit)
    local player pickee
    loop
        exitwhen playerID == bj_MAX_PLAYERS
        if (pickedUpItem == playerFlags[playerID]) then
            set pickee = Player(playerID)
            if (IsPlayerAlly(picker, pickee)) then
                call UnitDropItemPoint(pickedUpUnit, playerFlags[playerID], GetUnitX(pickedUpUnit), GetUnitY(pickedUpUnit))
            endif
            call UnitShareVision( pickedUpUnit, pickee, true )
            call PlaySoundEx( "Sounds\\Internal\\Sound\\Interface\\Warning.wav" )
            call DisplayTextToPlayer(pickee, 0, 0, "Your flag has been picked up!")
        endif
        set playerID = playerID + 1
    endloop
endfunction
 
Level 10
Joined
Mar 31, 2009
Messages
732
Arrgh. Okay its not the sound thats crashing my client.

Its somewhere in here though, I can't figure out exactly whats causing it, because its happened when a hero picks up an item, but sometimes just when a hero walks up to the item.

If I disable this whole trigger, it doesnt crash. Anyway:

JASS:
function Trig_CTF_Flag_Picked_Up_Conditions takes nothing returns boolean
    local integer theItem = GetItemTypeId(GetManipulatedItem())
    if ( theItem == 'flag' or theItem == 'nflg' or theItem == 'oflg' or theItem == 'uflg' ) then
        return true
    endif
    return false
endfunction

function Trig_CTF_Flag_Picked_Up_Actions takes nothing returns nothing requires minorLibs
    local integer playerID = 0
    local item pickedUpItem = GetManipulatedItem()
    local unit pickedUpUnit = GetTriggerUnit()
    local player picker = GetOwningPlayer(pickedUpUnit)
    local player pickee
    loop
        exitwhen playerID == bj_MAX_PLAYERS
        if (pickedUpItem == playerFlags[playerID]) then
            set pickee = Player(playerID)
            if (IsPlayerAlly(picker, pickee)) then
                call UnitDropItemPoint(pickedUpUnit, playerFlags[playerID], GetUnitX(pickedUpUnit), GetUnitY(pickedUpUnit))
                return
            endif
            call UnitShareVision( pickedUpUnit, pickee, true )
            //call PlaySoundEx( "Sound\\Interface\\Warning.wav" )
            call DisplayTextToPlayer(pickee, 0, 0, "Your flag has been picked up!")
        endif
        set playerID = playerID + 1
    endloop
endfunction

//===========================================================================
function InitTrig_CTF_Flag_Picked_Up takes nothing returns nothing
    set gg_trg_CTF_Flag_Picked_Up = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_CTF_Flag_Picked_Up, EVENT_PLAYER_UNIT_PICKUP_ITEM )
    call TriggerAddCondition( gg_trg_CTF_Flag_Picked_Up, Condition( function Trig_CTF_Flag_Picked_Up_Conditions ) )
    call TriggerAddAction( gg_trg_CTF_Flag_Picked_Up, function Trig_CTF_Flag_Picked_Up_Actions )
    call DisableTrigger(gg_trg_CTF_Flag_Picked_Up)
endfunction

playerFlags[x] is initialised when the flags are spawned in another trigger. Because the flags are only spawned for active players, the variable either stays null or unallocated (not sure how it works) for the other players, and I wonder if thats causing the problem?
 
Level 18
Joined
Jan 21, 2006
Messages
2,552
Try initializing them to (null). Even still, it shouldn't be crashing your game when a hero walks next to an item. It could potentially kill the thread (no more executions) but it shouldn't crash War3.exe.
 
Level 10
Joined
Mar 31, 2009
Messages
732
Dammit! Lol...

Is it safe to use that PlaySound inside of a GetLocalPlayer? Or is there another way to only play it for a specific player?


Annnnnnnnnnd another question!

I'm trying to make it so if a unit carrying "the flag" stealths, then "the flag" is dropped. I have that working, but now I realised I also need to apply this if the unit town portals or uses a staff of teleportation.
Any insight on where to get started?


Question 3 of this post!

How can I make a unit unselectable? I think I remember something about making it a locust, but I need a way to only do this with a trigger? I want the unit to still be there and in the way of other units, but just be unselectable/untargettable by the user.
 
Level 18
Joined
Jan 21, 2006
Messages
2,552
Teelo said:
Is it safe to use that PlaySound inside of a GetLocalPlayer? Or is there another way to only play it for a specific player?

I'm pretty sure its safe.

Teelo said:
I'm trying to make it so if a unit carrying "the flag" stealths, then "the flag" is dropped. I have that working, but now I realised I also need to apply this if the unit town portals or uses a staff of teleportation.
Any insight on where to get started?

What exactly do you mean, "stealth". Also the way you had your triggers set up you were moving the flag back to the circle of power whenever it was dropped, is this to be excluded from that?

For the second part, do you mean... you want the flag to be dropped if the unit uses town portal?

Teelo said:
How can I make a unit unselectable? I think I remember something about making it a locust, but I need a way to only do this with a trigger? I want the unit to still be there and in the way of other units, but just be unselectable/untargettable by the user.

If you add the ability Aloc or, Locust, the unit will become unaffected by pathing in addition to being unselectable, untargetable, and invulnerable. Other than that the unit will act in the same way as normal unit.

Another trick that works with the Locust ability is the Chaos ability, but that (I believe) gives the pathability back to the unit but it also makes the unit targetable. I suppose at that point you could make the unit invulnerable. Look at the WarCraft III Ability Guide in my signature for more information on how to use Chaos and Locust.
 
Level 10
Joined
Mar 31, 2009
Messages
732
Hmm. Well I want to make those Circle of Powers still exist there and be in the way of building on top of them, just want to make them unselectable, cause I noticed it was kind of difficult to select the nightelf flag sitting on top of it.
Would locust or chaos retain its stopping stuff being built on top of it?

I've got the stealth part working fine. The event fires when a unit gains Windwalk or Sorc's Invisibility...
I thought about it, catching it being teleported probably wont be easy. It needs to cover the unit using a scroll of town portal, a staff of teleportation, but also needs to include being affected by a friendly unit using a staff of preservation, and being town portalled by another unit doing th TP. Might be too much work to even bother.


EDIT: The PlaySoundEx() caused a desync =/
 
Level 18
Joined
Jan 21, 2006
Messages
2,552
You can stop it from being selected altogether (it can be dragged over though). Simply do:

JASS:
call UnitAddAbility(playerCops[ playerID ], 'Aloc')
call UnitRemoveAbility(playerCops[ playerID ], 'Aloc')
call ShowUnit(playerCops[playerID], false)
call ShowUnit(playerCops[playerID], false)

Lots of the abilities are far more powerful than the code available from the API. You should read the Ability Guide in my signature like I said.

Teelo said:
EDIT: The PlaySoundEx() caused a desync =/

I'm pretty sure sounds don't cause desyncs. I wouldn't be surprised that there is something I've done wrong though since I'm not all that familiar with sounds, and there really isn't much for tutorials.
 
Level 10
Joined
Mar 31, 2009
Messages
732
Okay back to my stealth question.
I've done a bit of testing, and found a problem I'm stuck on with Sorcs casting Invisibility.

I use the event EVENT_PLAYER_UNIT_SPELL_FINISH, and it catches Windwalk, no problems. It also catches Invisibility, but I can't get the unit that Invisibility was cast on.
When it catches Windwalk, GetTriggerUnit returns the Blademaster.
When it catches Invisibility, GetTriggerUnit returns the sorc. GetSpellTargetUnit returns null!
 
Level 10
Joined
Mar 31, 2009
Messages
732
Ahh yeah that works. Thanks.

To cover town portalling and such, I've got EVENT_PLAYER_UNIT_USE_ITEM. I can catch the unit that uses the item with GetManipulatingUnit, but when I try GetSpellTargetUnit to get the target of the item being used (Staff of preservation), it returns null. What should I use?
 
Level 10
Joined
Mar 31, 2009
Messages
732
Okay I'm doing that, its picking up the event, but...

JASS:
function onPortalFilter takes nothing returns boolean
    local integer itt = GetSpellAbilityId()
    call BJDebugMsg("DEBUG. Item used: " + GetObjectName(itt))
    return (itt == 'Altp' or itt == 'ANsa' or itt == 'ANpr' or itt == 'Almt')
endfunction
That variable is getting the item code, but it doesn't seem to be successfully matching against any of those 4 codes. I can't figure out a way to print out the code in a debug message either, other than as the raw number (how do I convert that?).
 
Last edited:
Level 10
Joined
Mar 31, 2009
Messages
732
Sure. Whole trigger:

JASS:
library CTFPortal initializer init

globals
    trigger CTFPortalTrigger = CreateTrigger()
endglobals

public function enable takes nothing returns nothing
    call EnableTrigger(CTFPortalTrigger)
endfunction

function onPortalFilter takes nothing returns boolean
    local integer itt = GetSpellAbilityId()
    //call BJDebugMsg("DEBUG. Item used: " + GetObjectName(itt))
    return (itt == 'Altp' or itt == 'ANsa' or itt == 'ANpr' or itt == 'Almt')
endfunction

function onPortal takes nothing returns nothing
    local unit castingUnit = GetTriggerUnit()
    local unit targetUnit = GetSpellTargetUnit()
    local integer itt = GetSpellAbilityId()
    local integer playerID = 0
    local item flag
    //call BJDebugMsg("DEBUG. Portal item used: " + AbilityId2String(itt))
    // Scroll of town portal or staff of teleportation
    if (itt == 'Altp' or itt == 'Almt') then
        loop
            exitwhen (playerID == bj_MAX_PLAYERS)
            set flag = playerFlags[playerID]
            if (UnitHasItem(castingUnit, playerFlags[playerID])) then
                set playerFlags[playerID] = CreateItem(GetItemTypeId(flag), GetUnitX(playerCops[playerID]), GetUnitY(playerCops[playerID]))
                call RemoveItem(flag)
                call UnitShareVision(castingUnit, Player(playerID), false)
                call DisplayTextToPlayer(Player(playerID), 1, 1, "Your flag was returned because the carrier used a teleport item.")
            endif
            
            set playerID = playerID + 1
        endloop
    endif
    
    // Staff of preservation or staff of sanctuary
    if (itt == 'ANsa' or itt == 'ANpr') then
        loop
            exitwhen (playerID == bj_MAX_PLAYERS)
            set flag = playerFlags[playerID]
            if (UnitHasItem(targetUnit, playerFlags[playerID])) then
                set playerFlags[playerID] = CreateItem(GetItemTypeId(flag), GetUnitX(playerCops[playerID]), GetUnitY(playerCops[playerID]))
                call RemoveItem(flag)
                call UnitShareVision(targetUnit, Player(playerID), false)
                call DisplayTextToPlayer(Player(playerID), 1, 1, "Your flag was returned because the carrier was affected by a teleport item.")
            endif
            
            set playerID = playerID + 1
        endloop
    endif
    
    set castingUnit = null
    set targetUnit = null
    set flag = null
endfunction

private function init takes nothing returns nothing
    call TriggerRegisterAnyUnitEventBJ(CTFPortalTrigger, EVENT_PLAYER_UNIT_SPELL_EFFECT)
    call TriggerAddCondition(CTFPortalTrigger, Condition(function onPortalFilter))
    call TriggerAddAction(CTFPortalTrigger, function onPortal)
    call DisableTrigger(CTFPortalTrigger)
endfunction

endlibrary
 
Level 18
Joined
Jan 21, 2006
Messages
2,552
Why don't you try matching them like so:

JASS:
call BJDebugMsg(I2S(GetSpellAbilityId()))
call BJDebugMsg(I2S('AItp'))

Do the same for all of them, and make sure that you're checking the right IDs.
 
Level 10
Joined
Mar 31, 2009
Messages
732
I'll come back to that one later, as I've annoyed myself too much today on that problem.

Current problem is setting up a multiboard.
Its supposed to have 3 columns (Player name / Their gold / Their lumber).
First row is the headers, then one row per playing player.

I've got it updating every 5 seconds, but its acting weird. Its not updating the first row, and the last row is getting multiple lines written over it.

Have I screwed up my loop?

JASS:
library GreedLeaderboard

globals
    multiboard greedMultiboard
endglobals

function update takes nothing returns nothing
    local integer row = 0
    local integer playerID = 0
    
    call MultiboardSetRowCount(greedMultiboard, 1)
    loop
        exitwhen playerID == bj_MAX_PLAYERS
        if (GetPlayerSlotState(Player(playerID)) == PLAYER_SLOT_STATE_PLAYING) then
            set row = row + 1
            call MultiboardSetRowCount(greedMultiboard, row + 1)
            call MultiboardSetItemValueBJ(greedMultiboard, 1, row, GetPlayerName(Player(playerID)))
            call MultiboardSetItemValueBJ(greedMultiboard, 2, row, I2S(GetPlayerState(Player(playerID), PLAYER_STATE_RESOURCE_GOLD)))
            call MultiboardSetItemValueBJ(greedMultiboard, 3, row, I2S(GetPlayerState(Player(playerID), PLAYER_STATE_RESOURCE_LUMBER)))
        endif
        set playerID = playerID + 1
    endloop
endfunction

public function setup takes nothing returns nothing
    set greedMultiboard = CreateMultiboard()
    call MultiboardSetColumnCount(greedMultiboard, 3)
    call MultiboardSetRowCount(greedMultiboard, 1)
    call MultiboardSetItemValueBJ(greedMultiboard, 1, 1, "Player")
    call MultiboardSetItemValueBJ(greedMultiboard, 2, 1, "Gold")
    call MultiboardSetItemValueBJ(greedMultiboard, 3, 1, "Lumber")
    call MultiboardSetItemsWidth(greedMultiboard, 0.1)
    call MultiboardDisplay(greedMultiboard, true)
    call TimerStart(CreateTimer(), 5, true, function update)
endfunction

endlibrary
 
Level 18
Joined
Jan 21, 2006
Messages
2,552
You should really separate these questions into different threads. Also use the non-BJ function MultiboardSetItemValue. There is a lot of unnecessary code in the BJ function.

What are you doing with your rows... you constantly change how many rows are in the multiboard which is probably where your errors are coming from.
 
Level 10
Joined
Mar 31, 2009
Messages
732
I don't wanna spam up the forum with a bunch of threads :S

I'm updating the rows for when players leave and such... I probably haven't considered whether PLAYER_SLOT_STATE_PLAYING updates with that.

Good point about the multiboarditem, I should go figure out how they work.
---
Its doing exactly the same nonsense like this:
JASS:
function update takes nothing returns nothing
    local integer row = 0
    local integer playerID = 0
    local multiboarditem mbi
    
    call MultiboardSetRowCount(greedMultiboard, 1)
    loop
        exitwhen playerID == bj_MAX_PLAYERS
        if (GetPlayerSlotState(Player(playerID)) == PLAYER_SLOT_STATE_PLAYING) then
            set row = row + 1
            call MultiboardSetRowCount(greedMultiboard, row + 1)
            set mbi = MultiboardGetItem(greedMultiboard, row, 0)
            call MultiboardSetItemValue(mbi, GetPlayerName(Player(playerID)))
            call MultiboardReleaseItem(mbi)
            set mbi = MultiboardGetItem(greedMultiboard, row, 1)
            call MultiboardSetItemValue(mbi, I2S(GetPlayerState(Player(playerID), PLAYER_STATE_RESOURCE_GOLD)))
            call MultiboardReleaseItem(mbi)
            set mbi = MultiboardGetItem(greedMultiboard, row, 2)
            call MultiboardSetItemValue(mbi, I2S(GetPlayerState(Player(playerID), PLAYER_STATE_RESOURCE_LUMBER)))
            call MultiboardReleaseItem(mbi)
        endif
        set playerID = playerID + 1
    endloop
endfunction
:(
 
Level 18
Joined
Jan 21, 2006
Messages
2,552
You should update the rows when players leave on EVENT_PLAYER_LEAVE, rather than in a constant loop. You're also setting the rows back to 1 on each iteration, which is probably screwing with your data. Actually, knowing you, it probably isn't its probably some strange bug but that's besides the point.

Here, try this.

JASS:
library GreedMultiboard initializer init

globals
    // If you want the multiboard to be referenced from outside the scope/library, then make sure you give it the public
    // prefix so that the name does not conflict.
    public multiboard           infoBoard            
    //
endglobals

// This function should be private. You don't want the name to conflict (update is pretty generic) with anything else and
// you don't want this function to be referenced from outside the scope/library.
private function update takes nothing returns nothing
    local integer i = 1
    local integer m = MultiboardGetRowCount(infoBoard)
    local multiboarditem mi = null
    local player p
    loop
        exitwhen i==m
        set p=Player(i-1)
        set mi=MultiboardGetItem(infoBoard, i, 0)
        call MultiboardSetItemValue(mi, GetPlayerName(p))
        call MultiboardReleaseItem(mi)
        set mi=MultiboardGetItem(infoBoard, i, 1)
        call MultiboardSetItemValue(mi, I2S(GetPlayerState(p, PLAYER_STATE_RESOURCE_GOLD)))
        call MultiboardReleaseItem(mi)
        set mi=MultiboardGetItem(infoBoard, i, 2)
        call MultiboardSetItemValue(mi, I2S(GetPlayerState(p, PLAYER_STATE_RESOURCE_LUMBER)))
        call MultiboardReleaseItem(mi)
        set i=i+1
    endloop
    set mi=null
    set p=null
endfunction

public function setup takes nothing returns nothing
    local integer i = 0
    local integer m = 0
    local player p
    local multiboarditem mi = null
    // You only want to create enough rows for the amount of playing (non-computer) players, I assume.
    loop
        exitwhen(i==12)
        set p=Player(i)
        if GetPlayerSlotState(p)==PLAYER_SLOT_STATE_PLAYING and GetPlayerController(p)==MAP_CONTROL_USER then
            set m=m+1
        endif
        set i=i+1
    endloop
    set p=null
    
    call MultiboardSetColumnCount(infoBoard, 3)
    call MultiboardSetRowCount(infoBoard, 1+m)
    
    set mi=MultiboardGetItem(infoBoard, 0, 0)
    call MultiboardSetItemValue(mi, "Player")
    call MultiboardReleaseItem(mi)
    set mi=MultiboardGetItem(infoBoard, 0, 1)
    call MultiboardSetItemValue(mi, "Gold")
    call MultiboardReleaseItem(mi)
    set mi=MultiboardGetItem(infoBoard, 0, 2)
    call MultiboardSetItemValue(mi, "Lumber")
    call MultiboardReleaseItem(mi)
    set mi=null
    
    call MultiboardSetTitleText(infoBoard, "Greed")
    call MultiboardSetItemsWidth(infoBoard, 0.1)
    call MultiboardSetItemsStyle(infoBoard, true, false)
    call MultiboardDisplay(infoBoard, true)
    
    call TimerStart(GetExpiredTimer(), 1, true, function update)
endfunction

public function init takes nothing returns nothing
    set infoBoard = CreateMultiboard()
    // Multiboards cannot be created on map-initialization, but that doesn't mean they cannot be created 0-seconds AFTER map
    // initialization.
    call TimerStart(CreateTimer(), 0, false, function setup)
endfunction

endlibrary

It would be problematic if a player were to leave, since I use the player associated with the current row. This means that the first row will be player 1, the second will be player 2. If you were to loop through the players it would be easier to reference the correct row-count. I'm sure you know how to play around with it.
 
Last edited:
Why do you use:
JASS:
            call MultiboardSetRowCount(greedMultiboard, row + 1)

But then, you set the values of the row before it:
JASS:
            set mbi = MultiboardGetItem(greedMultiboard, row, 0)

So say it is running on player 1 (red). It will set the rows to 2. Then it will set the row 1 with Player 1's values?
All the way toward the end, you'd have an extra row if I'm not mistaken. You'd have 13 and you'd use only 12. I'm just guessing though, too lazy to test it at the moment. =P You also set the row count to 1 each time.

EDIT: Bah, beat to the post.
 
Level 10
Joined
Mar 31, 2009
Messages
732
I'm still trying to figure it out. Something in there is 0-based, something is 1-based.
I'm making the number of rows (number of players) + 1 (for the header). According to the BJ function, MultiboardGetItem is 0-based.
So row 0 should have the headers, row 1 should be player(0), row 2 should be player(1), unless theres a gap in active players or something.

You're also setting the rows back to 1 on each iteration, which is probably screwing with your data.
Probably. I'll give it a shot without changing the row count.
 
Level 18
Joined
Jan 21, 2006
Messages
2,552
The reason I hate using BJ functions is sometimes they make their rows start off at 1, rather than 0. This can screw your math logic up sometimes, even though its not hard to fix.

Here's the perfect example:
JASS:
function GetConvertedPlayerId takes player whichPlayer returns integer
    return GetPlayerId(whichPlayer) + 1
endfunction
 
Status
Not open for further replies.
Top