- Joined
- Jun 26, 2020
- Messages
- 1,928
Maybe some of you know my Bounty Controller but I think left it just for GUI and create an actually system just for people who don't use GUI
How it works:
-Is the same as the GUI version but now "Bounty" is a class.
-Now to register the events you must use the functions:
-To edit the values in the BountyDeadEvent in the vJass version you must use the function
In the lua version:
-To create your own bounty just do:
Is important use the Run method inmediatly because this function destroy that instance and in other case this will leak and there can only exists as many instances at a time as allowed by the limit recursion.
Main differences:
-There are no need to save the values because now the bounties are instances, therefore no need to use BountyHold and BountyRelease.
-There are no need to clear the values, but if you wanna clear an instance just use the
-Not use the player group "WhoSee", instead there is the method "Can See"
-Is more easy to add to your map because this don't use any "udg" variable.
Just copy-paste it in your map
Here are also test maps to see the systems:
How it works:
-Is the same as the GUI version but now "Bounty" is a class.
-Now to register the events you must use the functions:
vJASS:
// To register it all in a single trigger
function RegisterBountyDeadEvent takes code func returns triggeraction
function RegisterBountyEvent takes code func returns triggeraction
// To register it in different triggers
function TriggerRegisterBountyDeadEvent takes trigger t, code func returns triggeraction
function TriggerRegisterBountyEvent takes trigger t, code func returns triggeraction
Lua:
---@param callback fun(bounty: Bounty)
function Bounty.OnDead(callback)
---@param callback fun(bounty: Bounty)
function Bounty.OnRun(callback)
Bounty.GetCurrent
to get the current instance and edit the members (shown below), like this:
vJASS:
local Bounty this = Bounty.GetCurrent()
set this.Amount = -10
set this.Color = "00ff00"
//etc
Lua:
Bounty.OnRun(function (bounty)
bounty.Amount = -10
bounty.Color = "00ff00"
vJASS:
local Bounty new = Bounty.create()
set new.Amount = <What you want>
set new.UnitPos = <What you want> or set new.LocPos = <What you want>
set new.Receiver = <What you want>
call new.CanSee(new.Receiver, true)
//etc
call new.Run()
Main differences:
-There are no need to save the values because now the bounties are instances, therefore no need to use BountyHold and BountyRelease.
-There are no need to clear the values, but if you wanna clear an instance just use the
destroy
and create
methods.-Not use the player group "WhoSee", instead there is the method "Can See"
-Is more easy to add to your map because this don't use any "udg" variable.
vJASS:
integer Amount: The quantity of gold or lumber that you will receive (it can be negative).
string Color: The color of the text (if is not set, the color of the text will have the default values depending of the state).
real Size: The size of the text.
real LifeSpan: The max. lifetime of the text.
real Age: For some reason the x,y position of the texttag respect to the camera depends of its speed and age, so you can edit it.
real Speed: The speed of the text.
real Direction: The direction to the texttag will move.
real FadePoint: How many seconds the text will fade after apear.
string State: What type of bounty the player will receive (only "gold" and "lumber" are valid).
real Height: How many distance the text will be from the floor.
boolean Show: To show the text or not.
boolean ShowNothing: If the Bounty is 0 by default the text is not showed, if you set this to true, the text will be showed even if the bounty is 0.
boolean AllowFriendFire: By default the bounty only will happen if the dying unit is enemy of the killing unit, if you set this to true, the bounty will happen even if they weren't enemies.
string Effect: The effect that will be displayed (In the same place of the text)
boolean ShowEff: The effect will be displayed if this value is true.
boolean Permanent: This allows erase it (care, if this value is true and you don't use the texttag later it can be an object leak)
player Receiver: The player who will receive the bounty.
unit UnitPos: The position of the text and the effect (If is a unit)
location LocPos: The position of the text and the effect (If is a location, this have more priority than UnitPos, and is removed with the destroy method to prevent object leak, and for this reason don't set it to a variable that you gonna use later)
texttag TextTag: The texttag that will be displayed (never edit this value).
real PosX: Only get with the BountyEvent
real PosY: Only get with the BountyEvent
unit KillingUnit: Instead of "GetKillingUnit()"
unit DyingUnit: Instead of "GetDyingUnit()"
vJASS:
static method create takes nothing returns Bounty
//To set the bounty
static method SetBase takes integer id, integer base returns nothing
static method SetDice takes integer id, integer dice returns nothing
static method SetSides takes integer id, integer sides returns nothing
static method Set takes integer id, integer base, integer dice, integer side returns nothing
//To get the bounty
static method GetBase takes integer id returns integer
static method GetDice takes integer id returns integer
static method GetSides takes integer id returns integer
static method Get takes integer id returns integer
//To get the current instance in the BountyEvent and BountyDeadEvent
static method GetCurrent takes nothing returns Bounty
//To change the receiver in one line
method ChangeReceiver takes player newPlayer, boolean removePrevious, boolean addNew returns nothing
//To set the main members in one line and call the run method
method Call takes integer bounty, unit pos, player myplayer, boolean addplayer, boolean perm returns texttag
//To make the player can see the text
method CanSee takes player p, boolean flag returns nothing
//If the player can see the text
method Seeing takes player p returns boolean
//To run the bounty
method Run takes nothing returns texttag
method destroy takes nothing returns nothing
Just to the vJass version:
Just to the Lua version:
vJASS:
//To register the actions in one trigger
function RegisterBountyDeadEvent takes code func returns triggeraction
function RegisterBountyEvent takes code func returns triggeraction
//To get the main trigger that runs the actions set in the previous functions
function GetNativeBountyDeadTrigger takes nothing returns trigger
function GetNativeBountyTrigger takes nothing returns trigger
//To register the actions in differents triggers
function TriggerRegisterBountyDeadEvent takes trigger t, code func returns triggeraction
function TriggerRegisterBountyEvent takes trigger t, code func returns triggeraction
Lua:
---@param callback fun(bounty: Bounty)
---@returns function remove_func
function Bounty.OnDead(callback)
---@param callback fun(bounty: Bounty)
---@returns function remove_func
function Bounty.OnRun(callback)
Just copy-paste it in your map
vJASS:
//The pure vJass version of the Bounty Controller
//GUI version: https://www.hiveworkshop.com/threads/gui-bounty-controller.332114/
library BountyController requires optional Table
globals
trigger Bounty_Controller
/*private*/ player LocalPlayer
//This constants can be edited (obviously only valid values)
private constant string DEF_COLOR_GOLD = "ffcc00"
private constant string DEF_COLOR_LUMBER = "32cd32"
private constant integer DEF_SIZE = 10
private constant real DEF_LIFE_SPAN = 3.50
private constant real DEF_AGE = 0.00
private constant real DEF_SPEED = 64
private constant real DEF_DIRECTION = 90
private constant real DEF_FADE_POINT = 2.50
private constant string DEF_STATE = "gold"
private constant real DEF_HEIGHT = 0
private constant boolean DEF_SHOW = true
private constant boolean DEF_SHOW_NOTHING = false
private constant boolean DEF_ALLOW_FRIEND_FIRE = false
private constant string DEF_EFFECT = "UI\\Feedback\\GoldCredit\\GoldCredit.mdl"
private constant boolean DEF_SHOW_EFFECT = true
private constant boolean DEF_PERMANENT = false
private constant integer LIMIT_RECURSION = 16 //If a loop caused by recursion is doing in porpouse you can edit the tolerance of how many calls can do
private real Event = 0.00
private real DeadEvent = 0.00
private trigger t1 = CreateTrigger()
private trigger t2 = CreateTrigger()
private boolean array canSee
endglobals
struct Bounty extends array
integer Amount
string Color
real Size
real LifeSpan
real Age
real Speed
real Direction
real FadePoint
string State
real Height
boolean Show
boolean ShowNothing
boolean AllowFriendFire
string Effect
boolean ShowEff
boolean Permanent
player Receiver
unit UnitPos
location LocPos
texttag TextTag
real PosX
real PosY
unit KillingUnit
unit DyingUnit
private static thistype current = 0
static if LIBRARY_Table then
private static Table Bounties0
private static Table Bounties1
private static Table Bounties2
else
private static hashtable Bounties = InitHashtable()
endif
private static integer Recursion = 0
//Since the system must start and end "instantly", I think there is no problem with this methods
private static method allocate takes nothing returns thistype
set Recursion = Recursion + 1
return Recursion
endmethod
private static method deallocate takes nothing returns nothing
set Recursion = Recursion - 1
endmethod
method destroy takes nothing returns nothing
local integer i = 0
loop
exitwhen i > PLAYER_NEUTRAL_AGGRESSIVE
set canSee[this + i * LIMIT_RECURSION] = false
set i = i + 1
endloop
if LocPos != null then
call RemoveLocation(LocPos)
set LocPos = null
endif
set Color = null
set Receiver = null
set UnitPos = null
call deallocate()
endmethod
method CanSee takes player p, boolean flag returns nothing
set canSee[this + GetPlayerId(p) * LIMIT_RECURSION] = flag
endmethod
method Seeing takes player p returns boolean
return canSee[this + GetPlayerId(p) * LIMIT_RECURSION]
endmethod
//The functions to set the bounty stats
static method SetBase takes integer id, integer base returns nothing
static if LIBRARY_Table then
set Bounties0.integer[id] = base
else
call SaveInteger(Bounties, 0, id, base)
endif
endmethod
static method SetDice takes integer id, integer dice returns nothing
static if LIBRARY_Table then
set Bounties1.integer[id] = dice
else
call SaveInteger(Bounties, 1, id, dice)
endif
endmethod
static method SetSides takes integer id, integer sides returns nothing
static if LIBRARY_Table then
set Bounties2.integer[id] = sides
else
call SaveInteger(Bounties, 2, id, sides)
endif
endmethod
static method Set takes integer id, integer base, integer dice, integer side returns nothing
call SetBase(id, base)
call SetDice(id, dice)
call SetSides(id, side)
endmethod
//The static methods to get the bounty stats (that you set before)
static method GetBase takes integer id returns integer
static if LIBRARY_Table then
return Bounties0.integer[id]
else
return LoadInteger(Bounties, 0, id)
endif
endmethod
static method GetDice takes integer id returns integer
static if LIBRARY_Table then
return Bounties1.integer[id]
else
return LoadInteger(Bounties, 1, id)
endif
endmethod
static method GetSides takes integer id returns integer
static if LIBRARY_Table then
return Bounties2.integer[id]
else
return LoadInteger(Bounties, 2, id)
endif
endmethod
static method Get takes integer id returns integer
return GetBase(id)+GetRandomInt(0, GetDice(id) * GetSides(id))
endmethod
//This function is runned at the map initialization, if you wanna use it to set your bounties, you can do it
static method SetData takes nothing returns nothing
local integer i = 0
/*Peasant*/ call Set('hpea', 15, 5, 3)
loop
exitwhen i > PLAYER_NEUTRAL_AGGRESSIVE
call SetPlayerState(Player(i), PLAYER_STATE_GIVES_BOUNTY, 0)
set i = i + 1
endloop
set i = LIMIT_RECURSION * PLAYER_NEUTRAL_AGGRESSIVE
loop
exitwhen i == 0
set canSee[i] = false
set i = i - 1
endloop
endmethod
static method GetCurrent takes nothing returns thistype
return current
endmethod
private static method Sign takes integer i returns string
if i < 0 then
return ""
endif
return "+"
endmethod
method Run takes nothing returns texttag
local playerstate what
local texttag tt
if Recursion > LIMIT_RECURSION then //If there is recursion that don't stop soon, the system stops automatically
call DisplayTimedTextToPlayer(LocalPlayer, 0.0, 0.0, 60.0, "There is a recursion with the Bounty system, check if you are not creating a infinite loop.")
call this.destroy()
return null
endif
if State == "gold" then
set what = PLAYER_STATE_RESOURCE_GOLD
elseif State == "lumber" then
set what = PLAYER_STATE_RESOURCE_LUMBER
else
call this.destroy()
return null //If the state is not valid, the process stop
endif
if Amount == 0 and not ShowNothing then
set Show = false
set ShowEff = false
endif
call AdjustPlayerStateSimpleBJ(Receiver, what, Amount)
if Color == null then
if State == "gold" then
set Color = DEF_COLOR_GOLD
elseif State == "lumber" then
set Color = DEF_COLOR_LUMBER
endif
endif
if LocPos!=null then
set PosX=GetLocationX(LocPos)
set PosY=GetLocationY(LocPos)
elseif UnitPos!=null then
set PosX=GetUnitX(UnitPos)
set PosY=GetUnitY(UnitPos)
else
set Show=false
set ShowEff=false //If there is no position to the text, the text and the effect won't show
endif
if LocPos != null then
set PosX = GetLocationX(LocPos)
set PosY = GetLocationY(LocPos)
elseif UnitPos != null then
set PosX = GetUnitX(UnitPos)
set PosY = GetUnitY(UnitPos)
else
set Show = false
set ShowEff = false //If there is no position to the text, the text and the effect won't show
endif
set TextTag = CreateTextTag()
call SetTextTagPermanent(TextTag, Permanent)
call SetTextTagText(TextTag, "|cff" + Color + Sign(Amount) + I2S(Amount) + "|r", TextTagSize2Height(Size))
call SetTextTagVisibility(TextTag, Seeing(LocalPlayer) and Show)
call SetTextTagPos(TextTag, PosX, PosY, Height)
call SetTextTagFadepoint(TextTag, FadePoint)
call SetTextTagLifespan(TextTag, LifeSpan)
call SetTextTagVelocityBJ(TextTag, Speed, Direction)
call SetTextTagAge(TextTag, Age)
if ShowEff then
call DestroyEffect(AddSpecialEffect(Effect, PosX, PosY))
endif
set tt = TextTag
set current = this
set Event = 0.00
set Event = 1.00
set current = this
call this.destroy()
return tt
endmethod
method Call takes integer bounty, unit pos, player myplayer, boolean addplayer, boolean perm returns texttag
set Amount = bounty
set UnitPos = pos
set Receiver = myplayer
call CanSee(Receiver, addplayer)
set Permanent = perm
return Run()
endmethod
method ChangeReceiver takes player newPlayer, boolean removePrevious, boolean addNew returns nothing
call CanSee(Receiver, not removePrevious)
set Receiver = newPlayer
call CanSee(Receiver, addNew)
endmethod
static method create takes nothing returns thistype
local thistype this = thistype.allocate()
set .Amount = 0
set .Size = DEF_SIZE
set .LifeSpan = DEF_LIFE_SPAN
set .Age = DEF_AGE
set .Speed = DEF_SPEED
set .Direction = DEF_DIRECTION
set .FadePoint = DEF_FADE_POINT
set .State = DEF_STATE
set .Height = DEF_HEIGHT
set .Show = DEF_SHOW
set .ShowNothing = DEF_SHOW_NOTHING
set .Effect = DEF_EFFECT
set .ShowEff = DEF_SHOW_EFFECT
set .Permanent = DEF_PERMANENT
set .PosX = 0.00
set .PosY = 0.00
return this
endmethod
private static method UnitBounty takes nothing returns nothing
local thistype this = thistype.create()
set .KillingUnit = GetKillingUnit()
set .DyingUnit = GetDyingUnit()
set .Amount = Get(GetUnitTypeId(.DyingUnit))
set .Receiver=GetOwningPlayer(.KillingUnit)
call .CanSee(.Receiver,true)
set .UnitPos = .DyingUnit
set current = this
set DeadEvent=0.00
set DeadEvent=1.00
set current = this
if IsUnitEnemy(.DyingUnit, .Receiver) or .AllowFriendFire then
call .Run()
else
call .destroy()
endif
endmethod
private static method UnitBountyCheck takes nothing returns boolean
return GetKillingUnit() != null //If there is not killing unit then the process stop
endmethod
private static method onInit takes nothing returns nothing
//The trigger that runs when a unit dies
set Bounty_Controller=CreateTrigger()
call TriggerRegisterAnyUnitEventBJ(Bounty_Controller, EVENT_PLAYER_UNIT_DEATH)
call TriggerAddCondition(Bounty_Controller, Condition(function thistype.UnitBountyCheck))
call TriggerAddAction(Bounty_Controller, function thistype.UnitBounty)
//Last details
call TriggerRegisterVariableEvent(t1, SCOPE_PRIVATE + "DeadEvent", EQUAL, 1.00)
call TriggerRegisterVariableEvent(t2, SCOPE_PRIVATE + "Event", EQUAL, 1.00)
static if LIBRARY_Table then
set Bounties0 = Table.create()
set Bounties1 = Table.create()
set Bounties2 = Table.create()
endif
set LocalPlayer=GetLocalPlayer()
call SetData()
endmethod
endstruct
function RegisterBountyDeadEvent takes code func returns triggeraction
return TriggerAddAction(t1, func)
endfunction
function TriggerRegisterBountyDeadEvent takes trigger t, code func returns triggeraction
call TriggerRegisterVariableEvent(t, SCOPE_PRIVATE + "DeadEvent", EQUAL, 1.00)
return TriggerAddAction(t, func)
endfunction
function GetNativeBountyDeadTrigger takes nothing returns trigger
return t1
endfunction
function RegisterBountyEvent takes code func returns triggeraction
return TriggerAddAction(t2, func)
endfunction
function TriggerRegisterBountyEvent takes trigger t, code func returns triggeraction
call TriggerRegisterVariableEvent(t, SCOPE_PRIVATE + "Event", EQUAL, 1.00)
return TriggerAddAction(t, func)
endfunction
function GetNativeBountyTrigger takes nothing returns trigger
return t2
endfunction
endlibrary
Lua:
-- The pure Lua version of the Bounty Controller
-- GUI version: https://www.hiveworkshop.com/threads/gui-bounty-controller.332114/
OnInit("BountyController", function() -- https://www.hiveworkshop.com/threads/global-initialization.317099/
Require "EventListener" -- https://www.hiveworkshop.com/threads/event-listener.323354/
-- These can be edited (obviously only valid values)
local DEF_COLOR_GOLD = "ffcc00"
local DEF_COLOR_LUMBER = "32cd32"
local DEF_SIZE = 10
local DEF_LIFE_SPAN = 3.50
local DEF_AGE = 0.00
local DEF_SPEED = 64
local DEF_DIRECTION = 90
local DEF_FADE_POINT = 2.50
local DEF_STATE = "gold"
local DEF_HEIGHT = 0
local DEF_SHOW = true
local DEF_SHOW_NOTHING = false
local DEF_ALLOW_FRIEND_FIRE = false
local DEF_EFFECT = "UI\\Feedback\\GoldCredit\\GoldCredit.mdl"
local DEF_SHOW_EFFECT = true
local DEF_PERMANENT = false
-- This function is run at the start of the game, if you wanna use it to your bounties, you can do it
local function Config()
--[[Peasant]] Bounty.Set(FourCC('hpea'), 15, 5, 3)
for i = 0, PLAYER_NEUTRAL_AGGRESSIVE do
SetPlayerState(Player(i), PLAYER_STATE_GIVES_BOUNTY, 0)
end
end
---@class Bounty
---@field Amount integer
---@field Color string
---@field Size number
---@field LifeSpan number
---@field Age number
---@field Speed number
---@field Direction number
---@field FadePoint number
---@field State string
---@field Height number
---@field Show boolean
---@field ShowNothing boolean
---@field AllowFriendFire boolean
---@field Effect string
---@field ShowEff boolean
---@field Permanent boolean
---@field Receiver player
---@field UnitPos unit
---@field LocPos location
---@field TextTag texttag
---@field PosX number
---@field PosY number
---@field KillingUnit unit
---@field DyingUnit unit
Bounty = {
base = __jarray(0),
dice = __jarray(0),
sides = __jarray(0)
}
Bounty.__index = Bounty
---@param value any
---@return boolean
function IsBounty(value)
return getmetatable(value) == Bounty
end
-- The order it returns (if there is no error) is: number, Bounty
local function ValidValues(v1, v2)
if type(v1) == "number" and IsBounty(v2) then
return v1, v2
elseif IsBounty(v1) and type(v2) == "number" then
return v2, v1
else
error("Wrong operators", 3)
end
end
-- Metamethods
function Bounty.__add(v1, v2)
local num, bounty = ValidValues(v1, v2)
local new = Bounty.Copy(bounty)
new.Amount = new.Amount + num
return new
end
function Bounty.__sub(v1, v2)
local num, bounty = ValidValues(v1, v2)
local new = Bounty.Copy(bounty)
new.Amount = new.Amount - num
return new
end
function Bounty.__mul (v1, v2)
local num, bounty = ValidValues(v1, v2)
local new = Bounty.Copy(bounty)
new.Amount = new.Amount * num
return new
end
function Bounty.__div(v1, v2)
local num, bounty = ValidValues(v1, v2)
local new = Bounty.Copy(bounty)
new.Amount = new.Amount / num
return new
end
function Bounty.__pow(v1, v2)
if not (type(v2) == "number" and IsBounty(v1)) then
error("Wrong operators", 2)
end
local new = Bounty.Copy(v1)
new.Amount = new.Amount ^ v2
return new
end
Bounty.__name = "Bounty"
function Bounty.__tostring(t)
return "Bounty: |cff" .. t.Color .. Bounty.Sign(t.Bounty) .. t.Bounty .. "|r"
end
-- Events
local deadEvent = EventListener.create()
local runEvent = EventListener.create()
---The callback runs when a unit kills another
---@param cb fun(bounty: Bounty)
function Bounty.OnDead(cb)
deadEvent:register(cb)
end
---The callback runs when a bounty is runned
---@param cb fun(bounty: Bounty)
function Bounty.OnRun(cb)
runEvent:register(cb)
end
-- Functions
function Bounty:destroy()
if self.LocPos then
RemoveLocation(self.LocPos)
end
self._canSee = nil
end
---Sets if the player can see the bounty
---@param p player
---@param flag boolean
function Bounty:CanSee(p, flag)
self._canSee[p] = flag
end
---Returns if the player can see the bounty
---@param p player
---@return boolean
function Bounty:Seeing(p)
return self._canSee[p]
end
---Runs the created bounty
---@return texttag
function Bounty:Run()
local what
if self.State == "gold" then
what = PLAYER_STATE_RESOURCE_GOLD
elseif self.State == "lumber" then
what = PLAYER_STATE_RESOURCE_LUMBER
else
self:destroy()
error("Invalid state: " .. self.State) --If the state is not valid, the process stops
end
if self.Amount == 0 and not self.ShowNothing then
self.Show = false
self.ShowEff = false
end
AdjustPlayerStateSimpleBJ(self.Receiver, what, self.Amount)
if not self.Color then
if self.State == "gold" then
self.Color = DEF_COLOR_GOLD
elseif self.State == "lumber" then
self.Color = DEF_COLOR_LUMBER
end
end
if self.LocPos then
self.PosX = GetLocationX(self.LocPos)
self.PosY = GetLocationY(self.LocPos)
elseif self.UnitPos then
self.PosX = GetUnitX(self.UnitPos)
self.PosY = GetUnitY(self.UnitPos)
else
self.Show = false
self.ShowEff = false --If there is no position to the text, the text and the effect won't show
end
self.TextTag = CreateTextTag()
SetTextTagPermanent(self.TextTag, self.Permanent)
SetTextTagText(self.TextTag, "|cff" .. self.Color .. Bounty.Sign(self.Amount) .. I2S(self.Amount) .. "|r", TextTagSize2Height(self.Size))
SetTextTagVisibility(self.TextTag, self:Seeing(GetLocalPlayer()) and self.Show)
SetTextTagPos(self.TextTag, self.PosX, self.PosY, self.Height)
SetTextTagFadepoint(self.TextTag, self.FadePoint)
SetTextTagLifespan(self.TextTag, self.LifeSpan)
SetTextTagVelocityBJ(self.TextTag, self.Speed, self.Direction)
SetTextTagAge(self.TextTag, self.Age)
if self.ShowEff then
DestroyEffect(AddSpecialEffect(self.Effect, self.PosX, self.PosY))
end
what = self.TextTag
runEvent:run(self)
self:destroy()
return what
end
---Creates and runs a bounty
---@param bounty integer
---@param pos unit
---@param myplayer player
---@param addplayer boolean
---@param perm boolean
---@return texttag
function Bounty:Call(bounty, pos, myplayer, addplayer, perm)
self.Amount = bounty
self.UnitPos = pos
self.Receiver = myplayer
self:CanSee(myplayer, addplayer)
self.Permanent = perm
return self:Run()
end
---Change the player who receive the bounty.
---Consider that only doing this won't affect if they can see the bounty
---so you can also modify that
---@param newPlayer player
---@param removePrevious boolean
---@param addNew boolean
function Bounty:ChangeReceiver(newPlayer, removePrevious, addNew)
self:CanSee(self.Receiver, not removePrevious)
self.Receiver = newPlayer
self:CanSee(newPlayer, addNew)
end
---Defines the bounty of a unit-type
---@param id integer
---@param base integer
---@param dice integer
---@param sides integer
function Bounty.Set(id, base, dice, sides)
Bounty.base[id] = base
Bounty.dice[id] = dice
Bounty.sides[id] = sides
end
---Returns a random bounty that the unit-type should give
---@param id integer
---@return integer
function Bounty.Get(id)
return Bounty.base[id] + math.random(0, Bounty.dice[id] * Bounty.sides[id])
end
---Returns '+' if the value is positive or an empty string if is negative
---@param i number
---@return string
function Bounty.Sign(i)
return i < 0 and "" or "+"
end
---@param bounty Bounty
---@return Bounty
function Bounty.Copy(bounty)
if IsBounty(bounty) then
local new = setmetatable({}, Bounty)
for k, v in pairs(bounty) do
new[k] = v
end
return new
else
error("Wrong argument, expected Bounty", 2)
end
end
---@return Bounty
function Bounty.create()
return setmetatable({
Amount = 0,
Size = DEF_SIZE,
LifeSpan = DEF_LIFE_SPAN,
Age = DEF_AGE,
Speed = DEF_SPEED,
Direction = DEF_DIRECTION,
FadePoint = DEF_FADE_POINT,
State = DEF_STATE,
Height = DEF_HEIGHT,
Show = DEF_SHOW,
ShowNothing = DEF_SHOW_NOTHING,
Effect = DEF_EFFECT,
ShowEff = DEF_SHOW_EFFECT,
Permanent = DEF_PERMANENT,
AllowFriendFire = DEF_ALLOW_FRIEND_FIRE,
PosX = 0.00,
PosY = 0.00,
_canSee = {}
}, Bounty)
end
---Enables the bounty controller
function Bounty:Enable()
EnableTrigger(self.trig)
end
---Disables the bounty controller
function Bounty:Disable()
DisableTrigger(self.trig)
end
--The trigger that runs when a unit dies
Bounty.trig = CreateTrigger()
TriggerRegisterAnyUnitEventBJ(Bounty.trig, EVENT_PLAYER_UNIT_DEATH)
TriggerAddAction(Bounty.trig, function()
local killer = GetKillingUnit()
if killer then -- If there is no killing unit then the process stops
local self = Bounty.create()
self.KillingUnit = killer
self.DyingUnit = GetTriggerUnit()
self.Amount = Bounty.Get(GetUnitTypeId(self.DyingUnit))
self.Receiver = GetOwningPlayer(self.KillingUnit)
self:CanSee(self.Receiver, true)
self.UnitPos = self.DyingUnit
deadEvent:run(self)
if IsUnitEnemy(self.DyingUnit, self.Receiver) or self.AllowFriendFire then
self:Run()
else
self:destroy()
end
end
end)
OnInit.final(Config)
end)
Attachments
Last edited: