warscript 0.0.1-dev.4414935 → 0.0.1-dev.459629d

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (78) hide show
  1. package/core/types/frame.d.ts +1 -0
  2. package/core/types/frame.lua +112 -37
  3. package/core/types/handle.lua +6 -9
  4. package/core/types/item.d.ts +1 -0
  5. package/core/types/item.lua +1 -0
  6. package/core/types/player.d.ts +1 -1
  7. package/core/types/player.lua +12 -11
  8. package/core/types/sound.lua +1 -1
  9. package/engine/behaviour/ability/damage.d.ts +3 -0
  10. package/engine/behaviour/ability/damage.lua +8 -2
  11. package/engine/behaviour/ability/emulate-impact.lua +5 -4
  12. package/engine/behaviour/ability.d.ts +9 -5
  13. package/engine/behaviour/ability.lua +29 -0
  14. package/engine/buff.d.ts +49 -17
  15. package/engine/buff.lua +241 -118
  16. package/engine/internal/ability.lua +15 -15
  17. package/engine/internal/item/fields.d.ts +12 -0
  18. package/engine/internal/item/fields.lua +33 -0
  19. package/engine/internal/item.d.ts +4 -5
  20. package/engine/internal/item.lua +37 -40
  21. package/engine/internal/object-data/attribute-bonus.lua +2 -2
  22. package/engine/internal/object-data/health-bonus.d.ts +2 -0
  23. package/engine/internal/object-data/health-bonus.lua +16 -0
  24. package/engine/internal/object-data/mana-bonus.d.ts +2 -0
  25. package/engine/internal/object-data/mana-bonus.lua +16 -0
  26. package/engine/internal/unit/bonus.d.ts +4 -0
  27. package/engine/internal/unit/bonus.lua +23 -3
  28. package/engine/internal/unit/range-event.d.ts +12 -0
  29. package/engine/internal/unit/range-event.lua +90 -0
  30. package/engine/internal/unit+bonus.lua +3 -3
  31. package/engine/internal/unit.d.ts +1 -1
  32. package/engine/internal/unit.lua +25 -38
  33. package/engine/local-client.d.ts +5 -0
  34. package/engine/local-client.lua +56 -1
  35. package/engine/object-data/auxiliary/unit-attribute.lua +1 -1
  36. package/engine/object-data/entry/ability-type/{armor-increase.d.ts → armor-bonus.d.ts} +3 -3
  37. package/engine/object-data/entry/ability-type/{armor-increase.lua → armor-bonus.lua} +9 -9
  38. package/engine/object-data/entry/ability-type/health-bonus.d.ts +8 -0
  39. package/engine/object-data/entry/ability-type/health-bonus.lua +26 -0
  40. package/engine/object-data/entry/ability-type/mana-bonus.d.ts +8 -0
  41. package/engine/object-data/entry/ability-type/mana-bonus.lua +26 -0
  42. package/engine/object-data/entry/ability-type/reincarnation.d.ts +8 -0
  43. package/engine/object-data/entry/ability-type/reincarnation.lua +26 -0
  44. package/engine/object-data/entry/ability-type.d.ts +2 -0
  45. package/engine/object-data/entry/ability-type.lua +84 -4
  46. package/engine/object-data/entry/buff-type/applicable.lua +113 -109
  47. package/engine/object-field/ability.lua +2 -2
  48. package/engine/object-field/item.d.ts +22 -0
  49. package/engine/object-field/item.lua +118 -0
  50. package/engine/object-field.d.ts +1 -1
  51. package/engine/object-field.lua +9 -7
  52. package/engine/random.d.ts +1 -0
  53. package/engine/random.lua +8 -0
  54. package/engine/standard/fields/item.d.ts +4 -0
  55. package/engine/standard/fields/item.lua +6 -0
  56. package/engine/unit.d.ts +1 -0
  57. package/engine/unit.lua +1 -0
  58. package/lualib_bundle.lua +1 -1
  59. package/math.d.ts +2 -0
  60. package/math.lua +14 -0
  61. package/network.lua +25 -1
  62. package/objutil/object.lua +1 -1
  63. package/operation.d.ts +8 -1
  64. package/operation.lua +38 -18
  65. package/package.json +4 -4
  66. package/patch-lua.lua +15 -0
  67. package/utility/linked-map.d.ts +11 -2
  68. package/utility/linked-map.lua +41 -0
  69. package/utility/linked-set.d.ts +3 -1
  70. package/utility/linked-set.lua +23 -0
  71. package/utility/random.d.ts +102 -0
  72. package/utility/random.lua +273 -0
  73. package/utility/unordered-map.d.ts +27 -0
  74. package/utility/unordered-map.lua +99 -0
  75. /package/engine/internal/object-data/{armor-increase.d.ts → armor-bonus.d.ts} +0 -0
  76. /package/engine/internal/object-data/{armor-increase.lua → armor-bonus.lua} +0 -0
  77. /package/engine/object-data/entry/ability-type/{attribute-increase.d.ts → attribute-bonus.d.ts} +0 -0
  78. /package/engine/object-data/entry/ability-type/{attribute-increase.lua → attribute-bonus.lua} +0 -0
@@ -80,6 +80,7 @@ export declare class Frame extends Handle<jframehandle> {
80
80
  get onMouseLeave(): FrameEvent;
81
81
  get onMouseUp(): FrameEvent;
82
82
  get onMouseWheel(): FrameEvent<[number]>;
83
+ private trackMouseLocally;
83
84
  get mouseEnterLocalEvent(): Event;
84
85
  get mouseLeaveLocalEvent(): Event;
85
86
  get popupMenuItemChangeEvent(): FrameEvent<[
@@ -24,11 +24,23 @@ local frameCoordinatesToWorld = ____playerCamera.frameCoordinatesToWorld
24
24
  local worldCoordinatesToFrame = ____playerCamera.worldCoordinatesToFrame
25
25
  local ____get_2Dterrain_2Dz = require("engine.internal.misc.get-terrain-z")
26
26
  local getTerrainZ = ____get_2Dterrain_2Dz.getTerrainZ
27
+ local ____lua_2Dsets = require("utility.lua-sets")
28
+ local mutableLuaSet = ____lua_2Dsets.mutableLuaSet
29
+ local ____socket = require("net.socket")
30
+ local Socket = ____socket.Socket
31
+ local ____lua_2Dmaps = require("utility.lua-maps")
32
+ local getOrPut = ____lua_2Dmaps.getOrPut
33
+ local luaMapInvert = ____lua_2Dmaps.luaMapInvert
34
+ local luaMapOf = ____lua_2Dmaps.luaMapOf
35
+ local mutableLuaMap = ____lua_2Dmaps.mutableLuaMap
27
36
  local frameClick = BlzFrameClick
28
37
  local frameGetEnable = BlzFrameGetEnable
29
38
  local frameIsVisible = BlzFrameIsVisible
30
39
  local frameSetEnable = BlzFrameSetEnable
31
40
  local frameSetScale = BlzFrameSetScale
41
+ local getHandleId = GetHandleId
42
+ local getOriginFrame = BlzGetOriginFrame
43
+ local location = Location
32
44
  local ____rawget = _G.rawget
33
45
  local rawset = _G.rawset
34
46
  local invoke = Event.invoke
@@ -130,6 +142,79 @@ do
130
142
  FramePoint.BOTTOM_RIGHT = FRAMEPOINT_BOTTOMRIGHT
131
143
  end
132
144
  local tooltipByFrame = setmetatable({}, {__mode = "k"})
145
+ local isMouseInsideLocallyByFrame = mutableLuaMap()
146
+ local mouseEnterLocalEventByFrame = mutableLuaMap()
147
+ local mouseLeaveLocalEventByFrame = mutableLuaMap()
148
+ local isLocalMouseTrackingStarted = false
149
+ --- Reused across ticks to avoid per-tick allocations: only the first `leftFrameCount` /
150
+ -- `enteredFrameCount` entries are meaningful, stale entries beyond them are never read and are
151
+ -- kept collectable by the weak values mode.
152
+ local leftFrames = setmetatable({}, {__mode = "v"})
153
+ local enteredFrames = setmetatable({}, {__mode = "v"})
154
+ --- All frames share a single poll which invokes every mouse leave event before any mouse enter
155
+ -- event within the same tick. With a poll per event, the invocation order would depend on the
156
+ -- event creation order instead, breaking listeners relying on the natural "leave the old frame,
157
+ -- then enter the new frame" order.
158
+ local function startLocalMouseTracking()
159
+ if isLocalMouseTrackingStarted then
160
+ return
161
+ end
162
+ isLocalMouseTrackingStarted = true
163
+ Timer.onPeriod[1 / 64]:addListener(function()
164
+ local leftFrameCount = 0
165
+ local enteredFrameCount = 0
166
+ for frame, wasMouseInside in pairs(isMouseInsideLocallyByFrame) do
167
+ local tooltip = tooltipByFrame[frame]
168
+ local isMouseInside = tooltip ~= nil and tooltip.visible
169
+ if isMouseInside ~= wasMouseInside then
170
+ isMouseInsideLocallyByFrame[frame] = isMouseInside
171
+ if isMouseInside then
172
+ enteredFrames[enteredFrameCount + 1] = frame
173
+ enteredFrameCount = enteredFrameCount + 1
174
+ else
175
+ leftFrames[leftFrameCount + 1] = frame
176
+ leftFrameCount = leftFrameCount + 1
177
+ end
178
+ end
179
+ end
180
+ for i = 1, leftFrameCount do
181
+ local event = mouseLeaveLocalEventByFrame[leftFrames[i]]
182
+ if event ~= nil then
183
+ Event.invoke(event)
184
+ end
185
+ end
186
+ for i = 1, enteredFrameCount do
187
+ local event = mouseEnterLocalEventByFrame[enteredFrames[i]]
188
+ if event ~= nil then
189
+ Event.invoke(event)
190
+ end
191
+ end
192
+ end)
193
+ end
194
+ local keyByAsyncInitOriginFrameType = luaMapOf(ORIGIN_FRAME_PORTRAIT_HP_TEXT, "hp", ORIGIN_FRAME_PORTRAIT_MANA_TEXT, "mana")
195
+ local asyncInitOriginFrameTypeByKey = luaMapInvert(keyByAsyncInitOriginFrameType)
196
+ local seenAsyncInitOriginFrameTypes = mutableLuaSet()
197
+ local seenAsyncInitOriginFrameTypesSocket = __TS__New(Socket)
198
+ local seenPlayersByAsyncInitOriginFrameType = mutableLuaMap()
199
+ seenAsyncInitOriginFrameTypesSocket.onMessage:addListener(function(player, key)
200
+ local asyncInitOriginFrameType = asyncInitOriginFrameTypeByKey[key]
201
+ if asyncInitOriginFrameType ~= nil then
202
+ getOrPut(seenPlayersByAsyncInitOriginFrameType, asyncInitOriginFrameType, mutableLuaSet)[player] = true
203
+ end
204
+ end)
205
+ local function haveAllPlayersSeenAsyncInitOriginFrameType(frame)
206
+ local players = seenPlayersByAsyncInitOriginFrameType[frame]
207
+ if players == nil then
208
+ return false
209
+ end
210
+ for ____, player in ipairs(Player.all) do
211
+ if player.isUser and player.isPlaying and not (players[player] ~= nil) then
212
+ return false
213
+ end
214
+ end
215
+ keyByAsyncInitOriginFrameType[frame] = nil
216
+ return true
217
+ end
133
218
  ____exports.Frame = __TS__Class()
134
219
  local Frame = ____exports.Frame
135
220
  Frame.name = "Frame"
@@ -162,6 +247,18 @@ function Frame.prototype.getEvent(self, eventType, c)
162
247
  end
163
248
  return self.events[eventId]
164
249
  end
250
+ function Frame.prototype.trackMouseLocally(self)
251
+ if not (tooltipByFrame[self] ~= nil) then
252
+ ____exports.Frame.SIMPLE_FRAME_TEST_CHILD.parent = self
253
+ local tooltip = ____exports.Frame.SIMPLE_FRAME_TEST_CHILD.parent == self and ____exports.Frame:createByType("SIMPLEFRAME", "", ____exports.Frame.CONSOLE_UI) or ____exports.Frame:createByType("FRAME", "", ____exports.Frame.GAME_UI)
254
+ ____exports.Frame.SIMPLE_FRAME_TEST_CHILD.parent = ____exports.Frame.CONSOLE_UI
255
+ self:setTooltip(tooltip)
256
+ end
257
+ if not (isMouseInsideLocallyByFrame[self] ~= nil) then
258
+ isMouseInsideLocallyByFrame[self] = false
259
+ startLocalMouseTracking()
260
+ end
261
+ end
165
262
  function Frame.prototype.hide(self)
166
263
  self.hideCounter = self.hideCounter + 1
167
264
  if self.hideCounter > 0 then
@@ -308,7 +405,17 @@ function Frame.byOrigin(self, frameType, index)
308
405
  if index == nil then
309
406
  index = 0
310
407
  end
311
- return self:of(BlzGetOriginFrame(frameType, index))
408
+ local frame = getOriginFrame(frameType, index)
409
+ local asyncInitOriginFrameTypeKey = keyByAsyncInitOriginFrameType[frameType]
410
+ if index == 0 and asyncInitOriginFrameTypeKey ~= nil and not haveAllPlayersSeenAsyncInitOriginFrameType(frameType) then
411
+ if getHandleId(frame) == 0 or seenAsyncInitOriginFrameTypes[frameType] ~= nil then
412
+ location(0, 0)
413
+ else
414
+ seenAsyncInitOriginFrameTypes[frameType] = true
415
+ seenAsyncInitOriginFrameTypesSocket:send(asyncInitOriginFrameTypeKey)
416
+ end
417
+ end
418
+ return self:of(frame)
312
419
  end
313
420
  Frame.GAME_UI = ____exports.Frame:byOrigin(ORIGIN_FRAME_GAME_UI)
314
421
  Frame.CONSOLE_UI = ____exports.Frame:byOrigin(ORIGIN_FRAME_SIMPLE_UI_PARENT)
@@ -627,24 +734,8 @@ __TS__SetDescriptor(
627
734
  "mouseEnterLocalEvent",
628
735
  {get = function(self)
629
736
  local event = __TS__New(Event)
630
- if not (tooltipByFrame[self] ~= nil) then
631
- ____exports.Frame.SIMPLE_FRAME_TEST_CHILD.parent = self
632
- local tooltip = ____exports.Frame.SIMPLE_FRAME_TEST_CHILD.parent == self and ____exports.Frame:createByType("SIMPLEFRAME", "", ____exports.Frame.CONSOLE_UI) or ____exports.Frame:createByType("FRAME", "", ____exports.Frame.GAME_UI)
633
- ____exports.Frame.SIMPLE_FRAME_TEST_CHILD.parent = ____exports.Frame.CONSOLE_UI
634
- self:setTooltip(tooltip)
635
- end
636
- local isMouseInside = false
637
- Timer.onPeriod[1 / 64]:addListener(function()
638
- local tooltip = tooltipByFrame[self]
639
- if tooltip and tooltip.visible then
640
- if not isMouseInside then
641
- isMouseInside = true
642
- Event.invoke(event)
643
- end
644
- else
645
- isMouseInside = false
646
- end
647
- end)
737
+ self:trackMouseLocally()
738
+ mouseEnterLocalEventByFrame[self] = event
648
739
  rawset(self, "mouseEnterLocalEvent", event)
649
740
  return event
650
741
  end},
@@ -655,24 +746,8 @@ __TS__SetDescriptor(
655
746
  "mouseLeaveLocalEvent",
656
747
  {get = function(self)
657
748
  local event = __TS__New(Event)
658
- if not (tooltipByFrame[self] ~= nil) then
659
- ____exports.Frame.SIMPLE_FRAME_TEST_CHILD.parent = self
660
- local tooltip = ____exports.Frame.SIMPLE_FRAME_TEST_CHILD.parent == self and ____exports.Frame:createByType("SIMPLEFRAME", "", ____exports.Frame.CONSOLE_UI) or ____exports.Frame:createByType("FRAME", "", ____exports.Frame.GAME_UI)
661
- ____exports.Frame.SIMPLE_FRAME_TEST_CHILD.parent = ____exports.Frame.CONSOLE_UI
662
- self:setTooltip(tooltip)
663
- end
664
- local isMouseInside = false
665
- Timer.onPeriod[1 / 64]:addListener(function()
666
- local tooltip = tooltipByFrame[self]
667
- if tooltip and tooltip.visible then
668
- isMouseInside = true
669
- else
670
- if isMouseInside then
671
- isMouseInside = false
672
- Event.invoke(event)
673
- end
674
- end
675
- end)
749
+ self:trackMouseLocally()
750
+ mouseLeaveLocalEventByFrame[self] = event
676
751
  rawset(self, "mouseLeaveLocalEvent", event)
677
752
  return event
678
753
  end},
@@ -15,6 +15,8 @@ local ____exception = require("exception")
15
15
  local IllegalStateException = ____exception.IllegalStateException
16
16
  local ____attributes = require("attributes")
17
17
  local AttributesHolder = ____attributes.AttributesHolder
18
+ local ____preconditions = require("utility.preconditions")
19
+ local checkNotNull = ____preconditions.checkNotNull
18
20
  local getHandleId = GetHandleId
19
21
  local onCreateEventByHandleConstructor = {}
20
22
  local onDestroyEventByHandleConstructor = {}
@@ -66,17 +68,12 @@ function Handle.prototype.onDestroy(self, ...)
66
68
  return nil
67
69
  end
68
70
  function Handle.prototype.destroy(self, ...)
71
+ if self[0] == 2 or self[0] == 3 then
72
+ return nil
73
+ end
69
74
  local clazz = self.constructor
70
75
  local id = getHandleId(self.handle)
71
- if not clazz.memoized[id] then
72
- error(
73
- __TS__New(
74
- IllegalStateException,
75
- "Double-destroy run for handle " .. tostring(id)
76
- ),
77
- 0
78
- )
79
- end
76
+ checkNotNull(clazz.memoized[id])
80
77
  self[0] = 2
81
78
  if self.onDestroyEvent then
82
79
  Event.invoke(self.onDestroyEvent)
@@ -1,4 +1,5 @@
1
1
  /** @noSelfInFile */
2
2
  import { Item } from "../../engine/internal/item";
3
3
  import "../../engine/internal/item+owner";
4
+ import "../../engine/internal/item/fields";
4
5
  export { Item };
@@ -2,5 +2,6 @@ local ____exports = {}
2
2
  local ____item = require("engine.internal.item")
3
3
  local Item = ____item.Item
4
4
  require("engine.internal.item+owner")
5
+ require("engine.internal.item.fields")
5
6
  ____exports.Item = Item
6
7
  return ____exports
@@ -28,6 +28,7 @@ export declare class Player extends Handle<jplayer> {
28
28
  static readonly neutralExtra: Player;
29
29
  private static events;
30
30
  readonly id: number;
31
+ readonly slotState: jplayerslotstate;
31
32
  constructor(handle: jplayer);
32
33
  onDestroy(): HandleDestructor;
33
34
  toString(): string;
@@ -45,7 +46,6 @@ export declare class Player extends Handle<jplayer> {
45
46
  get isUser(): boolean;
46
47
  get isPlaying(): boolean;
47
48
  get controller(): jmapcontrol;
48
- get slotState(): jplayerslotstate;
49
49
  clearSelection(): void;
50
50
  selectSingle(unit: Unit): void;
51
51
  select(unit: Unit): void;
@@ -56,6 +56,7 @@ Player.name = "Player"
56
56
  __TS__ClassExtends(Player, Handle)
57
57
  function Player.prototype.____constructor(self, handle)
58
58
  Handle.prototype.____constructor(self, handle)
59
+ self.slotState = GetPlayerSlotState(self.handle)
59
60
  self.id = GetPlayerId(handle)
60
61
  end
61
62
  function Player.prototype.onDestroy(self)
@@ -364,7 +365,7 @@ __TS__SetDescriptor(
364
365
  Player.prototype,
365
366
  "isUser",
366
367
  {get = function(self)
367
- return GetPlayerController(self.handle) == MAP_CONTROL_USER
368
+ return self.controller == MAP_CONTROL_USER
368
369
  end},
369
370
  true
370
371
  )
@@ -372,7 +373,7 @@ __TS__SetDescriptor(
372
373
  Player.prototype,
373
374
  "isPlaying",
374
375
  {get = function(self)
375
- return GetPlayerSlotState(self.handle) == PLAYER_SLOT_STATE_PLAYING
376
+ return self.slotState == PLAYER_SLOT_STATE_PLAYING
376
377
  end},
377
378
  true
378
379
  )
@@ -380,15 +381,9 @@ __TS__SetDescriptor(
380
381
  Player.prototype,
381
382
  "controller",
382
383
  {get = function(self)
383
- return GetPlayerController(self.handle)
384
- end},
385
- true
386
- )
387
- __TS__SetDescriptor(
388
- Player.prototype,
389
- "slotState",
390
- {get = function(self)
391
- return GetPlayerSlotState(self.handle)
384
+ local controller = GetPlayerController(self.handle)
385
+ rawset(self, "controller", controller)
386
+ return controller
392
387
  end},
393
388
  true
394
389
  )
@@ -490,4 +485,10 @@ __TS__ObjectDefineProperty(
490
485
  end}
491
486
  )
492
487
  Player.colorChangedEvent = playerColorChangedEvent
488
+ ____exports.Player.onLeave:addListener(
489
+ 999999,
490
+ function(player)
491
+ rawset(player, "slotState", PLAYER_SLOT_STATE_LEFT)
492
+ end
493
+ )
493
494
  return ____exports
@@ -22,7 +22,7 @@ local setSoundPlayPosition = SetSoundPlayPosition
22
22
  local stopSound = StopSound
23
23
  local attachSoundToUnit = AttachSoundToUnit
24
24
  local killSoundWhenDone = KillSoundWhenDone
25
- ____exports.SoundChannel = SoundChannel or ({})
25
+ ____exports.SoundChannel = ____exports.SoundChannel or ({})
26
26
  ____exports.SoundChannel.General = 0
27
27
  ____exports.SoundChannel[____exports.SoundChannel.General] = "General"
28
28
  ____exports.SoundChannel.UnitSelection = 1
@@ -25,8 +25,11 @@ export declare abstract class DamageAbilityBehavior<T extends DamageAbilityBehav
25
25
  protected readonly damage: AbilityDependentValue<number>;
26
26
  protected readonly parameters?: T | undefined;
27
27
  protected constructor(ability: Ability, damage: AbilityDependentValue<number>, parameters?: T | undefined);
28
+ protected precalculatedDamage?: number;
28
29
  protected calculateDamage(caster: Unit): number;
29
30
  protected damageTarget(caster: Unit, target: Widget, damage?: number): void;
31
+ onChannelingStart(caster: Unit): void;
32
+ onStop(): void;
30
33
  }
31
34
  export declare class DamageSelfAbilityBehavior extends DamageAbilityBehavior {
32
35
  constructor(ability: Ability, damage: AbilityDependentValue<number>, parameters?: DamageAbilityBehaviorParameters);
@@ -39,7 +39,7 @@ function DamageAbilityBehavior.prototype.damageTarget(self, caster, target, dama
39
39
  local parameters = self.parameters
40
40
  caster:damageTarget(
41
41
  target,
42
- damage or self:calculateDamage(caster),
42
+ damage or self.precalculatedDamage or self:calculateDamage(caster),
43
43
  nil,
44
44
  nil,
45
45
  self:resolveCurrentAbilityDependentValue(parameters and parameters.attackType),
@@ -48,6 +48,12 @@ function DamageAbilityBehavior.prototype.damageTarget(self, caster, target, dama
48
48
  self:resolveCurrentAbilityDependentValue(parameters and parameters.metadata)
49
49
  )
50
50
  end
51
+ function DamageAbilityBehavior.prototype.onChannelingStart(self, caster)
52
+ self.precalculatedDamage = self:calculateDamage(caster)
53
+ end
54
+ function DamageAbilityBehavior.prototype.onStop(self)
55
+ self.precalculatedDamage = nil
56
+ end
51
57
  ____exports.DamageSelfAbilityBehavior = __TS__Class()
52
58
  local DamageSelfAbilityBehavior = ____exports.DamageSelfAbilityBehavior
53
59
  DamageSelfAbilityBehavior.name = "DamageSelfAbilityBehavior"
@@ -83,7 +89,7 @@ function DamageAreaAbilityBehavior.prototype.damageArea(self, caster, x, y)
83
89
  y,
84
90
  self:resolveCurrentAbilityDependentValue(parameters and parameters.areaOfEffect or AREA_OF_EFFECT_ABILITY_FLOAT_LEVEL_FIELD)
85
91
  )
86
- local damage = self:calculateDamage(caster)
92
+ local damage = self.precalculatedDamage or self:calculateDamage(caster)
87
93
  local maximumDamage = self:resolveCurrentAbilityDependentValue(parameters and parameters.maximumDamage or 0)
88
94
  if maximumDamage ~= 0 and damage > maximumDamage then
89
95
  damage = maximumDamage / #targets
@@ -10,9 +10,6 @@ local Unit = ____unit.Unit
10
10
  local ____ability = require("engine.standard.fields.ability")
11
11
  local COOLDOWN_ABILITY_FLOAT_LEVEL_FIELD = ____ability.COOLDOWN_ABILITY_FLOAT_LEVEL_FIELD
12
12
  local MANA_COST_ABILITY_INTEGER_LEVEL_FIELD = ____ability.MANA_COST_ABILITY_INTEGER_LEVEL_FIELD
13
- local ____math = require("math")
14
- local max = ____math.max
15
- local MINIMUM_POSITIVE_NORMALIZED_FLOAT = ____math.MINIMUM_POSITIVE_NORMALIZED_FLOAT
16
13
  local ____sound = require("core.types.sound")
17
14
  local Sound3D = ____sound.Sound3D
18
15
  local SoundSettings = ____sound.SoundSettings
@@ -31,7 +28,11 @@ function EmulateImpactAbilityBehavior.prototype.emulateImpact(self, caster)
31
28
  return false
32
29
  end
33
30
  caster.mana = caster.mana - manaCost
34
- self.ability.cooldownRemaining = max(cooldown, MINIMUM_POSITIVE_NORMALIZED_FLOAT)
31
+ if cooldown == 0 then
32
+ self.ability:interruptCast()
33
+ else
34
+ self.ability.cooldownRemaining = cooldown
35
+ end
35
36
  self:flashCasterEffect(caster)
36
37
  local soundPresetId = self.ability:getField(ABILITY_SF_EFFECT_SOUND)
37
38
  if soundPresetId ~= "" then
@@ -26,16 +26,20 @@ export declare abstract class AbilityBehavior<Parameters extends {
26
26
  get unit(): Unit | undefined;
27
27
  protected resolveCurrentAbilityDependentValue<T extends boolean | number | string>(value: AbilityDependentValue<T>): T;
28
28
  protected resolveCurrentAbilityDependentValue<T extends boolean | number | string>(value?: AbilityDependentValue<T>): T | undefined;
29
- protected flashCasterEffect(widget: Widget, ...parametersOrDuration: [parameters?: EffectParameters] | [duration?: number, parameters?: EffectParameters]): void;
30
- protected flashTargetEffect(widget: Widget, ...parametersOrDuration: [parameters?: EffectParameters] | [duration?: number, parameters?: EffectParameters]): void;
31
- protected flashAreaEffect(x: number, y: number, ...parametersOrDuration: [parameters?: EffectParameters] | [duration?: number, parameters?: EffectParameters]): void;
32
- protected flashEffect(x: number, y: number, ...parametersOrDuration: [parameters?: EffectParameters] | [duration?: number, parameters?: EffectParameters]): void;
33
- protected flashSpecialEffect(...args: [
29
+ flashCasterEffect(widget: Widget, ...parametersOrDuration: [parameters?: EffectParameters] | [duration?: number, parameters?: EffectParameters]): void;
30
+ flashTargetEffect(widget: Widget, ...parametersOrDuration: [parameters?: EffectParameters] | [duration?: number, parameters?: EffectParameters]): void;
31
+ flashAreaEffect(x: number, y: number, ...parametersOrDuration: [parameters?: EffectParameters] | [duration?: number, parameters?: EffectParameters]): void;
32
+ flashEffect(x: number, y: number, ...parametersOrDuration: [parameters?: EffectParameters] | [duration?: number, parameters?: EffectParameters]): void;
33
+ flashSpecialEffect(...args: [
34
34
  ...pointOrWidget: [x: number, y: number] | [widget: Widget],
35
35
  ...parametersOrDuration: [parameters?: EffectParameters] | [duration?: number, parameters?: EffectParameters]
36
36
  ]): void;
37
37
  private static MissileLaunchConfig;
38
38
  private get missileLaunchConfig();
39
+ protected launchMissile(source: Unit, ...args: [
40
+ ...pointOrWidget: [x: number, y: number] | [widget: Unit /** TODO: support Widget */],
41
+ ...parameters: NonNullable<Parameters["missileParameters"]>
42
+ ]): void;
39
43
  protected onCreate(): void;
40
44
  onValueChange(_value: ReadonlySubscribableAbilityDependentValue<string | number | boolean>): void;
41
45
  onMissileArrival(...parameters: NonNullable<Parameters["missileParameters"]>): void;
@@ -30,7 +30,14 @@ local ____ability = require("engine.object-field.ability")
30
30
  local AbilityField = ____ability.AbilityField
31
31
  local AbilityLevelField = ____ability.AbilityLevelField
32
32
  local resolveCurrentAbilityDependentValue = ____ability.resolveCurrentAbilityDependentValue
33
+ local ____missile = require("core.types.missile")
34
+ local Missile = ____missile.Missile
33
35
  local createBehaviorFunctionsByAbilityTypeId = {}
36
+ local function invokeOnMissileArrival(_missile, success, abilityBehavior, ...)
37
+ if success then
38
+ abilityBehavior:onMissileArrival(...)
39
+ end
40
+ end
34
41
  local exclusiveOnImpactHandlerAbilityBehaviorByAbility = setmetatable({}, {__mode = "k"})
35
42
  local function createUnitEventListener(key)
36
43
  return function(unit, ability, ...)
@@ -160,6 +167,28 @@ function AbilityBehavior.prototype.flashSpecialEffect(self, xOrWidget, yOrParame
160
167
  )
161
168
  end
162
169
  end
170
+ function AbilityBehavior.prototype.launchMissile(self, source, xOrWidget, yOrParameter, ...)
171
+ if type(xOrWidget) ~= "number" then
172
+ Missile:launch(
173
+ self.missileLaunchConfig,
174
+ source,
175
+ xOrWidget,
176
+ invokeOnMissileArrival,
177
+ self,
178
+ yOrParameter,
179
+ ...
180
+ )
181
+ else
182
+ Missile:launch(
183
+ self.missileLaunchConfig,
184
+ source,
185
+ vec2(xOrWidget, yOrParameter),
186
+ invokeOnMissileArrival,
187
+ self,
188
+ ...
189
+ )
190
+ end
191
+ end
163
192
  function AbilityBehavior.prototype.onCreate(self)
164
193
  end
165
194
  function AbilityBehavior.prototype.onValueChange(self, _value)
package/engine/buff.d.ts CHANGED
@@ -56,7 +56,8 @@ export type BuffParameters<T extends Buff<any> = Buff> = Buff extends T ? {
56
56
  damageIncrease?: NumberParameterValueType;
57
57
  damageIncreaseFactor?: NumberParameterValueType;
58
58
  armorIncrease?: NumberParameterValueType;
59
- armorIncreaseFactor?: NumberParameterValueType;
59
+ maxHealthIncrease?: NumberParameterValueType;
60
+ maxManaIncrease?: NumberParameterValueType;
60
61
  attackSpeedIncreaseFactor?: NumberParameterValueType;
61
62
  movementSpeedIncreaseFactor?: NumberParameterValueType;
62
63
  manaRegenerationRateIncreaseFactor?: NumberParameterValueType;
@@ -79,6 +80,9 @@ export type BuffParameters<T extends Buff<any> = Buff> = Buff extends T ? {
79
80
  maximumAutoAttackCount?: IntegerParameterValueType;
80
81
  maximumDamageDealtEventCount?: IntegerParameterValueType;
81
82
  maximumDamageReceivedEventCount?: IntegerParameterValueType;
83
+ absorbedDamageFactor?: NumberParameterValueType;
84
+ maximumDamageAbsorbed?: NumberParameterValueType;
85
+ destroysOnMaximumDamageAbsorbed?: BooleanParameterValueType;
82
86
  damageOnExpiration?: NumberParameterValueType;
83
87
  healingOnExpiration?: NumberParameterValueType;
84
88
  killsOnExpiration?: BooleanParameterValueType;
@@ -122,22 +126,26 @@ declare const enum BuffPropertyKey {
122
126
  MAXIMUM_DAMAGE_DEALT_EVENT_COUNT = 132,
123
127
  DAMAGE_RECEIVED_EVENT_COUNT = 133,
124
128
  MAXIMUM_DAMAGE_RECEIVED_EVENT_COUNT = 134,
125
- TURNS_INTO_GHOST = 135,
126
- STUNS = 136,
127
- IGNORES_STUN_IMMUNITY = 137,
128
- DISABLES_AUTO_ATTACK = 138,
129
- PROVIDES_INVULNERABILITY = 139,
130
- KILLS_ON_EXPIRATION = 140,
131
- EXPLODES_ON_EXPIRATION = 141,
132
- MISS_PROBABILITY = 142,
133
- ABILITY_COOLDOWN_FACTOR = 143,
134
- ABILITY_COOLDOWN_MODIFIER = 144
129
+ ABSORBED_DAMAGE_FACTOR = 135,
130
+ MAXIMUM_DAMAGE_ABSORBED = 136,
131
+ DAMAGE_ABSORBED = 137,
132
+ DESTROYS_ON_MAXIMUM_DAMAGE_ABSORBED = 138,
133
+ TURNS_INTO_GHOST = 139,
134
+ STUNS = 140,
135
+ IGNORES_STUN_IMMUNITY = 141,
136
+ DISABLES_AUTO_ATTACK = 142,
137
+ PROVIDES_INVULNERABILITY = 143,
138
+ KILLS_ON_EXPIRATION = 144,
139
+ EXPLODES_ON_EXPIRATION = 145,
140
+ MISS_PROBABILITY = 146,
141
+ ABILITY_COOLDOWN_FACTOR = 147,
142
+ ABILITY_COOLDOWN_MODIFIER = 148
135
143
  }
136
144
  export declare const enum BuffTypeIdSelectionPolicy {
137
145
  LEAST_DURATION = 0
138
146
  }
139
147
  export type BuffAdditionalParameters = Prohibit<Record<string, any>, keyof BuffParameters>;
140
- export type BuffConstructorParameters<AdditionalParameters extends BuffAdditionalParameters> = [
148
+ export type BuffConstructorParameters<T extends Buff<BuffAdditionalParameters>> = T extends Buff<infer AdditionalParameters> ? [
141
149
  ...typeId: [ApplicableBuffTypeId] | [
142
150
  typeIds: ReadonlyNonEmptyArray<ApplicableBuffTypeId>,
143
151
  typeIdSelectionPolicy: BuffTypeIdSelectionPolicy
@@ -147,8 +155,10 @@ export type BuffConstructorParameters<AdditionalParameters extends BuffAdditiona
147
155
  ...abilityOrParameters: [
148
156
  ability?: Ability | AbilityBehavior,
149
157
  parameters?: BuffParameters & Omit<AdditionalParameters, keyof BuffParameters>
150
- ] | [parameters?: BuffParameters & Omit<AdditionalParameters, keyof BuffParameters>]
151
- ];
158
+ ] | [
159
+ parameters?: BuffParameters & Omit<AdditionalParameters, keyof BuffParameters>
160
+ ]
161
+ ] : never;
152
162
  export declare class Buff<AdditionalParameters extends Prohibit<Record<string, any>, keyof BuffParameters> = object> extends UnitBehavior {
153
163
  private _unit;
154
164
  protected readonly __additionalParametersBrand?: AdditionalParameters;
@@ -187,6 +197,10 @@ export declare class Buff<AdditionalParameters extends Prohibit<Record<string, a
187
197
  private [BuffPropertyKey.DAMAGE_DEALT_EVENT_COUNT]?;
188
198
  private [BuffPropertyKey.MAXIMUM_DAMAGE_RECEIVED_EVENT_COUNT]?;
189
199
  private [BuffPropertyKey.DAMAGE_RECEIVED_EVENT_COUNT]?;
200
+ private [BuffPropertyKey.ABSORBED_DAMAGE_FACTOR]?;
201
+ private [BuffPropertyKey.MAXIMUM_DAMAGE_ABSORBED]?;
202
+ private [BuffPropertyKey.DAMAGE_ABSORBED]?;
203
+ private [BuffPropertyKey.DESTROYS_ON_MAXIMUM_DAMAGE_ABSORBED]?;
190
204
  private [BuffPropertyKey.TURNS_INTO_GHOST]?;
191
205
  private [BuffPropertyKey.STUNS]?;
192
206
  private [BuffPropertyKey.IGNORES_STUN_IMMUNITY]?;
@@ -201,10 +215,11 @@ export declare class Buff<AdditionalParameters extends Prohibit<Record<string, a
201
215
  readonly typeId: ApplicableBuffTypeId;
202
216
  readonly polarity: BuffPolarity;
203
217
  readonly resistanceType: BuffResistanceType;
204
- readonly parameters: IsExactlyAny<AdditionalParameters> extends true ? any : keyof AdditionalParameters extends never ? undefined : {
218
+ readonly parameters: IsExactlyAny<AdditionalParameters> extends true ? any : AdditionalParameters extends Record<PropertyKey, never> ? undefined : {
205
219
  [K in keyof Omit<AdditionalParameters, keyof BuffParameters>]: AdditionalParameters[K] extends AbilityDependentValue<infer T> ? T : AdditionalParameters[K];
206
220
  };
207
221
  private readonly handle;
222
+ readonly previousBuff?: Buff;
208
223
  private _timer?;
209
224
  private readonly _level?;
210
225
  private readonly _spellStealPriority?;
@@ -212,7 +227,7 @@ export declare class Buff<AdditionalParameters extends Prohibit<Record<string, a
212
227
  private readonly [BuffPropertyKey.MISS_PROBABILITY]?;
213
228
  private readonly _abilityTypeIds?;
214
229
  private _behaviors?;
215
- constructor(target: Unit, ...parameters: BuffConstructorParameters<AdditionalParameters>);
230
+ constructor(target: Unit, ...parameters: BuffConstructorParameters<Buff<AdditionalParameters>>);
216
231
  get level(): number;
217
232
  get remainingDamageOverDuration(): number;
218
233
  set remainingDamageOverDuration(remainingDamageOverDuration: number);
@@ -240,6 +255,10 @@ export declare class Buff<AdditionalParameters extends Prohibit<Record<string, a
240
255
  set receivedDamageFactor(receivedDamageFactor: number);
241
256
  get armorIncrease(): number;
242
257
  set armorIncrease(armorIncrease: number);
258
+ get maxHealthIncrease(): number;
259
+ set maxHealthIncrease(maxHealthIncrease: number);
260
+ get maxManaIncrease(): number;
261
+ set maxManaIncrease(maxManaIncrease: number);
243
262
  get turnsIntoGhost(): boolean;
244
263
  set turnsIntoGhost(turnsIntoGhost: boolean);
245
264
  get stuns(): boolean;
@@ -271,8 +290,16 @@ export declare class Buff<AdditionalParameters extends Prohibit<Record<string, a
271
290
  get manaRegenerationRateIncreaseFactor(): number;
272
291
  set manaRegenerationRateIncreaseFactor(manaRegenerationRateIncreaseFactor: number);
273
292
  get duration(): number;
293
+ set duration(duration: number);
274
294
  get remainingDuration(): number;
275
295
  set remainingDuration(remainingDuration: number);
296
+ get absorbedDamageFactor(): number;
297
+ set absorbedDamageFactor(absorbedDamageFactor: number);
298
+ get maximumDamageAbsorbed(): number;
299
+ set maximumDamageAbsorbed(maximumDamageAbsorbed: number);
300
+ get damageAbsorbed(): number;
301
+ get destroysOnMaximumDamageAbsorbed(): boolean;
302
+ set destroysOnMaximumDamageAbsorbed(destroysOnMaximumDamageAbsorbed: boolean);
276
303
  get abilityCooldownFactor(): number;
277
304
  set abilityCooldownFactor(abilityCooldownFactor: number);
278
305
  onAbilityGained(ability: Ability): void;
@@ -281,7 +308,12 @@ export declare class Buff<AdditionalParameters extends Prohibit<Record<string, a
281
308
  ...widgetOrXY: [] | [Widget] | [x: number, x: number],
282
309
  ...parametersOrDuration: [] | [EffectParameters] | [number]
283
310
  ]): void;
284
- flashSpecialEffect(...parameters: [...widget: [] | [Widget], ...duration: [] | [number]]): void;
311
+ flashSpecialEffect(...parameters: [
312
+ ...widgetOrXY: [] | [Widget] | [x: number, x: number],
313
+ ...parametersOrDuration: [] | [EffectParameters] | [number]
314
+ ]): void;
315
+ private flash;
316
+ expire(): void;
285
317
  protected onCreate(): void;
286
318
  protected onDestroy(): Destructor;
287
319
  static apply<T extends Buff<any>, Args extends any[]>(this: BuffConstructor<T, Args>, ...args: Args): T | undefined;