• 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 Needed - Advanced Bounty System

Status
Not open for further replies.
Level 30
Joined
Jan 31, 2010
Messages
3,552
First of all, thanks for watching at this thread. What I need is an advanced script that will follow the lines listed down. I need it for my project map, which is about to be released. Credits and reputation will be given, of course.

1. Whenever a unit takes damage (Not Hero, not Neutral), the system should add a "Integer" bounty integer to attacker. The bounty integer does not goes to user gold immediately. When a unit dies, the system is activated, giving gold to all units who attacked it, based on how much damage they dealt to that unit. The unit who delivers a killing blow gets additional gold equal to 25% of full bounty. I need arrays, so that I can easily set-up every unit's gold bounty. Bounty will be randomly assigned between two values (i.e.: between 40 and 50). Also, there should be displays of floating texts in this form: +25

Hoping for a script. Have a nice day!
 
Let me clarify this:
Creep dies - trigger calculates how many units took part in taking it down + checks how much damage each one actually dealt (based on percentage yes? because on damage-value it will suck).

So lets say bounty for BIG BIG Sheep is 300mln.

If I dealt 50% damage - I get 150mln
Maggy dealt 25% - 75mln
Rest was takes by vultures ;S
<just an ironic egzample>
 
http://www.hiveworkshop.com/forums/submissions-414/snippet-bounty-196926/

Create a TableArray of 8191. When a unit attacks another unit, using a Unit Indexer, increase the real damage-

TableArray[attacker][attacked] = TableArray[attacker][attacked] + damage

On attack, check if the attacked unit has a group made for it. If it doesn't, create a group. Add the attacker to the group if the attacker isn't already in the group. To see if the attacker is in the group, compare TableArray[attacker][attacked] to 0. Add the damage after this check.

When the attacked unit does, loop through all units in its group and apply bounty based upon the damage each unit did to the now dead unit. Remove the bounty from the killing unit so that the killing unit doesn't get full bounty + shared bounty.

Clear the group and destroy it. For each enumerated unit, delete TableArray[enumed][dead]

Keep in mind that for an RPG, this system is unfair to healers.
 
Level 30
Joined
Jan 31, 2010
Messages
3,552
@Spinnaker, the concept you wrote is pretty much what I need. Let me do the example:
There is a "Warmonger" creep with 200 hit points, and bounty of 200.
Apheraz does 100 damage.
Spinnaker does 60 damage.
Nestharus does 40 damage, and the killing blow.

Apheraz has done 50% damage of unit's hit points, she gains 100 gold.
Spinnaker has done about 32% damage of unit's hit points, he gains 64 gold.
Nestharus has done about 18% damage of unit's hit points, he gains 32 gold.
Nestharus has done the killing blow, earning a bonus of 25% of total bounty.

@Nestharus, thanks for that, but I don't know a thing to do in Jass.
 
Level 30
Joined
Jan 31, 2010
Messages
3,552
@Spinnaker,
More misunderstanding than I have thought it could be.
The formula is calculated by the percentage of damage dealt, meaning that player that does 64% of a unit's hit points gets 64% of bounty. The only exception is the player that delivers the killing blow, meaning that if she does 36% of damage and the killing blow, she gains bounty equal to 36%, +25% of total bounty for killing blow.

@Garfield1337,
Well, I need to configure bounty, right? It's not the same for all units, and when the bounty starts to process, it will be set to a random amount from X to Y.
I.E.: 2 footmans are attacked by a spell Chain Lightning, and their bounty integers are randomly assigned from 20 to 35. One gets, dunno, 22, and the other 31. Then the bounty is split to damage dealers when they die.
And it is dependable of damage dealt, I just explained it to the Spinnaker.
 
>>>>>>>>>>>>>>>>>>>>>>
EDIT: Advanced Bounty Code:

