• Listen to a special audio message from Bill Roper to the Hive Workshop community (Bill is a former Vice President of Blizzard Entertainment, Producer, Designer, Musician, Voice Actor) 🔗Click here to hear his message!
  • Read Evilhog's interview with Gregory Alper, the original composer of the music for WarCraft: Orcs & Humans 🔗Click here to read the full interview.

[JASS] Making a bossloot system but kinda stuck.

Status
Not open for further replies.
Level 19
Joined
Oct 12, 2007
Messages
1,821
Hey there.

I need some help with making this bossloot system. But first I need to tell you something about how the loot goes in my orpg.

The normal loot system is done and the reward loot system aswel.

Normal loot system:
A unit dies and drops loot. Then a unit called 'lootbag' spawns for the killing unit, and the item that dropped will be given to his inventory. Then when the player clicks the item in his 'lootbag''s inventory he will obtain the item in his own inventory.

Reward loot system:
Same as above, but whenever there are 2 or more items in 1 lootbag, the player can only chose one of them to go to his real inventory. After clicking an item, the others will disappear.

Now here's the code of the boss loot system I'm trying to make. Please take a look at it. I described quite a few things inside the trigger. There's just one thing I'm kinda stuck with, and I would like to ask someone to help me out with it.

JASS:
//=======================================================================================================================
// Bossloot
// How does it work:
// With CreateBossLoot(boss, players, item1, item2, item3, item4, item5, item6) I'm able to let a boss drop loot
// this loot will be given to a treasure chest. Each player that owned a hero that was in the area of killing the boss
// will get a treasure chest (with invisibility) for himself. This treasure chest has the dropped items.
// (A treasure chest is a unit with a 6 slot inventory)
// When clicking an item inside the treasure chest's inventory the player will roll for the item.
// Each player is able to roll 3 times and the first roll gets +40 and the second roll +20.
// When the Treasure Chests disappear (after the 20 second timer) the loot where players rolled will be distributed
// to the highest rollers.
// If nobody rolled on an item a random player will also obtain that item.
//
// So what basically happens is:
// a) A unit clicks the item in his Treasure Chest.
// b) A roll will appear and the player's roll on that item will be saved until the Treasure Chest disappears.
// c) The player with the highest roll on an item will obtain the item after the Treasure Chest disappears.
//
//
// Notes:
// 1) It shouldn't be possible that if 2 players roll the same amount none/both of them gets the item.
// 2) 
//=======================================================================================================================


library bossloot

globals

    constant integer array RollBonus[]
    constant integer array FirstRoll[]
    constant integer array SecondRoll[]
    constant integer array ThirdRoll[]
    constant integer array FirstItem[]
    constant integer array SecondItem[]
    constant integer array ThirdItem[]
    
    constant timer TreasureChestDuration[]

endglobals

private function LootDistribution takes nothing returns nothing
    ///This is the point I'm currently stuck a littlebit.
    ///I want the loot to be distributed here.
    ///So I want this function to check which players won loot by checking their rolls
    ///After that I want this function to create an item of that itemid for those players then
endfunction


///unit boss = killed boss
///group players = Hero's that killed the boss together
///integer item1-6 means the item id's. A boss can drop up to a maximum of 6 items.
function CreateBossLoot takes unit boss, group players, integer item1, integer item2, integer item3, integer item4, integer item5, integer item6 returns nothing
    local real x = GetUnitX(boss)
    local real y = GetUnitY(boss)
    local real face = GetUnitFacing(boss)
    local player p = GetOwningPlayer(u)
    local unit chest
    local item reward
    local unit u
    local integer timerid = GetPlayerId(GetOwningPlayer(FirstOfGroup(players)))

    loop
        set u FirstOfGroup(players)
        exitwhen u = null
        set chest = CreateUnit(GetOwningPlayer(u),'n00H', x, y, face)
        call UnitApplyTimedLife(chest, 'BTLF', 20.)

        if item1 > 0 then
            set reward = CreateItem(item1, x, y)
            call UnitAddItem(chest, reward)
        endif
        if item2 > 0 then
            set reward = CreateItem(item2, x, y)
            call UnitAddItem(chest, reward)
        endif
        if item3 > 0 then
            set reward = CreateItem(item3, x, y)
            call UnitAddItem(chest, reward)
        endif
        if item4 > 0 then
            set reward = CreateItem(item4, x, y)
            call UnitAddItem(chest, reward)
        endif
        if item5 > 0 then
            set reward = CreateItem(item5, x, y)
            call UnitAddItem(chest, reward)
        endif
        if item6 > 0 then
            set reward = CreateItem(item6, x, y)
            call UnitAddItem(chest, reward)
        endif
        call GroupRemoveUnit(players, u)
    endloop
    
    call TimerStart(TreasureChestDuration[timerid],20.,false,function LootDistribution)
    ///Its impossible for a player to defeat 2 bosses within 20 seconds of eachother. But it is possible that 2 bosses
    ///die within 20 seconds of eachother from multiple players at different zones in the map.
    ///Thats why I used the array for TreasureChestDuration. Now it starts the timer for a player that killed the boss.     
