Name | Type | is_array | initial_value |
CinematicSkip | boolean | No | |
GermanicPlayers | force | No | |
GermanicPlayersUsers | force | No | |
LightningTimer | timer | No | |
RomanPlayers | force | No | |
RomanPlayersUsers | force | No | |
TmpGroup | group | No | |
TmpUnit | unit | No |
library SimError initializer init
//**************************************************************************************************
//*
//* SimError
//*
//* Mimic an interface error message
//* call SimError(ForPlayer, msg)
//* ForPlayer : The player to show the error
//* msg : The error
//*
//* To implement this function, copy this trigger and paste it in your map.
//* Unless of course you are actually reading the library from wc3c's scripts section, then just
//* paste the contents into some custom text trigger in your map.
//*
//**************************************************************************************************
//==================================================================================================
globals
private sound error
endglobals
//====================================================================================================
function SimError takes player ForPlayer, string msg returns nothing
set msg="\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n|cffffcc00"+msg+"|r"
if (GetLocalPlayer() == ForPlayer) then
call ClearTextMessages()
call DisplayTimedTextToPlayer( ForPlayer, 0.52, 0.96, 2.00, msg )
call StartSound( error )
endif
endfunction
private function init takes nothing returns nothing
set error=CreateSoundFromLabel("InterfaceError",false,false,false,10,10)
//call StartSound( error ) //apparently the bug in which you play a sound for the first time
//and it doesn't work is not there anymore in patch 1.22
endfunction
endlibrary
library TreeUtils initializer Init
globals
constant integer SUMMER_TREE_WALL= 'LTlt'
constant integer ASHENVALE_TREE_WALL= 'ATtr'
constant integer ASHENVALE_CANOPY_TREE= 'ATtc'
constant integer BARRENS_TREE_WALL= 'BTtw'
constant integer BARRENS_CANOPY_TREE= 'BTtc'
constant integer BLACK_CITADEL_TREE_WALL= 'KTtw'
constant integer CITYSCAPE_SNOWY_TREE_WALL= 'YTst'
constant integer CITYSCAPE_FALL_TREE_WALL= 'YTft'
constant integer CITYSCAPE_WINTER_TREE_WALL= 'YTwt'
constant integer CITYSCAPE_SUMMER_TREE_WALL= 'YTct'
constant integer DALARAN_RUINS_TREE_WALL= 'JTtw'
constant integer DUNGEON_TREE_WALL= 'DTsh'
constant integer FELWOOD_TREE_WALL= 'CTtr'
constant integer FELWOOD_CANOPY_TREE= 'CTtc'
constant integer ICECROWN_TREE_WALL= 'ITtw'
constant integer ICECROWN_CANOPY_TREE= 'ITtc'
constant integer WINTER_TREE_WALL= 'WTtw'
constant integer NORTHREND_TREE_WALL= 'NTtw'
constant integer SNOWY_TREE_WALL= 'WTst'
constant integer OUTLAND_TREE_WALL= 'OTtw'
constant integer RUINS_TREE_WALL= 'ZTtw'
constant integer RUINS_CANOPY_TREE= 'ZTtc'
constant integer UNDERGROUND_TREE_WALL= 'GTsh'
constant integer VILLAGE_TREE_WALL= 'VTlt'
constant integer FALL_TREE_WALL= 'FTtw'
constant integer SCORCHED_TREE_WALL= 'Ytsc'
constant integer SILVERMOON_TREE= 'Yts1'
private integer array ids
private integer count = 0
endglobals
function AddTree takes integer id returns integer
local integer index= count
set ids[index]=id
set count=index + 1
return index
endfunction
function GetTree takes integer index returns integer
return ids[index]
endfunction
function GetTreeCount takes nothing returns integer
return count
endfunction
function IsTree takes integer id returns boolean
local integer i= 0
loop
exitwhen ( i == count)
if (ids[i] == id ) then
return true
endif
set i=i + 1
endloop
return false
endfunction
function IsDestructableTree takes destructable whichDestructable returns boolean
return IsTree(GetDestructableTypeId(whichDestructable))
endfunction
private function Init takes nothing returns nothing
call AddTree(SUMMER_TREE_WALL)
call AddTree(ASHENVALE_TREE_WALL)
call AddTree(ASHENVALE_CANOPY_TREE)
call AddTree(BARRENS_TREE_WALL)
call AddTree(BARRENS_CANOPY_TREE)
call AddTree(BLACK_CITADEL_TREE_WALL)
call AddTree(CITYSCAPE_SNOWY_TREE_WALL)
call AddTree(CITYSCAPE_FALL_TREE_WALL)
call AddTree(CITYSCAPE_WINTER_TREE_WALL)
call AddTree(CITYSCAPE_SUMMER_TREE_WALL)
call AddTree(DALARAN_RUINS_TREE_WALL)
call AddTree(DUNGEON_TREE_WALL)
call AddTree(FELWOOD_TREE_WALL)
call AddTree(FELWOOD_CANOPY_TREE)
call AddTree(ICECROWN_TREE_WALL)
call AddTree(ICECROWN_CANOPY_TREE)
call AddTree(WINTER_TREE_WALL)
call AddTree(NORTHREND_TREE_WALL)
call AddTree(SNOWY_TREE_WALL)
call AddTree(OUTLAND_TREE_WALL)
call AddTree(RUINS_TREE_WALL)
call AddTree(RUINS_CANOPY_TREE)
call AddTree(UNDERGROUND_TREE_WALL)
call AddTree(VILLAGE_TREE_WALL)
call AddTree(FALL_TREE_WALL)
call AddTree(SCORCHED_TREE_WALL)
call AddTree(SILVERMOON_TREE)
call AddTree('B000') // Oak
call AddTree('B002') // Birch
call AddTree('B003') // Pine
endfunction
endlibrary
library HideInTrees initializer Init requires TreeUtils
globals
public constant string ORDER_HIDE = "eattree"
public constant integer ABILITY_ID_HIDE = 'A00Z'
public constant integer ABILITY_ID_UNHIDE = 'A010'
public constant integer ABILITY_ID_LIFE_REGENERATION = 'A01B'
public constant integer ABILITY_ID_MANA_REGENERATION = 'A01C'
private constant integer KEY_UNIT = 0
private constant integer KEY_MOVE_TYPE = 1
private constant integer KEY_ATTACK_0_ENABLED = 2
private constant integer KEY_ATTACK_1_ENABLED = 3
private trigger castTrigger = CreateTrigger()
private trigger orderTrigger = CreateTrigger()
private trigger deathTrigger = CreateTrigger()
private unit filterCaster = null
private destructable resultingTree = null
private group casters = CreateGroup()
private hashtable h = InitHashtable()
endglobals
private function GetTreeHiddenUnit takes destructable t returns unit
return LoadUnitHandle(h, GetHandleId(t), KEY_UNIT)
endfunction
private function HideUnit takes unit whichUnit, destructable tree returns nothing
call GroupAddUnit(casters, whichUnit)
call SetUnitInvulnerable(whichUnit, true)
call SetUnitPathing(whichUnit, false)
call SetUnitX(whichUnit, GetDestructableX(tree))
call SetUnitY(whichUnit, GetDestructableY(tree))
call BlzUnitDisableAbility(GetTriggerUnit(), 'Amov', true, true)
call SaveUnitHandle(h, GetHandleId(tree), KEY_UNIT, whichUnit)
call SaveInteger(h, GetHandleId(whichUnit), KEY_MOVE_TYPE, BlzGetUnitIntegerField(whichUnit, UNIT_IF_MOVE_TYPE))
call SaveBoolean(h, GetHandleId(whichUnit), KEY_ATTACK_0_ENABLED, BlzGetUnitWeaponBooleanField(whichUnit, UNIT_WEAPON_BF_ATTACKS_ENABLED, 0))
call SaveBoolean(h, GetHandleId(whichUnit), KEY_ATTACK_1_ENABLED, BlzGetUnitWeaponBooleanField(whichUnit, UNIT_WEAPON_BF_ATTACKS_ENABLED, 1))
call BlzSetUnitIntegerField(whichUnit, UNIT_IF_MOVE_TYPE, 0)
call BlzSetUnitWeaponBooleanField(whichUnit, UNIT_WEAPON_BF_ATTACKS_ENABLED, 0, false)
call BlzSetUnitWeaponBooleanField(whichUnit, UNIT_WEAPON_BF_ATTACKS_ENABLED, 1, false)
call UnitAddAbility(whichUnit, 'Apiv')
call UnitAddAbility(whichUnit, ABILITY_ID_LIFE_REGENERATION)
call UnitAddAbility(whichUnit, ABILITY_ID_LIFE_REGENERATION)
call UnitAddAbility(whichUnit, ABILITY_ID_UNHIDE)
call UnitAddType(whichUnit, UNIT_TYPE_SNARED)
//call BJDebugMsg(GetUnitName(whichUnit) + " cast on " + GetDestructableName(tree))
endfunction
private function UnhideUnit takes unit whichUnit returns nothing
if (IsUnitInGroup(whichUnit, casters)) then
call GroupRemoveUnit(casters, whichUnit)
call SetUnitInvulnerable(whichUnit, false)
call SetUnitPathing(whichUnit, true)
call SetUnitPosition(whichUnit, GetUnitX(whichUnit), GetUnitY(whichUnit)) // for collision
call BlzUnitDisableAbility(GetTriggerUnit(), 'Amov', false, false)
call UnitRemoveAbility(whichUnit, 'Apiv')
call UnitRemoveAbility(whichUnit, ABILITY_ID_LIFE_REGENERATION)
call UnitRemoveAbility(whichUnit, ABILITY_ID_MANA_REGENERATION)
call UnitRemoveAbility(whichUnit, ABILITY_ID_UNHIDE)
//call BJDebugMsg(GetUnitName(whichUnit) + " cast unhide")
call BlzSetUnitIntegerField(whichUnit, UNIT_IF_MOVE_TYPE, LoadInteger(h, GetHandleId(whichUnit), KEY_MOVE_TYPE))
call BlzSetUnitWeaponBooleanField(whichUnit, UNIT_WEAPON_BF_ATTACKS_ENABLED, 0, LoadBoolean(h, GetHandleId(whichUnit), KEY_ATTACK_0_ENABLED))
call BlzSetUnitWeaponBooleanField(whichUnit, UNIT_WEAPON_BF_ATTACKS_ENABLED, 1, LoadBoolean(h, GetHandleId(whichUnit), KEY_ATTACK_1_ENABLED))
call FlushChildHashtable(h, GetHandleId(whichUnit))
endif
endfunction
private function TriggerConditionCast takes nothing returns boolean
if (GetSpellAbilityId() == ABILITY_ID_HIDE) then
if (GetTreeHiddenUnit(GetSpellTargetDestructable()) == null) then
call HideUnit(GetTriggerUnit(), GetSpellTargetDestructable())
else
call IssueImmediateOrder(GetTriggerUnit(), "stop")
call SimError(GetOwningPlayer(GetTriggerUnit()), GetLocalizedString("TRIGSTR_728")) // "Tree is already occupied."
endif
elseif (GetSpellAbilityId() == ABILITY_ID_UNHIDE) then
call UnhideUnit(GetTriggerUnit())
endif
return false
endfunction
private function DistanceBetweenCoordinates takes real x1,real y1,real x2,real y2 returns real
local real dx= ( x2 - x1 )
local real dy= ( y2 - y1 )
return SquareRoot(dx * dx + dy * dy)
endfunction
private function EnumDestructableFreeTree takes nothing returns nothing
if (IsDestructableTree(GetEnumDestructable()) and GetTreeHiddenUnit(GetEnumDestructable()) == null and (resultingTree == null or DistanceBetweenCoordinates(GetUnitX(filterCaster), GetUnitY(filterCaster), GetDestructableX(GetEnumDestructable()), GetDestructableY(GetEnumDestructable())) < DistanceBetweenCoordinates(GetUnitX(filterCaster), GetUnitY(filterCaster), GetDestructableX(resultingTree), GetDestructableY(resultingTree)))) then
set resultingTree = GetEnumDestructable()
endif
endfunction
private function GetFreeTreeNextTo takes unit caster, real x, real y returns destructable
local location l = Location(x, y)
set resultingTree = null
set filterCaster = caster
call EnumDestructablesInCircleBJ(64.0, l, function EnumDestructableFreeTree)
call RemoveLocation(l)
set l = null
return resultingTree
endfunction
private function OrderNextToTree takes unit caster, real x, real y returns nothing
local destructable tree = GetFreeTreeNextTo(caster, x, y)
if (tree != null) then
//call BJDebugMsg("Found tree " + GetDestructableName(tree))
call IssueTargetDestructableOrder(caster, ORDER_HIDE, tree)
set tree = null
endif
endfunction
private function TriggerConditionOrder takes nothing returns boolean
if (GetIssuedOrderId() == OrderId("smart") and GetUnitAbilityLevel(GetTriggerUnit(), ABILITY_ID_HIDE) > 0) then
//call BJDebugMsg("Order!")
call OrderNextToTree(GetTriggerUnit(), GetOrderPointX(), GetOrderPointY())
endif
return false
endfunction
private function FilterIsTree takes nothing returns boolean
return IsDestructableTree(GetFilterDestructable())
endfunction
private function RegisterDestDeathInRegionEnumX takes nothing returns nothing
call TriggerRegisterDeathEvent(bj_destInRegionDiesTrig, GetEnumDestructable())
endfunction
private function TriggerConditionDeath takes nothing returns boolean
if (GetTreeHiddenUnit(GetTriggerDestructable()) != null) then
call UnhideUnit(GetTreeHiddenUnit(GetTriggerDestructable()))
call FlushChildHashtable(h, GetHandleId(GetTriggerDestructable()))
endif
return false
endfunction
private function Init takes nothing returns nothing
call TriggerRegisterAnyUnitEventBJ(castTrigger, EVENT_PLAYER_UNIT_SPELL_CHANNEL)
call TriggerAddCondition(castTrigger, Condition(function TriggerConditionCast))
call TriggerRegisterAnyUnitEventBJ(orderTrigger, EVENT_PLAYER_UNIT_ISSUED_POINT_ORDER)
call TriggerAddCondition(orderTrigger, Condition(function TriggerConditionOrder))
set bj_destInRegionDiesTrig = deathTrigger
call EnumDestructablesInRect(GetPlayableMapRect(), Filter(function FilterIsTree), function RegisterDestDeathInRegionEnumX)
call TriggerAddCondition(deathTrigger, Condition(function TriggerConditionDeath))
endfunction
private function RemoveUnitHook takes unit whichUnit returns nothing
if (IsUnitInGroup(whichUnit, casters)) then
call GroupRemoveUnit(casters, whichUnit)
call FlushChildHashtable(h, GetHandleId(whichUnit))
endif
endfunction
private function RemoveDestructableHook takes destructable whichDestructable returns nothing
call FlushChildHashtable(h, GetHandleId(whichDestructable))
endfunction
hook RemoveUnit RemoveUnitHook
hook RemoveDestructable RemoveDestructableHook
endlibrary