BountyUnitType[] - Creep unit type
BountyBase[] - Base bounty for unit-type (use the same array index here as for given unit type)
BountyRadnomMin - Provides option for randomise bounty (your wish was -10% here)
BountyRadnomMax - Provides option for randomise bounty (your wish was +10% here)
BountyOnKillingBlow - Bonus bounty factor for owner of killing unit
BountyIndexSize - Enter here the maximum array used while declaring bounty data (It's a must)

Requires Unit Indexer and Damage Engine.

~Added floating text
~Fixed life regeneration issue
~Catchs up all every unit now

Initialization:
~I added a small bounty data example
  • settings
    • Events
      • Time - Elapsed game time is 2.00 seconds
    • Conditions
    • Actions
      • -------- ----------------------------------------------------- --------
      • Set BountyUnitType[0] = Forest Troll
      • Set BountyUnitType[1] = Gnoll
      • Set BountyUnitType[2] = Forest Troll Great Priest
      • Set BountyUnitType[3] = Forest Troll Shadow Priest
      • Set BountyUnitType[4] = Forest Troll Trapper
      • Set BountyUnitType[5] = Forest Troll Berserker
      • -------- ----------------------------------------------------- --------
      • Set BountyBase[0] = 200
      • Set BountyBase[1] = 50
      • Set BountyBase[2] = 1000
      • Set BountyBase[3] = 100
      • Set BountyBase[4] = 150
      • Set BountyBase[5] = 1200
      • -------- ----------------------------------------------------- --------
      • Set BountyIndexSize = 5
      • -------- ----------------------------------------------------- --------
      • Set BountyOnKillingBlow = 1.25
      • Set BountyRandomMax = 1.10
      • Set BountyRandomMin = 0.90
      • -------- ----------------------------------------------------- --------
      • Custom script: set udg_BountyHash = InitHashtable()
      • Custom script: set bj_wantDestroyGroup = true
      • Unit Group - Pick every unit in (Units in (Playable map area) matching ((((Matching unit) is Hero) Equal to False) and (((Matching unit) is alive) Equals to True))) and do (Actions)
        • Loop - Actions
          • Unit Group - Add (Picked unit) to Creeps
          • Custom script: call SaveInteger(udg_BountyHash, GetHandleId(GetEnumUnit()), 0, 0)
          • Set BountyDamageTaken[(Custom value of (Picked unit))] = 0.00
System script:
JASS:
//*************************************************************************
//*
//* Globals required
//*
//*************************************************************************


    //* udg_BountyHash          Hashtable for data storage

    //* All the rest variables are declared by systems used

    

//*************************************************************************
//*
//* Code itself
//*
//*************************************************************************

function GiveBounty takes nothing returns boolean
    local unit u = GetTriggerUnit()
    local unit l
    local integer id
    local integer i
    local integer n = 0
    local real d
    if IsUnitInGroup(u, udg_Creeps) then
        set id = GetHandleId(u)
        set i = LoadInteger(udg_BountyHash, id, 0)
        if i > 0 then
            loop
                exitwhen 0 == i
                loop
                    exitwhen udg_BountyUnitType[n] == GetUnitTypeId(u) or n > udg_BountyIndexSize
                    set n = n + 1
                endloop
                set l = LoadUnitHandle(udg_BountyHash, id, i)
                set d = LoadReal(udg_BountyHash, id, -i) / udg_BountyDamageTaken[GetUnitUserData(u)] * udg_BountyBase[n]
                set d = GetRandomReal(udg_BountyRandomMin * d, udg_BountyRandomMax * d)
                if l == GetKillingUnit() then
                    set d = d * udg_BountyOnKillingBlow
                endif
                call SetPlayerState(GetOwningPlayer(l), PLAYER_STATE_RESOURCE_GOLD, GetPlayerState(GetOwningPlayer(l), PLAYER_STATE_RESOURCE_GOLD) + R2I(d))
                //* Create floating text part
                set bj_lastCreatedTextTag = CreateTextTag()
                call SetTextTagText(bj_lastCreatedTextTag, "+" + I2S(R2I(d)), 0.024)
                call SetTextTagPos(bj_lastCreatedTextTag, GetUnitX(l)-16.0, GetUnitY(l), 0.0)
                call SetTextTagColor(bj_lastCreatedTextTag, 255, 220, 0, 255)
                call SetTextTagVelocity(bj_lastCreatedTextTag, 0., 0.03)
                call SetTextTagPermanent(bj_lastCreatedTextTag, false)
                call SetTextTagVisibility(bj_lastCreatedTextTag, true)
                call SetTextTagLifespan(bj_lastCreatedTextTag, 3.0)
                call SetTextTagFadepoint(bj_lastCreatedTextTag, 2.0)
                set l = null
                set i = i - 1
            endloop
        endif
        call GroupRemoveUnit(udg_Creeps, u)
        call FlushChildHashtable(udg_BountyHash, id)
    endif
    set u = null
    return false
endfunction

function CountBounty takes nothing returns boolean
    local integer id = GetHandleId(udg_DamageEventTarget)
    local integer n = GetUnitUserData(udg_DamageEventTarget)
    local integer i

    if udg_DamageEventAmount > 0.00 and IsUnitInGroup(udg_DamageEventTarget, udg_Creeps) then
        set udg_BountyDamageTaken[n] = udg_BountyDamageTaken[n] + udg_DamageEventAmount
        set i = LoadInteger(udg_BountyHash, id, 0)
        set n = i + 1
        loop
            exitwhen 0 == i
            if LoadUnitHandle(udg_BountyHash, id, i) == udg_DamageEventSource then
                call SaveReal(udg_BountyHash, id, -i, LoadReal(udg_BountyHash, id, -i) + udg_DamageEventAmount)
                return false
            endif
            set i = i - 1
        endloop
        call SaveUnitHandle(udg_BountyHash, id, n, udg_DamageEventSource)
        call SaveReal(udg_BountyHash, id, -n, udg_DamageEventAmount)
        call SaveInteger(udg_BountyHash, id, 0, n)
    endif
    return false
endfunction

function BountyAddUnit takes nothing returns boolean
    if not IsUnitType(udg_UDexUnits[udg_UDex], UNIT_TYPE_HERO) then
        call GroupAddUnit(udg_Creeps, udg_UDexUnits[udg_UDex])
        call SaveInteger(udg_BountyHash, GetHandleId(udg_UDexUnits[udg_UDex]), 0, 0)
        set udg_BountyDamageTaken[udg_UDex] = 0.00
    endif
    return false
endfunction

//***************************************************************************
function InitTrig_CallBounty takes nothing returns nothing
    local trigger t = CreateTrigger()
    call TriggerRegisterVariableEvent(t, "udg_DamageEvent", EQUAL, 1.00)
    call TriggerAddCondition(t, Filter(function CountBounty))
    set t = CreateTrigger()
    call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_DEATH)
    call TriggerAddCondition(t, Filter(function GiveBounty))
    set t = CreateTrigger()
    call TriggerRegisterVariableEvent(t, "udg_UnitIndexEvent", EQUAL, 1.00)
    call TriggerAddCondition(t, Filter(function BountyAddUnit))
    set t = null
endfunction
 

Attachments

  • AdvancedBounty.w3x
    28.5 KB · Views: 47
Last edited:
Level 20
Joined
Jul 6, 2009
Messages
1,885
Whats wrong? ;/
Well...
In GiveBounty, you create a local d and use it, uninitialized, here set d = d * udg_BountyFactor
which results in following functions not getting executed.
I think you forgot to load the damage dealt, but even if you did load it, it wouldn't work well since you're loading damage dealt and not procent of unit's health. You also need to consider regeneration and heals so to calculate correct procent, you need to total damage dealt to unit by divide damage dealt.

Although these things aren't hard to fix.
 
Level 20
Joined
Jul 6, 2009
Messages
1,885
Garfield - it's because I've uploaded old version.
Look script on previous page - it's the one new ver is using. Replaced old map with new one - it looks like I passed your egzam.
EDIT: Regeneration will be added it sec, you got a point here.
One more thing, each unit has a base bounty, so the bounty for each unit is: Base bounty * damage dealt / total damage dealt.

You can, for example, load the base bounty from a hashtable since i guess bounties will be saved for each unit on map init.
 
One more thing, each unit has a base bounty, so the bounty for each unit is: Base bounty * damage dealt / total damage dealt.

You can, for example, load the base bounty from a hashtable since i guess bounties will be saved for each unit on map init.