endfunction

private function itemPickUpCheck takes nothing returns boolean
    return GetUnitTypeId(GetManipulatingUnit()) == 'n00H'  ///This is the id of the Treasure Chest///
endfunction

private function itemPickUp takes nothing returns nothing
    local integer i = GetPlayerId(GetOwningPlayer(GetManipulatingUnit()))
    local unit u
    local string name = GetPlayerName(Player(i))
    local integer chance
    local string bonusstring
    local string laststring
    
    ///Rolling
    set chance = GetRandomInt(0,100)
    if RollBonus[i] == 40 then
        set FirstRoll[i] = chance + RollBonus[i]
        set FirstItem[i] = GetItemTypeId(GetManipulatedItem())
        set bonusstring = " |cff00ff00(+40)|r for "
        set laststring = " on his |cff00ff00first|r roll!"
    elseif RollBonus[i] == 20 then
        set SecondRoll[i] = chance + RollBonus[i]
        set SecondItem[i] = GetItemTypeId(GetManipulatedItem())
        set bonusstring = " |cffffde08(+20)|r for "
        set laststring = " on his |cffffde08second|r roll!"
    elseif RollBonus[i] == 0 then
        set ThirdRoll[i] = chance + RollBonus[i]
        set ThirdItem[i] = GetItemTypeId(GetManipulatedItem())
        set bonusstring = " (+0) for "
        set laststring = " on his third roll!"
    endif
    set msg = (name+(" has rolled "+(I2S(chance+RollBonus[i])+((bonusstring)+(GetItemName(GetManipulatedItem()))+(laststring)))))
    
    loop
        exitwhen i > GetPlayers()
        call DisplayTimedTextToPlayer(Player(i),0,0,10,msg)
        set i = i + 1
    endloop
      
endfunction

private function itemPickUpCheck takes nothing returns boolean
    return GetUnitTypeId(GetManipulatingUnit()) == 'n00H'  ///This is the id of the Treasure Chest///
endfunction

private function init takes nothing returns nothing
    local trigger trig = CreateTrigger()
    
    call TriggerRegisterAnyUnitEventBJ(trig,EVENT_PLAYER_UNIT_USE_ITEM)
    call TriggerAddAction(trig,function itemPickUp)
    call TriggerAddCondition(trig,Condition(function itemPickUpCheck))

endfunction
endlibrary


EDIT:
Hmm the thing that will currently help me most is if I can do various actions for a group withoud having to use FirstOfGroup so I don't have to remove units out of a group. Is that the 'ForGroup' command? I have no idea how that actually works.
 
Last edited:
By the way, I noticed this:
JASS:
set u FirstOfGroup(players)
You forgot the equal sign.

And the ForGroup function is definitely the best option for the case of structs, because you can browse and allocate members quite fast, something that comes in handy for the ForGroup function (e.g. when you want to check whether the caster is an enemy of the enumerated unit).
 
Level 19
Joined
Oct 12, 2007
Messages
1,821
Ahhh.
Thanks for the help guys.

This is what I got right now.
Still not working properly, but I'm fixing the typo's and mistakes right now.
And about structs. I might add a struct later on. Don't know that much about structs, but I might be able to add one myself.

