//Talent 1.24a
//by Tasyen
//===========================================================================
// Gives wanted Heroes on specific Levels a choice between optins.
// can replace the default skill choicing or work seperate.
//===========================================================================
//Event:
//===========================================================================
// udg_Talent__Event
// = 1 => on Choice.
// after the Auotskills are added
// = 2 => choice-Container aviable, does only call when there is no choice for this hero yet.
// = 3 => Finished all choices of its hero Type.
// = -1 => on Reset for each choice reseted.
// before the autoskills are removed
// udg_Talent__Event_Hero = the unit gaining the skill
// udg_Talent__Event_Choice = the choice choosen/reseted or the choice container gained.
// udg_Talent__Event_Level = the level from which this choice/container is.
//===========================================================================
//udg_TalentTrigger is an array of Triggers controlling this system.
// udg_TalentTrigger[0] = Enables Choices| specific unit starts channel
// udg_TalentTrigger[1] = On Levelup| specific unit
// udg_TalentTrigger[2] = EnterPlayable Map
// , if you alreay have a EnterPlayable Map trigger you might remove the event inside the init and let yours call this one.
// udg_TalentTrigger[3] = Make Talent UI Visbile; Event On Unit Selection.
// udg_TalentTrigger[4] = Hides the UI when spending Skill-Points for something else.
// once your map reached a state in which there is no choice possible anymore it might be a good idea to disable 0 to 4.
// udg_TalentReset = No Event; when called resets udg_Talent__Reseter and calls for each choice undone the reset event(-1).
// a successful reset will enable udg_TalentTrigger[0]
// Reset uses following values
// udg_Talent__ResetAmount = amount of talents undone starting from last selected. (use an absurd high number to undo all talents of a hero)
// udg_Talent__Reseter = the hero losing talents.
// function TalentResetDo takes unit u, integer amountOfResets returns nothing
// - undo amountOfResets choices for unit u.
// function TalentCopy takes integer result, integer copyOrigin returns nothing
// - units from type result will use the setup from copyOrigin
//===========================================================================
//Definitions:
//===========================================================================
//UseSkillPoints will spent and requier Skill-Points to pick talents.
constant function TalentUseSkillPoints takes nothing returns boolean
return false
endfunction
//This will make the system only give your hero skill Points if he get's a choice.
// your heroes need atleast 1 learnable Skill to adjust skillPoints.
constant function TalentControlSkillPoints takes nothing returns boolean
return false
endfunction
//Hide the UI Button when you can't learn a talent.
//At true will give udg_TalentTrigger[3] the Event "selects a unit" for each player.
constant function TalentHideUIWhenUnneeded takes nothing returns boolean
return true
endfunction
//Increases the Level of abilities gained by choices, if the ability is already owned.
constant function TalentIncreaseByDoubleLearning takes nothing returns boolean
return true
endfunction
//===========================================================================
//Hashtable
//handleId
constant function TalentHashIndex_LastLevel takes nothing returns integer
return -1
endfunction
constant function TalentHashIndex_LevelOfLastChoice takes nothing returns integer
return -2
endfunction
constant function TalentHashIndex_CurrentChoice takes nothing returns integer
return -3
endfunction
constant function TalentHashIndex_CurrentChoiceLevel takes nothing returns integer
return -4
endfunction
constant function TalentHashIndex_SelectionsDone takes nothing returns integer
return -5
endfunction
constant function TalentHashIndex_SkillPoints takes nothing returns integer
return -10
endfunction
constant function TalentHashIndex_HasChoice takes nothing returns integer
return 0
endfunction
//UnitTypeId
// 0 to x choice containers
// x = last talent(true)
constant function TalentHashIndex_DataCustomUI takes nothing returns integer
return -1
endfunction
constant function TalentHashIndex_DataCopyData takes nothing returns integer
return -2
endfunction
//===========================================================================
function TalentGetUnitTypeId takes unit u returns integer
local integer heroTypeId = GetUnitTypeId(u)
local integer copyId = LoadInteger(udg_TalentHash, heroTypeId, TalentHashIndex_DataCopyData())
if copyId != 0 then //Copy another HeroType?
return copyId
else
return heroTypeId
endif
endfunction
function TalentCopy takes integer result, integer copyOrigin returns nothing
call SaveInteger(udg_TalentHash, result, TalentHashIndex_DataCopyData(), copyOrigin)
endfunction
//has the general Choice UI or hero specific Choice UI.
function TalentHas takes unit u returns boolean
return GetUnitAbilityLevel(u, udg_Talent_DefaultUI) != 0 or GetUnitAbilityLevel(u, LoadInteger(udg_TalentHash, TalentGetUnitTypeId(u), TalentHashIndex_DataCustomUI())) != 0
endfunction
//has the general Choice UI or hero specific Choice UI.
function TalentHasCondition takes nothing returns boolean
return TalentHas(GetTriggerUnit())
endfunction
function TalentAddSelection takes unit u, integer uId returns nothing
local integer containerGained
local integer heroTypeId = TalentGetUnitTypeId(u)
local integer currentLevel = GetHeroLevel(u)
local player owner
//Start from the last skill selection added.
local integer loopA = LoadInteger(udg_TalentHash, uId,TalentHashIndex_LevelOfLastChoice())
// Only show 1 SelectionContainer at the same time.
if LoadBoolean(udg_TalentHash, uId,TalentHashIndex_HasChoice()) then
return
endif
set owner = GetOwningPlayer(u)
loop
exitwhen loopA > currentLevel
set containerGained = LoadInteger(udg_TalentHash, heroTypeId, loopA)
if containerGained != 0 then
call UnitAddAbility(u, containerGained)
call UnitMakeAbilityPermanent(u, true, containerGained)
call SetPlayerAbilityAvailable(owner, containerGained, false)
//Remember the container gained
call SaveInteger(udg_TalentHash, uId, TalentHashIndex_CurrentChoice(), containerGained)
//Remember the level of the container gained
call SaveInteger(udg_TalentHash, uId, TalentHashIndex_CurrentChoiceLevel(), loopA)
//Mark unit to have a selection.
call SaveBoolean(udg_TalentHash, uId, TalentHashIndex_HasChoice(), true)
//Remember this Level to leave lower levels out for further selections checks.
call SaveInteger(udg_TalentHash, uId,TalentHashIndex_LevelOfLastChoice(),loopA +1)
// show UI
call SetPlayerAbilityAvailable(owner, udg_Talent_DefaultUI, true)
call SetPlayerAbilityAvailable(owner, LoadInteger(udg_TalentHash, heroTypeId, TalentHashIndex_DataCustomUI()), true)
//Throw Selection Event
set udg_Talent__Event_Choice = containerGained
set udg_Talent__Event_Hero = u
set udg_Talent__Event_Level = loopA
set udg_Talent__Event = 2
set udg_Talent__Event = 0
set owner = null
return
endif
set loopA = loopA + 1
endloop
//if this part of code is reached there is no choice avaible
//Remember this Level to leave lower levels out for further selections checks.
call SaveInteger(udg_TalentHash, uId,TalentHashIndex_LevelOfLastChoice(),currentLevel + 1)
//Hide UI when wanted so
if TalentHideUIWhenUnneeded() then
call SetPlayerAbilityAvailable(owner, udg_Talent_DefaultUI, false)
call SetPlayerAbilityAvailable(owner, LoadInteger(udg_TalentHash, heroTypeId, TalentHashIndex_DataCustomUI()), false)
endif
set owner = null
endfunction
function TalentLevelUpA takes unit u, integer uId returns nothing
local integer lastLevel = LoadInteger(udg_TalentHash, uId, TalentHashIndex_LastLevel())
local integer currentLevel = IMaxBJ(GetHeroLevel(u), GetUnitLevel(u))
local integer heroTypeId = TalentGetUnitTypeId(u)
local integer containerGained
loop
set containerGained = LoadInteger(udg_TalentHash, heroTypeId, lastLevel)
if containerGained != 0 then
call UnitModifySkillPoints(u, 1)
endif
set lastLevel = lastLevel + 1
exitwhen lastLevel > currentLevel
endloop
//Save last Level
call SaveInteger(udg_TalentHash, uId, TalentHashIndex_LastLevel(), currentLevel + 1)
call SaveInteger(udg_TalentHash, uId, TalentHashIndex_SkillPoints(), GetHeroSkillPoints(u))
endfunction
function TalentLevelUp takes nothing returns nothing
local unit u = GetTriggerUnit()
local integer uId = GetHandleId(u)
//Reduce if he gained a skill Point.
if LoadInteger(udg_TalentHash, uId, TalentHashIndex_SkillPoints()) < GetHeroSkillPoints(u) then
call UnitModifySkillPoints(u, -1)
endif
call TalentLevelUpA(u,uId)
call TalentAddSelection(u,uId)
set u = null
endfunction
function TalentPickDo takes unit u, integer skillId returns nothing
local integer uId = GetHandleId(u)
local integer heroTypeId = TalentGetUnitTypeId(u)
local integer skillGained
local integer skillContainer = LoadInteger(udg_TalentHash, uId, TalentHashIndex_CurrentChoice())
local integer skillContainerLevel = LoadInteger(udg_TalentHash, uId, TalentHashIndex_CurrentChoiceLevel())
local integer selectionsDone = LoadInteger(udg_TalentHash, uId,TalentHashIndex_SelectionsDone()) + 1
local integer loopB = 0
local integer abilitylevel
//add Skills
loop
set skillGained = LoadInteger(udg_TalentHash, skillId, loopB)
if skillGained != 0 then
set abilitylevel = GetUnitAbilityLevel(u, skillGained)
if abilitylevel == 0 then
call UnitAddAbility(u, skillGained)
call UnitMakeAbilityPermanent(u, true, skillGained)
elseif TalentIncreaseByDoubleLearning() then
call SetUnitAbilityLevel(u, skillGained, abilitylevel + 1)
endif
endif
exitwhen skillGained == 0
set loopB = loopB + 1
endloop
//remove Container of this Selection
//call UnitRemoveAbility(u, skillContainer)
//Throw Selection Event
set udg_Talent__Event_Choice = skillId
set udg_Talent__Event_Hero = u
set udg_Talent__Event_Level = skillContainerLevel
set udg_Talent__Event = 1
set udg_Talent__Event = 0
//Save Choices
call SaveInteger(udg_TalentHash, uId, selectionsDone, skillId)
call SaveInteger(udg_TalentHash, uId, TalentHashIndex_SelectionsDone(), selectionsDone)
call SaveInteger(udg_TalentHash, uId, skillId, skillContainerLevel)
//Unmark having a selection.
call SaveBoolean(udg_TalentHash, uId, TalentHashIndex_HasChoice(), false)
//Last choice for this heroType?
if LoadBoolean(udg_TalentHash, heroTypeId, skillContainerLevel) then
//has herospeciifc learnbook?
if HaveSavedInteger(udg_TalentHash, heroTypeId, TalentHashIndex_DataCustomUI()) then
call UnitRemoveAbility(u, LoadInteger(udg_TalentHash, heroTypeId, TalentHashIndex_DataCustomUI()))
else
call UnitRemoveAbility(u, udg_Talent_DefaultUI)
endif
call UnitAddAbility(u, udg_Talent_EmptyHeroSkill)
call SetUnitAbilityLevel (u, udg_Talent_EmptyHeroSkill, 4)
//Throw Finish Choices Event.
set udg_Talent__Event = 3
set udg_Talent__Event = 0
else
//Check for further choices.
call TalentAddSelection(u,uId)
endif
set u = null
endfunction
function TalentPickTimer takes nothing returns nothing
local unit u
local integer uId
local integer skillContainer
local integer skillId
local integer gId = GetHandleId(udg_Talent_PickGroup)
loop
set u = FirstOfGroup(udg_Talent_PickGroup)
exitwhen u == null
call GroupRemoveUnit(udg_Talent_PickGroup,u)
set uId = GetHandleId(u)
set skillId = LoadInteger(udg_TalentHash,uId, gId)
set skillContainer = LoadInteger(udg_TalentHash, uId, TalentHashIndex_CurrentChoice())
//Remove the choice-container, if the unit loses the casted spell its a choice.
call UnitRemoveAbility(u, skillContainer)
if GetUnitAbilityLevel(u, skillId) != 0 then
call UnitAddAbility(u, skillContainer)
else
//choice
//Stop spellcasting
call IssueImmediateOrder(u, "stop")
// Skill-Points?
if TalentUseSkillPoints() then
if GetHeroSkillPoints(u) != 0 then
call UnitModifySkillPoints(u, -1)
call SaveInteger(udg_TalentHash, uId, TalentHashIndex_SkillPoints(), GetHeroSkillPoints(u))
else
//Not enough Skill-Points
call DisplayTimedTextToPlayer(GetOwningPlayer(u), 0, 0, 20, "Not enough Skill-Points")
call UnitAddAbility(u, skillContainer)
return
endif
endif
// run the add skill script
call TalentPickDo(u, skillId)
endif
endloop
endfunction
function TalentPick takes nothing returns nothing
local unit u = GetTriggerUnit()
local integer uId = GetHandleId(u)
//Is allowed to make a choice?
if LoadBoolean(udg_TalentHash, uId, TalentHashIndex_HasChoice()) then
call GroupAddUnit(udg_Talent_PickGroup, u)
call SaveInteger(udg_TalentHash,uId, GetHandleId(udg_Talent_PickGroup), GetSpellAbilityId())
call TimerStart(udg_Talent_PickTimer,0.01,false, function TalentPickTimer)
endif
set u = null
endfunction
function TalentLevelUpSimple takes nothing returns nothing
call TalentAddSelection(GetTriggerUnit(),GetHandleId(GetTriggerUnit()))
endfunction
function TalentAdd2Hero takes unit u returns nothing
local integer uId = GetHandleId(u)
//call GroupAddUnit(udg_Talent_User, u)
call TriggerRegisterUnitEvent( udg_TalentTrigger[0], u, EVENT_UNIT_SPELL_CHANNEL )
call TriggerRegisterUnitEvent( udg_TalentTrigger[1], u, EVENT_UNIT_HERO_LEVEL)
if TalentControlSkillPoints() then
call UnitModifySkillPoints(u, -1)
call TalentLevelUpA(u,uId)
endif
if TalentHideUIWhenUnneeded() and TalentUseSkillPoints() then
call TriggerRegisterUnitEvent( udg_TalentTrigger[4], u, EVENT_UNIT_HERO_SKILL)
endif
call TalentAddSelection(u,uId)
set u = null
endfunction
function TalentAutoOnEnterMap takes nothing returns nothing
call TalentAdd2Hero(GetTriggerUnit())
endfunction
function TalentResetDo takes unit u, integer amountOfResets returns nothing
local integer uId
local integer heroTypeId
local integer selectionsDone
local integer skillGained
local integer choice
local integer level
local integer loopB = 0
local integer abilitylevel
//stop nullpointer.
if u == null then
return
endif
// reset less then 1 does not make sense.
if amountOfResets < 1 then
return
endif
set uId = GetHandleId(u)
set heroTypeId = TalentGetUnitTypeId(u)
set selectionsDone = LoadInteger(udg_TalentHash, uId, TalentHashIndex_SelectionsDone())
//No selections done -> skip the rest.
if selectionsDone == 0 then
return
endif
set udg_Talent__Event_Hero = u
//Remove Autoadded Skills
loop
set choice = LoadInteger(udg_TalentHash, uId, selectionsDone)
set udg_Talent__Event_Choice = choice
set level = LoadInteger(udg_TalentHash, uId, choice)
set udg_Talent__Event_Level = level
//Throw a event that this choice is going to be lost.
set udg_Talent__Event = -1
set udg_Talent__Event = 0
//Remove all Skill this Choice added.
set loopB = 0
loop
set skillGained = LoadInteger(udg_TalentHash, choice, loopB)
exitwhen skillGained == 0
set abilitylevel = GetUnitAbilityLevel(u, skillGained)
if abilitylevel > 1 and TalentIncreaseByDoubleLearning() then
call SetUnitAbilityLevel(u, skillGained, abilitylevel - 1)
else
call UnitRemoveAbility(u, skillGained)
endif
set loopB = loopB + 1
endloop
set selectionsDone = selectionsDone - 1
set amountOfResets = amountOfResets - 1
exitwhen selectionsDone <= 0 or amountOfResets <= 0
endloop
//Enable Choices again.
call EnableTrigger (udg_TalentTrigger[0])
//Remove Current Choice Container.
call UnitRemoveAbility(u, LoadInteger(udg_TalentHash, uId, TalentHashIndex_CurrentChoice()))
//Forget this unit?
if selectionsDone <= 0 then
//Full Reset
call FlushChildHashtable(udg_TalentHash, uId)
else
//Partly Reset.
//Has no Choice,dat is needed to run the addChoice function.
call SaveBoolean(udg_TalentHash, uId,TalentHashIndex_HasChoice(), false)
//Save Level Progress of talents to the choice Level.
call SaveInteger(udg_TalentHash, uId, TalentHashIndex_LevelOfLastChoice(), level)
//Save Level Progress skillPoints
call SaveInteger(udg_TalentHash, uId, TalentHashIndex_LastLevel(), level)
//Choices Done
call SaveInteger(udg_TalentHash, uId,TalentHashIndex_SelectionsDone(), selectionsDone)
endif
//Regain Choice UI
//has herospeciifc learnbook?
if HaveSavedInteger(udg_TalentHash, heroTypeId, TalentHashIndex_DataCustomUI()) then
call UnitAddAbility(u, LoadInteger(udg_TalentHash, heroTypeId, TalentHashIndex_DataCustomUI()))
else
call UnitAddAbility(u, udg_Talent_DefaultUI)
endif
call UnitRemoveAbility(u, udg_Talent_EmptyHeroSkill)
//Recalc skillpoints if wanted.
if TalentUseSkillPoints() then
call UnitModifySkillPoints(u, -9999)
call TalentLevelUpA(u,uId)
endif
call TalentAddSelection(u,uId)
endfunction
function TalentReset takes nothing returns nothing
call TalentResetDo(udg_Talent__Reseter, udg_Talent__ResetAmount)
set udg_Talent__Reseter = null
endfunction
function TalentShowUI takes nothing returns nothing
local unit u = GetTriggerUnit()
local player owner = GetOwningPlayer(u)
local integer customUI = LoadInteger(udg_TalentHash, TalentGetUnitTypeId(u), TalentHashIndex_DataCustomUI())
local boolean show = LoadBoolean(udg_TalentHash, GetHandleId(u), TalentHashIndex_HasChoice() )
call SetPlayerAbilityAvailable(owner, udg_Talent_DefaultUI, show)
call SetPlayerAbilityAvailable(owner, customUI, show)
set u = null
set owner = null
endfunction
function TalentSpentSkillPoints takes nothing returns nothing
local unit u = GetTriggerUnit()
local player owner = GetOwningPlayer(u)
local integer customUI
local integer skillPoints = GetHeroSkillPoints(u)
call SaveInteger(udg_TalentHash, GetHandleId(u), TalentHashIndex_SkillPoints(), skillPoints - 1)
//Spent the last Point?
if skillPoints == 1 then
set customUI = LoadInteger(udg_TalentHash, TalentGetUnitTypeId(u), TalentHashIndex_DataCustomUI())
call SetPlayerAbilityAvailable(owner, udg_Talent_DefaultUI, false)
call SetPlayerAbilityAvailable(owner, customUI, false)
endif
set u = null
set owner = null
endfunction
function TalentShowUICon takes nothing returns boolean
return TalentHas(GetTriggerUnit()) and IsUnitOwnedByPlayer(GetTriggerUnit(), GetTriggerPlayer())
endfunction
//runs when executing the Talent <gen> trigger.
function TalentInit takes nothing returns nothing
local group g = CreateGroup()
local unit fog
local integer fogId
local integer loopA = 0
set udg_TalentTrigger[0] = CreateTrigger()
set udg_TalentTrigger[1] = CreateTrigger()
set udg_TalentTrigger[2] = CreateTrigger()
set udg_TalentTrigger[3] = CreateTrigger()
set udg_TalentTrigger[4] = CreateTrigger()
set udg_TalentReset = CreateTrigger()
call TriggerAddAction( udg_TalentReset, function TalentReset)
//Do a choice.
call TriggerAddAction( udg_TalentTrigger[0], function TalentPick )
call TriggerAddAction( udg_TalentTrigger[4], function TalentSpentSkillPoints )
//Get a choice when Level Up
//when using skillpoints the default hero skill system should not be used for this hero.
if TalentControlSkillPoints() then
call TriggerAddAction( udg_TalentTrigger[1], function TalentLevelUp)
else
call TriggerAddAction( udg_TalentTrigger[1], function TalentLevelUpSimple)
endif
call TriggerAddAction( udg_TalentTrigger[3], function TalentShowUI)
call TriggerAddCondition( udg_TalentTrigger[3], Condition( function TalentShowUICon ))
//Get Choices on Entering Map for lvl 0/1.
call TriggerRegisterEnterRectSimple( udg_TalentTrigger[2], GetPlayableMapRect() )
call TriggerAddAction( udg_TalentTrigger[2], function TalentAutoOnEnterMap)
call TriggerAddCondition( udg_TalentTrigger[2], Condition( function TalentHasCondition ))
loop
call SetPlayerAbilityAvailable(Player(loopA), udg_Talent_EmptyHeroSkill, false)
if TalentHideUIWhenUnneeded() then
call TriggerRegisterPlayerUnitEvent(udg_TalentTrigger[3], Player(loopA), EVENT_PLAYER_UNIT_SELECTED, null)
endif
set loopA = loopA + 1
exitwhen loopA == bj_MAX_PLAYER_SLOTS
endloop
//Add possible choices to all Units having the Talent book.
call GroupEnumUnitsInRect (g, GetPlayableMapRect(), null)
loop
set fog = FirstOfGroup(g)
exitwhen fog == null
call GroupRemoveUnit(g,fog)
if TalentHas(fog) then
call TalentAdd2Hero(fog)
endif
endloop
//cleanup
call DestroyGroup(g)
set g = null
set fog = null
//make this trigger unuseable
call TriggerClearActions(gg_trg_Talent)
call TriggerClearConditions(gg_trg_Talent)
endfunction
//===========================================================================
function InitTrig_Talent takes nothing returns nothing
set gg_trg_Talent = CreateTrigger( )
set udg_TalentHash = InitHashtable( )
call TriggerAddAction( gg_trg_Talent, function TalentInit)
endfunction