-
Notifications
You must be signed in to change notification settings - Fork 14
/
builder.lua
155 lines (124 loc) · 5.7 KB
/
builder.lua
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
-- A build ability is used (not yet confirmed)
function Build( event )
local caster = event.caster
local ability = event.ability
local ability_name = ability:GetAbilityName()
local building_name = ability:GetAbilityKeyValues()['UnitName']
local gold_cost = ability:GetGoldCost(1)
local hero = caster:IsRealHero() and caster or caster:GetOwner()
local playerID = hero:GetPlayerID()
-- If the ability has an AbilityGoldCost, it's impossible to not have enough gold the first time it's cast
-- Always refund the gold here, as the building hasn't been placed yet
hero:ModifyGold(gold_cost, false, 0)
-- Makes a building dummy and starts panorama ghosting
BuildingHelper:AddBuilding(event)
-- Additional checks to confirm a valid building position can be performed here
event:OnPreConstruction(function(vPos)
-- Check for minimum height if defined
if not BuildingHelper:MeetsHeightCondition(vPos) then
BuildingHelper:print("Failed placement of " .. building_name .." - Placement is below the min height required")
SendErrorMessage(playerID, "#error_invalid_build_position")
return false
end
-- If not enough resources to queue, stop
if PlayerResource:GetGold(playerID) < gold_cost then
BuildingHelper:print("Failed placement of " .. building_name .." - Not enough gold!")
SendErrorMessage(playerID, "#error_not_enough_gold")
return false
end
return true
end)
-- Position for a building was confirmed and valid
event:OnBuildingPosChosen(function(vPos)
-- Spend resources
hero:ModifyGold(-gold_cost, false, 0)
-- Play a sound
EmitSoundOnClient("DOTA_Item.ObserverWard.Activate", PlayerResource:GetPlayer(playerID))
end)
-- The construction failed and was never confirmed due to the gridnav being blocked in the attempted area
event:OnConstructionFailed(function()
local playerTable = BuildingHelper:GetPlayerTable(playerID)
local building_name = playerTable.activeBuilding
BuildingHelper:print("Failed placement of " .. building_name)
end)
-- Cancelled due to ClearQueue
event:OnConstructionCancelled(function(work)
local building_name = work.name
BuildingHelper:print("Cancelled construction of " .. building_name)
-- Refund resources for this cancelled work
if work.refund then
hero:ModifyGold(gold_cost, false, 0)
end
end)
-- A building unit was created
event:OnConstructionStarted(function(unit)
BuildingHelper:print("Started construction of " .. unit:GetUnitName() .. " " .. unit:GetEntityIndex())
-- Play construction sound
-- If it's an item-ability and has charges, remove a charge or remove the item if no charges left
if ability.GetCurrentCharges and not ability:IsPermanent() then
local charges = ability:GetCurrentCharges()
charges = charges-1
if charges == 0 then
ability:RemoveSelf()
else
ability:SetCurrentCharges(charges)
end
end
-- Units can't attack while building
unit.original_attack = unit:GetAttackCapability()
unit:SetAttackCapability(DOTA_UNIT_CAP_NO_ATTACK)
-- Give item to cancel
unit.item_building_cancel = CreateItem("item_building_cancel", hero, hero)
if unit.item_building_cancel then
unit:AddItem(unit.item_building_cancel)
unit.gold_cost = gold_cost
end
-- FindClearSpace for the builder
FindClearSpaceForUnit(caster, caster:GetAbsOrigin(), true)
caster:AddNewModifier(caster, nil, "modifier_phased", {duration=0.03})
-- Remove invulnerability on npc_dota_building baseclass
unit:RemoveModifierByName("modifier_invulnerable")
end)
-- A building finished construction
event:OnConstructionCompleted(function(unit)
BuildingHelper:print("Completed construction of " .. unit:GetUnitName() .. " " .. unit:GetEntityIndex())
-- Play construction complete sound
-- Remove the item
if unit.item_building_cancel then
UTIL_Remove(unit.item_building_cancel)
end
-- Give the unit their original attack capability
unit:SetAttackCapability(unit.original_attack)
end)
-- These callbacks will only fire when the state between below half health/above half health changes.
-- i.e. it won't fire multiple times unnecessarily.
event:OnBelowHalfHealth(function(unit)
BuildingHelper:print(unit:GetUnitName() .. " is below half health.")
end)
event:OnAboveHalfHealth(function(unit)
BuildingHelper:print(unit:GetUnitName().. " is above half health.")
end)
end
-- Called when the Cancel ability-item is used
function CancelBuilding( keys )
local building = keys.unit
local hero = building:GetOwner()
local playerID = building:GetPlayerOwnerID()
BuildingHelper:print("CancelBuilding "..building:GetUnitName().." "..building:GetEntityIndex())
-- Refund here
if building.gold_cost then
hero:ModifyGold(building.gold_cost, false, 0)
end
-- Eject builder
local builder = building.builder_inside
if builder then
BuildingHelper:ShowBuilder(builder)
end
building:ForceKill(true) --This will call RemoveBuilding
end
-- Requires notifications library from bmddota/barebones
function SendErrorMessage( pID, string )
Notifications:ClearBottom(pID)
Notifications:Bottom(pID, {text=string, style={color='#E62020'}, duration=2})
EmitSoundOnClient("General.Cancel", PlayerResource:GetPlayer(pID))
end