JASS:
//=======================================================================================================================
// Bossloot
// How does it work:
// With CreateBossLoot(boss, players, item1, item2, item3, item4, item5, item6) I'm able to let a boss drop loot
// this loot will be given to a treasure chest. Each player that owned a hero that was in the area of killing the boss
// will get a treasure chest (with invisibility) for himself. This treasure chest has the dropped items.
// (A treasure chest is a unit with a 6 slot inventory)
// When clicking an item inside the treasure chest's inventory the player will roll for the item.
// Each player is able to roll 3 times and the first roll gets +40 and the second roll +20.
// When the Treasure Chests disappear (after the 20 second timer) the loot where players rolled will be distributed
// to the highest rollers.
// If nobody rolled on an item a random player will also obtain that item.
//
// So what basically happens is:
// a) A unit clicks the item in his Treasure Chest.
// b) A roll will appear and the player's roll on that item will be saved until the Treasure Chest disappears.
// c) The player with the highest roll on an item will obtain the item after the Treasure Chest disappears.
//
//
// Notes:
// 1) It shouldn't be possible that if 2 players roll the same amount none/both of them gets the item.
// 2) 
//=======================================================================================================================


library bossloot

globals

    constant integer array RollBonus[]
    constant integer array FirstRoll[]
    constant integer array SecondRoll[]
    constant integer array ThirdRoll[]
    constant integer array FirstRollItem[]
    constant integer array SecondRollItem[]
    constant integer array ThirdRollItem[]
    
    constant integer array Item1[]
    constant integer array Item2[]
    constant integer array Item3[]
    constant integer array Item4[]
    constant integer array Item5[]
    constant integer array Item6[]
    
    constant unit array ItemWinner1[]
    constant unit array ItemWinner2[]
    constant unit array ItemWinner3[]
    constant unit array ItemWinner4[]
    constant unit array ItemWinner5[]
    constant unit array ItemWinner6[]
    
    constant timer TreasureChestDuration[]

endglobals

private function LootDistribution takes nothing returns nothing
    local unit u
    local unit bag
    local item loot
    local integer playerid
    local integer highest1 = 0   ///This is the current highest roll for item 1///
    local integer highest2 = 0
    local integer highest3 = 0
    local integer highest4 = 0
    local integer highest6 = 0
    local group winners = CreateGroup()
    
    loop
        set u = FirstOfGroup(players)
        exitwhen u == null
        set playerid = GetPlayerId(GetOwningPlayer(u))
        ///Item1///
        if FirstRollItem[playerid] == Item1[id] and highest1 < FirstRoll[playerid] then
            set highest1 = FirstRoll[playerid]
            set ItemWinner1[id] = u
        elseif SecondRollItem[playerid] == Item1[id] and highest1 < SecondRoll[playerid] then
            set highest1 = SecondRoll[playerid]
            set ItemWinner1[id] = u
        elseif ThirdRollItem[playerid] == Item1[id] and highest1 < ThirdRoll[playerid] then
            set highest1 = SecondRoll[playerid]
            set ItemWinner1[id] = u
        endif
        ///Item2///
        if FirstRollItem[playerid] == Item2[id] and highest2 < FirstRoll[playerid] then
            set highest2 = FirstRoll[playerid]
            set ItemWinner2[id] = u
        elseif SecondRollItem[playerid] == Item2[id] and highest2 < SecondRoll[playerid] then
            set highest2 = SecondRoll[playerid]
            set ItemWinner2[id] = u
        elseif ThirdRollItem[playerid] == Item2[id] and highest2 < ThirdRoll[playerid] then
            set highest2 = SecondRoll[playerid]
            set ItemWinner2[id] = u
        endif
        ///Item3///
        if FirstRollItem[playerid] == Item3[id] and highest3 < FirstRoll[playerid] then
            set highest3 = FirstRoll[playerid]
            set ItemWinner3[id] = u
        elseif SecondRollItem[playerid] == Item3[id] and highest3 < SecondRoll[playerid] then
            set highest3 = SecondRoll[playerid]
            set ItemWinner3[id] = u
        elseif ThirdRollItem[playerid] == Item3[id] and highest3 < ThirdRoll[playerid] then
            set highest3 = SecondRoll[playerid]
            set ItemWinner3[id] = u
        endif
        ///Item4///
        if FirstRollItem[playerid] == Item4[id] and highest4 < FirstRoll[playerid] then
            set highest4 = FirstRoll[playerid]
            set ItemWinner4[id] = u
        elseif SecondRollItem[playerid] == Item4[id] and highest4 < SecondRoll[playerid] then
            set highest4 = SecondRoll[playerid]
            set ItemWinner4[id] = u
        elseif ThirdRollItem[playerid] == Item4[id] and highest4 < ThirdRoll[playerid] then
            set highest4 = SecondRoll[playerid]
            set ItemWinner4[id] = u
        endif
        ///Item5///
        if FirstRollItem[playerid] == Item5[id] and highest5 < FirstRoll[playerid] then
            set highest5 = FirstRoll[playerid]
            set ItemWinner5[id] = u
        elseif SecondRollItem[playerid] == Item5[id] and highest5 < SecondRoll[playerid] then
            set highest5 = SecondRoll[playerid]
            set ItemWinner5[id] = u
        elseif ThirdRollItem[playerid] == Item5[id] and highest5 < ThirdRoll[playerid] then
            set highest5 = SecondRoll[playerid]
            set ItemWinner5[id] = u
        endif
        ///Item6///
        if FirstRollItem[playerid] == Item6[id] and highest6 < FirstRoll[playerid] then
            set highest6 = FirstRoll[playerid]
            set ItemWinner6[id] = u
        elseif SecondRollItem[playerid] == Item6[id] and highest6 < SecondRoll[playerid] then
            set highest6 = SecondRoll[playerid]
            set ItemWinner6[id] = u
        elseif ThirdRollItem[playerid] == Item6[id] and highest6 < ThirdRoll[playerid] then
            set highest6 = SecondRoll[playerid]
            set ItemWinner6[id] = u
        endif
        call GroupRemoveUnit(players, u)        
    endloop
    
    call GroupAddUnit(winners,ItemWinner1[id])
    call GroupAddUnit(winners,ItemWinner2[id])
    call GroupAddUnit(winners,ItemWinner3[id])
    call GroupAddUnit(winners,ItemWinner4[id])
    call GroupAddUnit(winners,ItemWinner5[id])
    call GroupAddUnit(winners,ItemWinner6[id])
    
    loop
        set u = FirstOfGroup(winners)
        exitwhen u == null
    
        set bag = CreateUnit(GetOwningPlayer(u),'nBAG',GetUnitX(u),GetUnitY(u),GetUnitFacing(u))
        call UnitApplyTimedLife(bag, 'BTLF', 60.)
        if GetOwningPlayer(bag) == GetOwningPlayer(ItemWinner1[id]) then
            set loot = CreateItem(Item1[id],GetUnitX(bag),GetUnitY(bag))
            call UnitAddItem(bag, loot)
        endif
        if GetOwningPlayer(bag) == GetOwningPlayer(ItemWinner2[id]) then
            set loot = CreateItem(Item2[id],GetUnitX(bag),GetUnitY(bag))
            call UnitAddItem(bag, loot)
        endif
        if GetOwningPlayer(bag) == GetOwningPlayer(ItemWinner3[id]) then
            set loot = CreateItem(Item3[id],GetUnitX(bag),GetUnitY(bag))
            call UnitAddItem(bag, loot)
        endif
        if GetOwningPlayer(bag) == GetOwningPlayer(ItemWinner4[id]) then
            set loot = CreateItem(Item4[id],GetUnitX(bag),GetUnitY(bag))
            call UnitAddItem(bag, loot)
        endif
        if GetOwningPlayer(bag) == GetOwningPlayer(ItemWinner5[id]) then
            set loot = CreateItem(Item5[id],GetUnitX(bag),GetUnitY(bag))
            call UnitAddItem(bag, loot)
        endif
        if GetOwningPlayer(bag) == GetOwningPlayer(ItemWinner6[id]) then
            set loot = CreateItem(Item6[id],GetUnitX(bag),GetUnitY(bag))
            call UnitAddItem(bag, loot)
        endif
        call GroupRemoveUnit(winners, u)
    endloop
    
    
    ///This is the point I'm currently stuck a littlebit.
    ///I want the loot to be distributed here.
    ///So I want this function to check which players won loot by checking their rolls
    ///After that I want this function to create an item of that itemid for those players then
endfunction

private function CreateChests takes nothing returns nothing
    local real x = GetUnitX(boss)
    local real y = GetUnitY(boss)
    local real face = GetUnitFacing(boss)
    local player p = GetOwningPlayer(u)
    local unit chest
    local item reward
    
    set chest = CreateUnit(GetOwningPlayer(GetEnumUnit()), 'n00H',x,y,face)
    call UnitApplyTimedLife(chest, 'BTLF', 20.)
        
        if item1 > 0 then
            set reward = CreateItem(item1, x, y)
            call UnitAddItem(chest, reward)
        endif
        if item2 > 0 then
            set reward = CreateItem(item2, x, y)
            call UnitAddItem(chest, reward)
        endif
        if item3 > 0 then
            set reward = CreateItem(item3, x, y)
            call UnitAddItem(chest, reward)
        endif
        if item4 > 0 then
            set reward = CreateItem(item4, x, y)
            call UnitAddItem(chest, reward)
        endif
        if item5 > 0 then
            set reward = CreateItem(item5, x, y)
            call UnitAddItem(chest, reward)
        endif
        if item6 > 0 then
            set reward = CreateItem(item6, x, y)
            call UnitAddItem(chest, reward)
        endif
endfunction

///unit boss = killed boss
///group players = Hero's that killed the boss together
///integer item1-6 means the item id's. A boss can drop up to a maximum of 6 items.
function CreateBossLoot takes unit boss, group players, integer item1, integer item2, integer item3, integer item4, integer item5, integer item6 returns nothing
    local integer id = GetPlayerId(GetOwningPlayer(FirstOfGroup(players)))

    if item1 != null then
        set Item1[id] = item1
    endif 
    if item2 != null then
        set Item2[id] = item2
    endif
    if item3 != null then
        set Item3[id] = item3
    endif 
    if item4 != null then
        set Item4[id] = item4
    endif
    if item5 != null then
        set Item5[id] = item5
    endif 
    if item6 != null then
        set Item6[id] = item6
    endif
    

    call ForGroup(players, function CreateChests)
        
    call TimerStart(TreasureChestDuration[id],20.,false,function LootDistribution)
    ///Its impossible for a player to defeat 2 bosses within 20 seconds of eachother. But it is possible that 2 bosses
    ///die within 20 seconds of eachother from multiple players at different zones in the map.
    ///Thats why I used the array for TreasureChestDuration. Now it starts the timer for a player that killed the boss.     
endfunction

private function itemPickUp takes nothing returns nothing
    local integer i = GetPlayerId(GetOwningPlayer(GetManipulatingUnit()))
    local unit u
    local string name = GetPlayerName(Player(i))
    local integer chance
    local string bonusstring
    local string laststring
    
    ///Rolling
    set chance = GetRandomInt(1,100)
    if RollBonus[i] == 40 then
        set FirstRoll[i] = chance + RollBonus[i]
        set FirstRollItem[i] = GetItemTypeId(GetManipulatedItem())
        set bonusstring = " |cff00ff00(+40)|r for "
        set laststring = " on his |cff00ff00first|r roll!"
    elseif RollBonus[i] == 20 then
        set SecondRoll[i] = chance + RollBonus[i]
        set SecondRollItem[i] = GetItemTypeId(GetManipulatedItem())
        set bonusstring = " |cffffde08(+20)|r for "
        set laststring = " on his |cffffde08second|r roll!"
    elseif RollBonus[i] == 0 then
        set ThirdRoll[i] = chance + RollBonus[i]
        set ThirdRollItem[i] = GetItemTypeId(GetManipulatedItem())
        set bonusstring = " (+0) for "
        set laststring = " on his third roll!"
    endif
    set msg = (name+(" has rolled "+(I2S(chance+RollBonus[i])+((bonusstring)+(GetItemName(GetManipulatedItem()))+(laststring)))))
    
    loop
        exitwhen i > GetPlayers()
        call DisplayTimedTextToPlayer(Player(i),0,0,10,msg)
        set i = i + 1
    endloop
      
endfunction

private function itemPickUpCheck takes nothing returns boolean
    return GetUnitTypeId(GetManipulatingUnit()) == 'n00H'  ///This is the id of the Treasure Chest///
endfunction

private function init takes nothing returns nothing
    local trigger trig = CreateTrigger()
    
    call TriggerRegisterAnyUnitEventBJ(trig,EVENT_PLAYER_UNIT_USE_ITEM)
    call TriggerAddAction(trig,function itemPickUp)
    call TriggerAddCondition(trig,Condition(function itemPickUpCheck))

endfunction
endlibrary
 
Level 19
Joined
Oct 12, 2007
Messages
1,821
i beleive the code needs quite the optimizing

Hehe you think?:p
The code currently SUX if I can be rude to myself.
But I'm working on optimizing it bit by bit. I think what it should done is kinda done already (with a few typo's or something). Now I just need to remove the typo's and bugs and things I did wrong. After that I'm gonna optimize it a bit by doing things that work better then how I did it.:)
 
Status
Not open for further replies.
Top