Laiev
Hey Listen!!
- Reaction score
- 188
Main Attribute Control
5.2
Requirements:
- AIDS
- TimerUtils
JASS:
// ~*=*~ ~*=*~ ~*=*~ ~*=*~ ~*=*~ ~*=*~ ~*=*~ ~*=*~ ~*=*~ ~*=*~ ~*=*~ ~*=*~ ~*=*~ ~*=*~
// ~*=*~ ~*=*~ ~*=*~ ~*=*~ ~*=*~ Main Attribute Control ~*=*~ ~*=*~ ~*=*~ ~*=*~ ~*=*~
// ~*=*~ ~*=*~ ~*=*~ ~*=*~ ~*=*~ ~*=*~ ~*=*~ ~*=*~ ~*=*~ ~*=*~ ~*=*~ ~*=*~ ~*=*~ ~*=*~
//
// MAC v5.2 by Laiev
// ===================================================================================
// ~ About ~
//
// This system is used to get the primary attribute (as Blizzard refers to it), this
// is achieved by databasing every single unittype in the game.
//
// It allow the user to use the Main Attribute of the hero without problems.
// With some function, this system allow you to manipulate the main attribute, you can
// change it when you want and for what you need.
//
// ===================================================================================
// ~ Importing ~
//
// To import this System you'll need:
// - Chaos Ability MAC (Ability used to morph the heroes.)
// - Dummy MAC (Unit used to take damage.)
// - Chaos MAC (Unit used to be morphed.)
//
// Then you'll need to copy the AIDS and TimerUtils if you don't have it yet.
// Copy this Trigger to your map and configure it below to your map.
//
// ===================================================================================
// ~ Pros/Cons ~
// _____________
// Pros
// - Can register id manually.
// - Debug Messages when in debug mode.
// - Automatic register.
// _____________
// Cons
// - Requires an area to do the Automatic Register.
// - Need to wait a little before use functions in the first time of that Id.
//
// ===================================================================================
// ~ Functions ~
/*
function MAC_SetValue takes unit whichUnit, integer newValue returns nothing
*/
// whichUnit = The unit registered in the system
// newValue = The new value to the main attribute of the whichUnit
/*
function MAC_GetValue takes unit whichUnit, boolean bonus returns integer
*/
// whichUnit = The unit registered in the system
// bonus = If include the bonus (green text with the plus)
// return = Return the value of the main attribute
/*
function MAC_GetMainAttribute takes unit whichUnit returns integer
*/
// whichUnit = The unit registered in the system
// return = Return what attribute is (based on Blizzard constants) 0 = Str, 1 = Agi, 2 = Int
/*
function MAC_AddValue takes unit whichUnit, integer howMuch returns nothing
*/
// whichUnit = The unit registered in the system
// howMuch = Amount of main attribute which you want to add
/*
function MAC_ReduceValue takes unit whichUnit, integer howMuch returns nothing
*/
// whichUnit = The unit registered in the system
// howMuch = Amount of main attribute which you want to reduce
/*
function MAC_Registered takes unit unitId returns boolean
*/
// unitId = The id of the unit that you will register to the system
// return = True if registered, false if not registered
/*
function MAC_Register takes integer unitId, integer whichAtt returns boolean
*/
// unitId = The id of the unit that you will register to the system
// whichAtt = The main attribute which you'll register to the system
// ATTRIBUTE_STRENGTH / bj_HEROSTAT_STR
// ATTRIBUTE_AGILITY / bj_HEROSTAT_AGI
// ATTRIBUTE_INTELLIGENCE / bj_HEROSTAT_INT
// return = True if register, false if registered.
/*
function MAC_GetMainAttributeById takes integer unitId returns integer
*/
// unitId = The id of the unit that you will register to the system
// return = Return what attribute is (based on Blizzard constants) 0 = Str, 1 = Agi, 2 = Int
/*
function MAC_DivideValue takes unit whichUnit, integer diviser returns nothing
*/
// whichUnit = The unit registered in the system
// diviser = The diviser, for example:
// Main Attribute = 50
// diviser = 5
// This function will change the Main Attribute to 10.
/*
function MAC_MultiplyValue takes unit whichUnit, integer multiplier returns nothing
*/
// whichUnit = The unit registered in the system
// multiplier = The multiplier, for example:
// Main Attribute = 5
// multiplier = 20
// This function will change the Main Attribute to 100.
/*
function MAC_PercentageValue takes unit whichUnit, real percent returns nothing
*/
// whichUnit = The unit registered in the system
// percent = The percent, for example:
// Main Attribute = 20
// percent = 0.05
// This function will change the Main Attribute to 1.
//
// ------------------
// ~ Direct Struct ~
//
/*
MAC[whichUnit].?
*/
// Change ? to some method:
// - setValue(newValue) -> nothing
// - getValue(bonus) -> integer
// - getMainAttribute() -> integer
// - addValue(howMuch) -> nothing
// - reduceValue(howMuch) -> nothing
// - divideValue(diviser) -> nothing
// - multiplyValue(multiplier) -> nothing
// - percentageValue(percent) -> nothing
//
// ===================================================================================
// ~ Credits ~
//
// Jesus4Lyf
// - AIDS and Hash Function
//
// Vexorian
// - TimerUtils
// ===================================================================================
library MAC requires AIDS, TimerUtils
// Configuration
globals
// Dummy ID to test the damage. Should't got Locust or any invulnerable thing.
private constant integer DUMMY = 039;dMAC039;
// Ability ID of Chaos.
private constant integer CHAOS_ABILITY = 039;AMAC039;
// Chaos Unit ID.
private constant integer CHAOS_UNIT = 039;CMAC039;
// The value here need to be hight enough.
private constant integer TEST_VALUE = 100
// Owner of the units that system will use.
private constant player TEST_OWNER = Player(15)
// The X/Y wheres you'll use to test the damage. This should
private constant real TEST_X = 2500.
private constant real TEST_Y = 2500.
// Don't change those values, it's only for easy access
// You can also use the constants from Blizzard
constant integer ATTRIBUTE_STRENGTH = 0
constant integer ATTRIBUTE_AGILITY = 1
constant integer ATTRIBUTE_INTELLIGENCE = 2
//bj_HEROSTAT_STR = 0
//bj_HEROSTAT_AGI = 1
//bj_HEROSTAT_INT = 2
endglobals
// ------------------------------------------------------------------
// Do not change anything from here unless you know what you're doing.
// ------------------------------------------------------------------
// Globals for the Hash Function.
globals
private constant integer HASH_NEXT = 53
private constant integer MAX_HASH_VALUE = 8191
private integer array HashedInt
endglobals
// Hash Function, don't change it.
private function Hash takes integer i returns integer
local integer hash = i - (i / MAX_HASH_VALUE) * MAX_HASH_VALUE
loop
exitwhen HashedInt[hash] == i
if HashedInt[hash] == 0 then
set HashedInt[hash] = i
return hash
endif
set hash = hash + HASH_NEXT
if hash >= MAX_HASH_VALUE then
set hash = hash-MAX_HASH_VALUE
endif
endloop
return hash
endfunction
// How to save the ID and what Attribute.
private struct MACData extends array
boolean registered
integer attribute
endstruct
// Check if ID is registered.
public function Registered takes integer unitId returns boolean
return MACData[Hash(unitId)].registered
endfunction
// Get the Main Attribute by the ID of the Unit.
public function GetMainAttributeById takes integer unitId returns integer
return MACData[Hash(unitId)].attribute
endfunction
// Register the Unit ID, return false if already registered, else if successfully registered.
public function Register takes integer unitId, integer whichAtt returns boolean
local MACData Mac = MACData[Hash(unitId)]
if Mac.registered then
debug call BJDebugMsg("|cffFF0000MAC:|r Trying to register a unit id more than once.")
return false
endif
set Mac.registered = true
set Mac.attribute = whichAtt
return true
endfunction
// Used to auto register the Main Attribute.
private struct TempData
unit d0
unit d1
unit d2
real r0
real r1
real r2
integer id
endstruct
private function GetAutomatic takes nothing returns nothing
local TempData td = GetTimerData(GetExpiredTimer())
// -----------------------------------
// Check the life of Attacked Dummies.
set td.r0 = GetWidgetLife(td.d0)
set td.r1 = GetWidgetLife(td.d1)
set td.r2 = GetWidgetLife(td.d2)
// -----------------------------------
// ----------------------------------------------
// Some Debugs just to check if things are right.
debug call BJDebugMsg("=========================")
debug call BJDebugMsg("Dummy I: " + R2S(td.r0))
debug call BJDebugMsg("Dummy II: " + R2S(td.r1))
debug call BJDebugMsg("Dummy III: " + R2S(td.r2))
// ----------------------------------------------
// -----------------------------------
// This need to be manually like this.
if td.r0 < td.r1 and td.r0 < td.r2 then
call MAC_Register(td.id, 0) //Strength
debug call BJDebugMsg("Main Attribute: Strength")
call ReleaseTimer(GetExpiredTimer())
call td.destroy()
elseif td.r1 < td.r0 and td.r1 < td.r2 then
call MAC_Register(td.id, 1) //Agility
debug call BJDebugMsg("Main Attribute: Agility")
call ReleaseTimer(GetExpiredTimer())
call td.destroy()
elseif td.r2 < td.r0 and td.r2 < td.r1 then
call MAC_Register(td.id, 2) //Intelligence
debug call BJDebugMsg("Main Attribute: Intelligence")
call ReleaseTimer(GetExpiredTimer())
call td.destroy()
debug else
// Just prevent something wrong.
debug call BJDebugMsg("|cffFF0000MAC:|r Something goes wrong.")
endif
// -----------------------------------
endfunction
private function Automatic takes unit u returns nothing
local unit h0 = CreateUnit(TEST_OWNER, GetUnitTypeId(u), TEST_X, TEST_Y, 0.)
local unit h1 = CreateUnit(TEST_OWNER, GetUnitTypeId(u), TEST_X, TEST_Y, 0.)
local unit h2 = CreateUnit(TEST_OWNER, GetUnitTypeId(u), TEST_X, TEST_Y, 0.)
local timer t = NewTimer()
local TempData td = TempData.create()
set td.id = GetUnitTypeId(u)
set td.d0 = CreateUnit(TEST_OWNER, DUMMY, TEST_X, TEST_Y, 0.)
set td.d1 = CreateUnit(TEST_OWNER, DUMMY, TEST_X, TEST_Y, 0.)
set td.d2 = CreateUnit(TEST_OWNER, DUMMY, TEST_X, TEST_Y, 0.)
// ----------------------------------------------------------------
// Add the Chaos Ability, change the Attribute and Order to Attack.
call UnitAddAbility(h0, CHAOS_ABILITY)
call SetHeroStr(h0, TEST_VALUE, true)
call IssueTargetOrder(h0, "attack", td.d0)
call UnitAddAbility(h1, CHAOS_ABILITY)
call SetHeroAgi(h1, TEST_VALUE, true)
call IssueTargetOrder(h1, "attack", td.d1)
call UnitAddAbility(h2, CHAOS_ABILITY)
call SetHeroInt(h2, TEST_VALUE, true)
call IssueTargetOrder(h2, "attack", td.d2)
// ----------------------------------------------------------------
// -------------------------------
// Set timed life for the dummies.
call UnitApplyTimedLife(h0, 039;BTLF039;, 1.)
call UnitApplyTimedLife(h1, 039;BTLF039;, 1.)
call UnitApplyTimedLife(h2, 039;BTLF039;, 1.)
call UnitApplyTimedLife(td.d0, 039;BTLF039;, 1.)
call UnitApplyTimedLife(td.d1, 039;BTLF039;, 1.)
call UnitApplyTimedLife(td.d2, 039;BTLF039;, 1.)
// -------------------------------
call TimerStart(t, .5, true, function GetAutomatic)
call SetTimerData(t, td)
set t = null
set h0 = null
set h1 = null
set h2 = null
endfunction
// The struct to store and get value.
struct MAC extends array
//! runtextmacro AIDS()
private static method AIDS_filter takes unit u returns boolean
if IsUnitType(u, UNIT_TYPE_HERO) and GetOwningPlayer(u) != TEST_OWNER then // Prevent infinty loop.
if not MAC_Registered(GetUnitTypeId(u)) then // If not registered will auto register.
call Automatic(u)
endif
return true
endif
return false
endmethod
// ---------------------------------------
// Change the value of the Main Attribute.
method setValue takes integer newValue returns nothing
if not MAC_Registered(GetUnitTypeId(.unit)) then
debug call BJDebugMsg("|cffFF0000MAC:|r Trying to define the main attribute of an unregistered unit.")
return
endif
if MAC_GetMainAttributeById(GetUnitTypeId(.unit)) == 0 then
call SetHeroStr(.unit, newValue, true)
elseif MAC_GetMainAttributeById(GetUnitTypeId(.unit)) == 1 then
call SetHeroAgi(.unit, newValue, true)
elseif MAC_GetMainAttributeById(GetUnitTypeId(.unit)) == 2 then
call SetHeroInt(.unit, newValue, true)
debug else
debug call BJDebugMsg("|cffFF0000MAC:|r Wrong value of main attribute, it should be 1, 2 or 3." )
endif
endmethod
// ---------------------------------------
// ---------------------------------------------------------------
// Get the total value (with/without bonus) of the Main Attribute.
method getValue takes boolean bonus returns integer
if not MAC_Registered(GetUnitTypeId(.unit)) then
debug call BJDebugMsg("|cffFF0000MAC:|r Trying to get the main attribute of an unregistered unit.")
return 0 // Return 0 if Unit is not registered or if Main Attribute is registered wrong.
endif
if MAC_GetMainAttributeById(GetUnitTypeId(.unit)) == 0 then
return GetHeroStr(.unit, bonus)
elseif MAC_GetMainAttributeById(GetUnitTypeId(.unit)) == 1 then
return GetHeroAgi(.unit, bonus)
elseif MAC_GetMainAttributeById(GetUnitTypeId(.unit)) == 2 then
return GetHeroInt(.unit, bonus)
debug else
debug call BJDebugMsg("|cffFF0000MAC:|r Wrong value of main attribute, it should be 1, 2 or 3." )
endif
return 0 // Return 0 if Unit is not registered or if Main Attribute is registered wrong.
endmethod
// ---------------------------------------------------------------
// --------------------------------------------------
// Get the Integer of the Main Attribute (Blizzlike).
method getMainAttribute takes nothing returns integer
if not MAC_Registered(GetUnitTypeId(.unit)) then
debug call BJDebugMsg("|cffFF0000MAC:|r Trying to getAttribute the main attribute of an unregistered unit.")
return - 1 // Return -1 because 0, 1 and 2 is used.
endif
return MAC_GetMainAttributeById(GetUnitTypeId(.unit))
endmethod
// --------------------------------------------------
// --------------------------------------------
// Completeness, you can easy use the setValue.
method addValue takes integer howMuch returns nothing
call .setValue(.getValue(false) + howMuch)
endmethod
// --------------------------------------------
// --------------------------------------------
// Completeness, you can easy use the setValue.
method reduceValue takes integer howMuch returns nothing
call .setValue(.getValue(false) - howMuch)
endmethod
// --------------------------------------------
// --------------------------------------------
// Completeness, you can easy use the setValue.
method divideValue takes integer divider returns nothing
call .setValue(.getValue(false) / divider)
endmethod
// --------------------------------------------
// --------------------------------------------
// Completeness, you can easy use the setValue.
method multiplyValue takes integer multiplier returns nothing
call .setValue(.getValue(false) * multiplier)
endmethod
// --------------------------------------------
// --------------------------------------------
// Completeness, you can easy use the setValue.
method percentageValue takes real percent returns nothing
call .setValue(.getValue(false) + R2I(.getValue(false) * percent))
endmethod
// --------------------------------------------
endstruct
// ------------------------------------------------------
// API for people that don't like to use struct directly.
// ------------------------------------------------------
// Get the value of the Main Attribute.
public function GetValue takes unit whichUnit, boolean bonus returns integer
return MAC[whichUnit].getValue(bonus)
endfunction
// Get the Integer of the Main Attribute (Blizzlike).
public function GetMainAttribute takes unit whichUnit returns integer
return MAC[whichUnit].getMainAttribute()
endfunction
// Change the main attribute of Unit to any value.
public function SetValue takes unit whichUnit, integer newValue returns nothing
call MAC[whichUnit].setValue(newValue)
endfunction
// Completeness, you can easy use the SetValue.
public function AddValue takes unit whichUnit, integer howMuch returns nothing
call MAC[whichUnit].addValue(howMuch)
endfunction
// Completeness, you can easy use the SetValue.
public function ReduceValue takes unit whichUnit, integer howMuch returns nothing
call MAC[whichUnit].reduceValue(howMuch)
endfunction
// Completeness, you can easy use the SetValue.
public function DivideValue takes unit whichUnit, integer divider returns nothing
call MAC[whichUnit].divideValue(divider)
endfunction
// Completeness, you can easy use the SetValue.
public function MultiplyValue takes unit whichUnit, integer multiplier returns nothing
call MAC[whichUnit].multiplyValue(multiplier)
endfunction
// Completeness, you can easy use the SetValue.
public function PercentageValue takes unit whichUnit, real percent returns nothing
call MAC[whichUnit].percentageValue(percent)
endfunction
endlibrary
Well, this should be easy to understand and if have some question about the system, see the documents or see the TESH bellow.
JASS:
//
// _____ ___ ___ _ _
// |_ _| __/ __| |_| |
// | | | _|\__ \ _ |
// |_| |___|___/_| |_| Highlighting:
// - MAC by Laiev
//
// What is this?
// ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
// Implementing this allows the TESH syntax highlighter in Jass NewGen
// to highlight the syntax for this system (and autocomplete the functions).
//
// How to import?
// ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
// Copy this into a blank text file, and save it at:
// <Your Jass NewGen folder>\tesh\includes\MAC.j
//
function MAC_SetValue takes unit whichUnit, integer newValue returns nothing
// Set the main attribute of the registered unit to some value
endfunction
function MAC_GetValue takes unit whichUnit, boolean bonus returns integer
// Get the exactly amount of the main attribute of the registered unit
endfunction
function MAC_GetMainAttribute takes unit whichUnit returns integer
// Get the main attribute registered in the system of the registered unit
// - 0 = Str
// - 1 = Agi
// - 2 = Int
endfunction
function MAC_AddValue takes unit whichUnit, integer howMuch returns nothing
// Add the amount of main attribute of the registered unit
endfunction
function MAC_ReduceValue takes unit whichUnit, integer howMuch returns nothing
// Reduce the amount of main attribute of the registered unit
endfunction
function MAC_GetMainAttributeById takes integer unitId returns integer
// Get the main attribute registered in the system of the registered unit by id
// - 0 = Str
// - 1 = Agi
// - 2 = Int
endfunction
function MAC_Registered takes integer unitId returns boolean
// Check if the id of the unit is registered
endfunction
function MAC_Register takes integer unitId, integer whichAtt returns boolean
// Register the id of some unit in the system
endfunction
function MAC_DivideValue takes unit whichUnit, integer divider returns nothing
// Divide the Main Attribute of the unit. It change the Main Attribute.
endfunction
function MAC_MultiplyValue takes unit whichUnit, integer multiplier returns nothing
// Multiply the Main Attribute of the unit. It change the Main Attribute.
endfunction
function MAC_PercentageValue takes unit whichUnit, real percent returns nothing
// Percentage the Main Attribute of the unit. It change the Main Attribute.
endfunction
Credits:
- Jesus4Lyf - AIDS and Hash function
- Weep and Sevion - How to auto do it.
- Vexorian - TimerUtils
- Errors? Fails? Bugs? Suggestions? It will help me to improve it.
Changelog:
- 1.0 - Release.
- 1.1 - Now using the optional function in the static if.
- 2.0 - Rewrited all the system with AIDS Struct, removed the use of group and reduced much the use of globals.
- 3.0 - Changed the way to register, fixed some mistake and rewrited the system a bit.
- 4.0 - Changed static variable, added new function to get main attribute by id.
- 4.1 - Changed the interface language of most functions.
- 5.0 - Added way to auto-register. Added some configurations. Added three new function (completeness). DivideValue, MultiplyValue and PercentageValue.
- 5.1 - Removed unused constant. Changed KT2 to TimerUtils. Added fast setting of ATTRIBUTE_(STRENGTH/AGILITY/INTELLIGENCE).
- 5.2 - Fixed wrong informations at Docs and Added requirement TimerUtils.
Press ESC to add 3 to the Main Attribute of a new Hero, notice that the first time it don't add and will return debug message.
Write '-get' to show the value of the Main Attribute of Last Created Unit.
Write '-get' to show the value of the Main Attribute of Last Created Unit.