About formula, I see you haven't seen my scream (in format h3) asking for bounty formula. I've added pseudo-base bounty variable. Untill that guy tell the formula I won't add it.
Counting damage was pie - why hashtables, when I was using unit indexer too? Uploaded map. Renegeration was the issue.
 
Level 20
Joined
Jul 6, 2009
Messages
1,885
About formula, I see you haven't seen my scream (in format h3) asking for bounty formula. I've added pseudo-base bounty variable. Untill that guy tell the formula I won't add it.
Counting damage was pie - why hashtables, when I was using unit indexer too? Uploaded map. Renegeration was the issue.
Trust me, it's the correct formula. It gives bounty compared to what part you took in killing the unit.
 
Level 20
Joined
Jul 6, 2009
Messages
1,885
Base bounty is a value that Apheraz is going to set for each unit, you don't calculate it, you just load it.
Although, Apheraz mentioned something like Base Bounty+/-Random small value.
I'd just add a configurable variable that would be the max bounty change and set base bounty formula to:
LoadBaseBounty (from hash or such) + GetRandomReal(-Variable,Variable).
 
Level 9
Joined
Apr 26, 2011
Messages
403
I don't have time to write a full script, but here is the draft :

JASS:
variable: 
unit_group  // group for unit
unit_array // type=unit, an array with unlimit size
current_index  // tempory variable, for current empty index
max_index  // keep trace of max index used in unit_array
unit_bounty_array // to keep bounty's percentage in decimal number



============================
Trigger: unit is attacked
-- if attacked_unit not in unit_group
----- // add unit to array, with index, change unit's custom value to array's index
----- add attacked_unit to unit_group
----- loop from 1 to max_index, if unit_array[loop_A] is empty, then set current_index = loop_A
----- if current_index > max_index, then set max_index = current_index 
----- set unit_array[current_index] = attacked_unit
----- set custom value of attacked_unit = current_index 
-----// calculate damage/total hp percentage
----- set temp_integer = player number( owner of attacking unit)
----- set temp_real = damage of attacking unit / total hp of attacked unit  // need convert integer to real
----- set temp_index = current_index*10 + temp_integer  //this is index for unit_bounty_array
----- set unit_bounty_array[temp_index] = unit_bounty_array[temp_index] + temp_real // every attack add up

Trigger: unit is dying
-- if dying_unit is in unit_group, then
----- set current_index = custom value of dying_unit 
----- set unit_array[current_index] = null
----- remove dying_unit from unit_group
----- /// calculate bounty
----- set total_bounty  = total bounty for dying unit // I don't know how you assign total bounty
----- loop : for every number from 0 to 9 do
-------- set temp_index = current_index*10 + loop_index
-------- set temp_real = unit_bounty_array[temp_index]
-------- set temp_bounty = I2R(total_bounty) * temp_real
-------- give bounty to player(loop_index)
-------- set unit_bounty_array[temp_index] = 0.0 // clean up bounty array for other creep
-- excute trigger "Trigger - Update Max_index"

Trigger - Update Max_index
--- set temp_index = 1
--- loop : from 1 to max_index
----- if unit_array[loop_A] is NOT empty, then 
-------- set temp_index = loop_A
--- set max_index = temp_index  // this will update max_index of current used index. 

==========

Explain :

unit_array : 
- this array is mainly for index look up 
- the index on unit_array = custom value of this unit
- the index also use for unit_bounty_array

unit_bounty_array:
- to use this, you need index from unit_array (or custom value of  unit).
- it can store information for 10 players (0-9)
for example:
if unit's index = 9, then:
unit_bounty_array[90] = player(0)  // convert percentage to real. eg, 10% = 0.1
unit_bounty_array[91] = player(1)
....
unit_bounty_array[98] = player(8)
 
Status
Not open for further replies.
Top