Module: Api::UnitExtension

Included in:
Unit
Defined in:
lib/sc2ai/protocol/extensions/unit.rb

Overview

Adds additional functionality to message object Api::Unit Mostly adds convenience methods by adding direct access to the Sc2::Bot data and api

Virtual properties collapse

Instance Attribute Summary collapse

Actions collapse

Instance Method Summary collapse

Instance Attribute Details

#botSc2::Player

Every unit gets access back to the bot to allow api access. For your own units, this allows API access.

Returns:



15
16
17
# File 'lib/sc2ai/protocol/extensions/unit.rb', line 15

def bot
  @bot
end

#is_active?Boolean (readonly)

Returns:

  • (Boolean)


175
# File 'lib/sc2ai/protocol/extensions/unit.rb', line 175

def is_active? = is_active

#is_blip?Boolean (readonly)

Returns:

  • (Boolean)


167
# File 'lib/sc2ai/protocol/extensions/unit.rb', line 167

def is_blip? = is_blip

#is_burrowed?Boolean (readonly)

Returns:

  • (Boolean)


151
# File 'lib/sc2ai/protocol/extensions/unit.rb', line 151

def is_burrowed? = is_burrowed

#is_flying?Boolean (readonly)

Returns:

  • (Boolean)


147
# File 'lib/sc2ai/protocol/extensions/unit.rb', line 147

def is_flying? = is_flying

#is_ground?Boolean (readonly)

Returns whether the unit is grounded (not flying).

Returns:

  • (Boolean)


180
# File 'lib/sc2ai/protocol/extensions/unit.rb', line 180

def is_ground? = !is_flying?

#is_hallucination?Boolean (readonly)

Returns:

  • (Boolean)


155
# File 'lib/sc2ai/protocol/extensions/unit.rb', line 155

def is_hallucination? = is_hallucination

#is_on_screen?Boolean (readonly)

Returns:

  • (Boolean)


163
# File 'lib/sc2ai/protocol/extensions/unit.rb', line 163

def is_on_screen? = is_on_screen

#is_powered?Boolean (readonly)

Returns:

  • (Boolean)


171
# File 'lib/sc2ai/protocol/extensions/unit.rb', line 171

def is_powered? = is_powered

#is_selected?Boolean (readonly)

Returns:

  • (Boolean)


159
# File 'lib/sc2ai/protocol/extensions/unit.rb', line 159

def is_selected? = is_selected

#widthFloat

width = radius * 2

Returns:

  • (Float)


136
137
138
139
140
141
# File 'lib/sc2ai/protocol/extensions/unit.rb', line 136

def width = radius * 2
# @!parse
#   # @!attribute width
#   # width = radius * 2
#   # @return [Float]
#   attr_reader :width

Instance Method Details

#ability_available?(ability_id) ⇒ Boolean

Returns whether this unit has an ability available Queries API if necessary

Parameters:

  • ability_id (Integer)

Returns:

  • (Boolean)


439
440
441
# File 'lib/sc2ai/protocol/extensions/unit.rb', line 439

def ability_available?(ability_id)
  @bot.unit_ability_available?(unit_tag: tag, ability_id:)
end

#action(ability_id:, target: nil, queue_command: false) ⇒ Object

Performs action on this unit

Parameters:

  • ability_id (Integer)
  • target (Api::Unit, Integer, Api::Point2D) (defaults to: nil)

    is a unit, unit tag or a Api::Point2D

  • queue_command (Boolean) (defaults to: false)

    shift+command



199
200
201
# File 'lib/sc2ai/protocol/extensions/unit.rb', line 199

def action(ability_id:, target: nil, queue_command: false)
  @bot.action(units: self, ability_id:, target:, queue_command:)
end

#add_onApi::Unit?

Returns the Api::Unit add-on (Reactor/Tech Lab), if present for this structure

Returns:

  • (Api::Unit, nil)

    the unit if an addon is present or nil if not present



519
520
521
# File 'lib/sc2ai/protocol/extensions/unit.rb', line 519

def add_on
  @add_on ||= @bot.structures[add_on_tag]
end

#attack(target:, queue_command: false) ⇒ Object

Shorthand for performing action ATTACK

Parameters:

  • target (Api::Unit, Integer, Api::Point2D)

    is a unit, unit tag or a Api::Point2D

  • queue_command (Boolean) (defaults to: false)

    shift+command



233
234
235
236
# File 'lib/sc2ai/protocol/extensions/unit.rb', line 233

def attack(target:, queue_command: false)
  return false if target.nil?
  action(ability_id: Api::AbilityId::ATTACK, target:, queue_command:)
end

#attack_with(units:, queue_command: false) ⇒ void

This method returns an undefined value.

Inverse of #attack, where you target self using another unit (source_unit)

Parameters:

  • units (Api::Unit, Sc2::UnitGroup)

    a unit or unit group

  • queue_command (Boolean) (defaults to: false)

    shift+command



242
243
244
245
246
# File 'lib/sc2ai/protocol/extensions/unit.rb', line 242

def attack_with(units:, queue_command: false)
  return unless units.is_a?(Api::Unit) || units.is_a?(Sc2::UnitGroup)

  units.attack(target: self, queue_command:)
end

#attributesArray<Api::Attribute>

Returns static [Api::UnitTypeData] for a unit

Returns:



53
54
55
# File 'lib/sc2ai/protocol/extensions/unit.rb', line 53

def attributes
  unit_data.attributes
end

#build(unit_type_id:, target: nil, queue_command: false) ⇒ Object Also known as: train

Builds target unit type, i.e. issuing a build command to worker.build(…Api::UnitTypeId::BARRACKS)

Parameters:

  • unit_type_id (Integer)

    Api::UnitTypeId the unit type you wish to build

  • target (Api::Point2D, Api::Unit, Integer, nil) (defaults to: nil)

    is a unit tag or a Api::Point2D. Nil for addons/orbital

  • queue_command (Boolean) (defaults to: false)

    shift+command



252
253
254
# File 'lib/sc2ai/protocol/extensions/unit.rb', line 252

def build(unit_type_id:, target: nil, queue_command: false)
  @bot.build(units: self, unit_type_id:, target:, queue_command:)
end

#build_reactor(queue_command: false) ⇒ void

This method returns an undefined value.

For Terran builds a tech lab add-on on the current structure



542
543
544
545
546
547
548
549
550
551
552
553
# File 'lib/sc2ai/protocol/extensions/unit.rb', line 542

def build_reactor(queue_command: false)
  unit_type_id = case unit_type
  when Api::UnitTypeId::BARRACKS, Api::UnitTypeId::BARRACKSFLYING
    Api::UnitTypeId::BARRACKSREACTOR
  when Api::UnitTypeId::FACTORY, Api::UnitTypeId::FACTORYFLYING
    Api::UnitTypeId::FACTORYREACTOR
  when Api::UnitTypeId::STARPORT, Api::UnitTypeId::STARPORTFLYING
    Api::UnitTypeId::STARPORTREACTOR
  end

  build(unit_type_id: unit_type_id, target: target_for_addon_placement, queue_command:)
end

#build_tech_lab(queue_command: false) ⇒ void

This method returns an undefined value.

For Terran builds a tech lab add-on on the current structure



557
558
559
560
561
562
563
564
565
566
567
# File 'lib/sc2ai/protocol/extensions/unit.rb', line 557

def build_tech_lab(queue_command: false)
  unit_type_id = case unit_type
  when Api::UnitTypeId::BARRACKS, Api::UnitTypeId::BARRACKSFLYING
    Api::UnitTypeId::BARRACKSTECHLAB
  when Api::UnitTypeId::FACTORY, Api::UnitTypeId::FACTORYFLYING
    Api::UnitTypeId::FACTORYTECHLAB
  when Api::UnitTypeId::STARPORT, Api::UnitTypeId::STARPORTFLYING
    Api::UnitTypeId::STARPORTTECHLAB
  end
  build(unit_type_id: unit_type_id, target: target_for_addon_placement, queue_command:)
end

#can_ability_target_unit?(unit:, ability:) ⇒ Boolean

Returns:

  • (Boolean)


458
459
460
461
462
463
464
# File 'lib/sc2ai/protocol/extensions/unit.rb', line 458

def can_ability_target_unit?(unit:, ability:)
  # false if enemy is air and we can only shoot ground
  return false if ability.target == Api::AbilityData::Target::NONE

  # Check if weapon and unit models are in range
  in_attack_range?(unit:, range: ability.cast_range)
end

#can_attack?(unit:, weapon_index: 0, ability_id: nil) ⇒ Boolean

Checks whether enemy is within range of weapon or ability and can target ground/air. Defaults to basic weapon. Pass in ability to override

Examples:

ghost.can_attack?(enemy, weapon_index: 0, ability_id: Api::AbilityId::SNIPE)

Parameters:

  • unit (Api::Unit)

    enemy

  • weapon_index (Integer) (defaults to: 0)

    defaults to 0 which is it’s basic weapon for it’s current form

  • ability_id (Integer) (defaults to: nil)

    passing this will override weapon Api::AbilityId::*

Returns:

  • (Boolean)


423
424
425
426
427
428
429
430
431
432
433
# File 'lib/sc2ai/protocol/extensions/unit.rb', line 423

def can_attack?(unit:, weapon_index: 0, ability_id: nil)
  if ability_id.nil?
    # weapon
    source_weapon = weapon(weapon_index)
    can_weapon_target_unit?(unit:, weapon: source_weapon)
  else
    # ability
    ability = @bot.ability_data(ability_id)
    can_ability_target_unit?(unit:, ability:)
  end
end

#can_weapon_target_unit?(unit:, weapon:) ⇒ Boolean

Checks whether a weapon can target a unit

Parameters:

Returns:

  • (Boolean)


447
448
449
450
451
452
453
454
455
456
# File 'lib/sc2ai/protocol/extensions/unit.rb', line 447

def can_weapon_target_unit?(unit:, weapon:)
  # false if enemy is air and we can only shoot ground
  return false if unit.is_flying && weapon.type == :GROUND # Api::Weapon::TargetType::GROUND

  # false if enemy is ground and we can only shoot air
  return false if unit.is_ground? && weapon.type == :AIR # Api::Weapon::TargetType::AIR

  # Check if weapon and unit models are in range
  in_attack_range?(unit:, range: weapon.range)
end

#debug_draw_placement(color = nil) ⇒ void

This method returns an undefined value.

Draws a placement outline noinspection RubyArgCount

Parameters:

  • color (Api::Color) (defaults to: nil)

    optional api color, default white



285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
# File 'lib/sc2ai/protocol/extensions/unit.rb', line 285

def debug_draw_placement(color = nil)
  # Slightly elevate the Z position so that the line doesn't clip into the terrain at same Z level
  z_elevated = pos.z + 0.01
  offset = footprint_radius
  # Box corners
  p0 = Api::Point.new(x: pos.x - offset, y: pos.y - offset, z: z_elevated)
  p1 = Api::Point.new(x: pos.x - offset, y: pos.y + offset, z: z_elevated)
  p2 = Api::Point.new(x: pos.x + offset, y: pos.y + offset, z: z_elevated)
  p3 = Api::Point.new(x: pos.x + offset, y: pos.y - offset, z: z_elevated)
  @bot.queue_debug_command Api::DebugCommand.new(
    draw: Api::DebugDraw.new(
      lines: [
        Api::DebugLine.new(
          color:,
          line: Api::Line.new(p0:, p1:)
        ),
        Api::DebugLine.new(
          color:,
          line: Api::Line.new(p0: p2, p1: p3)
        ),
        Api::DebugLine.new(
          color:,
          line: Api::Line.new(p0:, p1: p3)
        ),
        Api::DebugLine.new(
          color:,
          line: Api::Line.new(p0: p1, p1: p2)
        )
      ]
    )
  )
end

#debug_fire_range(weapon_index = 0, color = nil) ⇒ Object

Draws a sphere around the unit’s attack range

Parameters:

  • weapon_index (Api::Color) (defaults to: 0)

    default first weapon, see UnitTypeData.weapons

  • color (Api::Color) (defaults to: nil)

    optional api color, default red



321
322
323
324
325
326
327
# File 'lib/sc2ai/protocol/extensions/unit.rb', line 321

def debug_fire_range(weapon_index = 0, color = nil)
  color = Api::Color.new(r: 255, b: 0, g: 0) if color.nil?
  attack_range = unit_data.weapons[weapon_index].range
  raised_position = pos.dup
  raised_position.z += 0.01
  @bot.debug_draw_sphere(point: raised_position, radius: attack_range, color:)
end

#distance_to(other) ⇒ Object

Calculates the distance between self and other



333
334
335
336
337
338
# File 'lib/sc2ai/protocol/extensions/unit.rb', line 333

def distance_to(other)
  return 0.0 if other.nil? || other == self

  other = other.pos unless other.is_a? Sc2::Position
  pos.distance_to(other)
end

#footprint_radiusFloat

The placement size, by looking up unit’s creation ability, then game ability data This value should be correct for building placement math (unit.radius is not good for this)

Returns:

  • (Float)

    placement radius



497
498
499
# File 'lib/sc2ai/protocol/extensions/unit.rb', line 497

def footprint_radius
  @bot.data.abilities[unit_data.ability_id].footprint_radius
end

#has_attribute?(attribute) ⇒ Boolean

Checks unit data for an attribute value

Examples:

unit.has_attribute?(Api::Attribute::MECHANICAL)
unit.has_attribute?(:MECHANICAL)

Returns:

  • (Boolean)

    whether unit has attribute



62
63
64
# File 'lib/sc2ai/protocol/extensions/unit.rb', line 62

def has_attribute?(attribute)
  attributes.include? attribute
end

#has_buff?(buff_id) ⇒ Boolean

Whether unit is effected by buff_id

Examples:

unit.has_buff??(Api::BuffId::QUEENSPAWNLARVATIMER)

Parameters:

  • buff_id (Integer)

Returns:

  • (Boolean)


189
190
191
# File 'lib/sc2ai/protocol/extensions/unit.rb', line 189

def has_buff?(buff_id)
  buff_ids.include?(buff_id)
end

#has_reactor?Boolean

Returns whether the structure has a reactor add-on

Returns:

  • (Boolean)

    if the unit has a reactor attached



525
526
527
# File 'lib/sc2ai/protocol/extensions/unit.rb', line 525

def has_reactor?
  Sc2::UnitGroup::TYPE_REACTOR.include?(add_on&.unit_type)
end

#has_tech_lab?Boolean

Returns whether the structure has a tech lab add-on

Examples:

# Find the first Starport with a techlab
sp = structures.select_type(Api::UnitTypeId::STARPORT).find(&:has_tech_lab)
# Get the actual tech-lab with #add_on
sp.add_on.research ...

Returns:

  • (Boolean)

    if the unit has a tech lab attached



536
537
538
# File 'lib/sc2ai/protocol/extensions/unit.rb', line 536

def has_tech_lab?
  Sc2::UnitGroup::TYPE_TECHLAB.include?(add_on&.unit_type)
end

#hashObject



8
9
10
# File 'lib/sc2ai/protocol/extensions/unit.rb', line 8

def hash
  tag || super
end

#hold(queue_command: false) ⇒ Object Also known as: hold_position

Shorthand for performing action HOLDPOSITION

Parameters:

  • queue_command (Boolean) (defaults to: false)

    shift+command



225
226
227
# File 'lib/sc2ai/protocol/extensions/unit.rb', line 225

def hold(queue_command: false)
  action(ability_id: Api::AbilityId::HOLDPOSITION, queue_command:)
end

#in_attack_range?(unit:, range: nil) ⇒ Boolean

Checks whether opposing unit is in the attack range.

Parameters:

  • unit (Api::Unit)
  • range (Float, nil) (defaults to: nil)

    nil. will use default weapon range if nothing provided

Returns:

  • (Boolean)


470
471
472
473
# File 'lib/sc2ai/protocol/extensions/unit.rb', line 470

def in_attack_range?(unit:, range: nil)
  range = weapon.range if range.nil?
  distance_to(unit) <= radius + unit.radius + range
end

#in_circle?(point:, radius:) ⇒ Boolean

Detects whether a unit is within a given circle

Parameters:

Returns:

  • (Boolean)


359
360
361
# File 'lib/sc2ai/protocol/extensions/unit.rb', line 359

def in_circle?(point:, radius:)
  distance_to(point) <= radius
end

#in_progress?Boolean

Returns true if build progress is < 100%

Returns:

  • (Boolean)


509
510
511
# File 'lib/sc2ai/protocol/extensions/unit.rb', line 509

def in_progress?
  !is_completed?
end

#is_alive?Boolean

Returns whether a unit is alive or not Useful for cached Unit objects to see if they are still relevant.

Returns:

  • (Boolean)

    alive



32
33
34
# File 'lib/sc2ai/protocol/extensions/unit.rb', line 32

def is_alive?
  !@bot.all_units[tag].nil?
end

#is_armored?Boolean

Checks if unit is armored

Returns:

  • (Boolean)

    whether unit has attribute :Armored



74
75
76
# File 'lib/sc2ai/protocol/extensions/unit.rb', line 74

def is_armored?
  has_attribute?(:ARMORED)
end

#is_attacking?(target: nil) ⇒ Boolean

Returns whether unit is currently engaged with another

Parameters:

  • target (Api::Unit, Integer) (defaults to: nil)

    optionally check if unit is engaged with specific target

Returns:

  • (Boolean)


365
366
367
368
369
370
# File 'lib/sc2ai/protocol/extensions/unit.rb', line 365

def is_attacking?(target: nil)
  is_performing_ability_on_target?(
    [Api::AbilityId::ATTACK_ATTACK, Api::AbilityId::ATTACK],
    target:
  )
end

#is_biological?Boolean

Checks if unit is biological

Returns:

  • (Boolean)

    whether unit has attribute :Biological



80
81
82
# File 'lib/sc2ai/protocol/extensions/unit.rb', line 80

def is_biological?
  has_attribute?(:BIOLOGICAL)
end

#is_completed?Boolean

Returns true if build progress is 100%

Returns:

  • (Boolean)


503
504
505
# File 'lib/sc2ai/protocol/extensions/unit.rb', line 503

def is_completed?
  build_progress == 1.0 # standard:disable Lint/FloatComparison
end

#is_engaged_with?(unit) ⇒ Boolean

Returns whether engaged_target_tag or the current order matches supplied unit

Parameters:

  • unit (Api::Unit, Integer)

    optionally check if unit is engaged with specific target

Returns:

  • (Boolean)


403
404
405
406
407
408
409
410
411
412
413
# File 'lib/sc2ai/protocol/extensions/unit.rb', line 403

def is_engaged_with?(unit)
  # First match on unit#engaged_target_tag, since it's solid for attacks
  unit = unit.tag if unit.is_a? Api::Unit
  return true if engaged_target_tag == unit

  # Alternatively, check your order to see if your command ties you to the unit
  # It may not be in distance or actively performing, just yet.
  return orders.first.target_unit_tag == unit unless orders.empty?

  false
end

#is_harvesting?Boolean

Checks whether a unit is gathering or returning gathered minerals/gas

Returns:

  • (Boolean)

    true if either gathering or returning, false otherwise



384
385
386
# File 'lib/sc2ai/protocol/extensions/unit.rb', line 384

def is_harvesting?
  is_performing_ability?([Api::AbilityId::HARVEST_GATHER, Api::AbilityId::HARVEST_RETURN])
end

#is_heroic?Boolean

Checks if unit is heroic

Returns:

  • (Boolean)

    whether unit has attribute :Heroic



122
123
124
# File 'lib/sc2ai/protocol/extensions/unit.rb', line 122

def is_heroic?
  has_attribute?(:HEROIC)
end

#is_hover?Boolean

Checks if unit is hover

Returns:

  • (Boolean)

    whether unit has attribute :Hover



116
117
118
# File 'lib/sc2ai/protocol/extensions/unit.rb', line 116

def is_hover?
  has_attribute?(:HOVER)
end

#is_idle?Boolean

Returns true if unit does not have orders

Returns:

  • (Boolean)

    whether unit is idle



598
599
600
# File 'lib/sc2ai/protocol/extensions/unit.rb', line 598

def is_idle?
  orders.empty?
end

#is_light?Boolean

Checks if unit is light

Returns:

  • (Boolean)

    whether unit has attribute :Light



68
69
70
# File 'lib/sc2ai/protocol/extensions/unit.rb', line 68

def is_light?
  has_attribute?(:LIGHT)
end

#is_massive?Boolean

Checks if unit is massive

Returns:

  • (Boolean)

    whether unit has attribute :Massive



104
105
106
# File 'lib/sc2ai/protocol/extensions/unit.rb', line 104

def is_massive?
  has_attribute?(:MASSIVE)
end

#is_mechanical?Boolean

Checks if unit is mechanical

Returns:

  • (Boolean)

    whether unit has attribute :Mechanical



86
87
88
# File 'lib/sc2ai/protocol/extensions/unit.rb', line 86

def is_mechanical?
  has_attribute?(:MECHANICAL)
end

#is_performing_ability?(ability_ids) ⇒ Boolean

Checks whether a unit’s first order for ability

Parameters:

  • ability_ids (Integer, Array<Integer>)

    accepts one or an array of Api::AbilityId

Returns:

  • (Boolean)


390
391
392
393
394
395
396
397
398
# File 'lib/sc2ai/protocol/extensions/unit.rb', line 390

def is_performing_ability?(ability_ids)
  return false if orders.empty?

  if ability_ids.is_a? Array
    ability_ids.include?(orders.first&.ability_id)
  else
    ability_ids == orders.first&.ability_id
  end
end

#is_psionic?Boolean

Checks if unit is psionic

Returns:

  • (Boolean)

    whether unit has attribute :Psionic



98
99
100
# File 'lib/sc2ai/protocol/extensions/unit.rb', line 98

def is_psionic?
  has_attribute?(:PSIONIC)
end

#is_repairing?(target: nil) ⇒ Boolean

Returns whether the unit’s current order is to repair and optionally check it’s target

Parameters:

  • target (Api::Unit, Integer) (defaults to: nil)

    optionally check if unit is engaged with specific target

Returns:

  • (Boolean)


375
376
377
378
379
380
# File 'lib/sc2ai/protocol/extensions/unit.rb', line 375

def is_repairing?(target: nil)
  is_performing_ability_on_target?(
    [Api::AbilityId::EFFECT_REPAIR, Api::AbilityId::EFFECT_REPAIR_SCV, Api::AbilityId::EFFECT_REPAIR_MULE],
    target:
  )
end

#is_robotic?Boolean

Checks if unit is robotic

Returns:

  • (Boolean)

    whether unit has attribute :Robotic



92
93
94
# File 'lib/sc2ai/protocol/extensions/unit.rb', line 92

def is_robotic?
  has_attribute?(:ROBOTIC)
end

#is_structure?Boolean

Checks if unit is structure

Returns:

  • (Boolean)

    whether unit has attribute :Structure



110
111
112
# File 'lib/sc2ai/protocol/extensions/unit.rb', line 110

def is_structure?
  has_attribute?(:STRUCTURE)
end

#is_summoned?Boolean

Checks if unit is summoned

Returns:

  • (Boolean)

    whether unit has attribute :Summoned



128
129
130
# File 'lib/sc2ai/protocol/extensions/unit.rb', line 128

def is_summoned?
  has_attribute?(:SUMMONED)
end

#missing_harvestersInteger

For saturation counters on bases or gas, get the amount of missing harvesters required to saturate. For a unit to which this effect doesn’t apply, the amount is zero.

Returns:

  • (Integer)

    number of harvesters required to saturate this structure



487
488
489
490
491
492
# File 'lib/sc2ai/protocol/extensions/unit.rb', line 487

def missing_harvesters
  return 0 if ideal_harvesters.zero?

  missing = ideal_harvesters - assigned_harvesters
  missing.positive? ? missing : 0
end

#move(target:, queue_command: false) ⇒ Object

Shorthand for performing action MOVE

Parameters:

  • target (Api::Unit, Integer, Api::Point2D)

    is a unit, unit tag or a Api::Point2D

  • queue_command (Boolean) (defaults to: false)

    shift+command



213
214
215
# File 'lib/sc2ai/protocol/extensions/unit.rb', line 213

def move(target:, queue_command: false)
  action(ability_id: Api::AbilityId::MOVE, target:, queue_command:)
end

#nearest(units:, amount: nil) ⇒ Sc2::UnitGroup, ...

Gets the nearest amount of unit(s) from a group, relative to this unit Omitting amount returns a single Unit.

Parameters:

Returns:



345
346
347
348
349
350
351
352
353
354
355
# File 'lib/sc2ai/protocol/extensions/unit.rb', line 345

def nearest(units:, amount: nil)
  amount = 1 if !amount.nil? && amount.to_i <= 0

  # Performs suboptimal if sending an array. Don't.
  if units.is_a? Array
    units = Sc2::UnitGroup.new(units)
    units.use_kdtree = false # we will not re-use it's distance cache
  end

  units.nearest_to(pos:, amount:)
end

#previousApi::Unit?

Get the unit as from the previous frame. Good for comparison.

Returns:

  • (Api::Unit, nil)

    this unit from the previous frame or nil if it wasn’t present



25
26
27
# File 'lib/sc2ai/protocol/extensions/unit.rb', line 25

def previous
  @bot.previous.all_units[tag]
end

#refresh!Boolean

Replaces protobuf values with latest from game

Returns:

  • (Boolean)

    true if refreshed or false unchanged



38
39
40
41
42
43
44
45
46
47
# File 'lib/sc2ai/protocol/extensions/unit.rb', line 38

def refresh!
  new_unit = @bot.all_units[tag]
  return false if new_unit.nil? || new_unit == self

  method(:initialize).parameters.each do |_, entry|
    send(:"#{entry.name}=", new_unit.send(entry))
  end

  true
end

#repair(target:, queue_command: false) ⇒ Object

Issues repair command on target

Parameters:

  • target (Api::Unit, Integer)

    is a unit or unit tag

  • queue_command (Boolean) (defaults to: false)

    shift+command



266
267
268
# File 'lib/sc2ai/protocol/extensions/unit.rb', line 266

def repair(target:, queue_command: false)
  action(ability_id: Api::AbilityId::EFFECT_REPAIR, target:, queue_command:)
end

#research(upgrade_id:, queue_command: false) ⇒ Object

Research a specific upgrade

Parameters:

  • upgrade_id (Integer)

    Api::UnitTypeId the unit type you wish to research

  • queue_command (Boolean) (defaults to: false)

    shift+command



273
274
275
# File 'lib/sc2ai/protocol/extensions/unit.rb', line 273

def research(upgrade_id:, queue_command: false)
  @bot.research(units: self, upgrade_id:, queue_command:)
end

#smart(target: nil, queue_command: false) ⇒ Object

Shorthand for performing action SMART (right-click)

Parameters:

  • target (Api::Unit, Integer, Api::Point2D) (defaults to: nil)

    is a unit, unit tag or a Api::Point2D

  • queue_command (Boolean) (defaults to: false)

    shift+command



206
207
208
# File 'lib/sc2ai/protocol/extensions/unit.rb', line 206

def smart(target: nil, queue_command: false)
  action(ability_id: Api::AbilityId::SMART, target:, queue_command:)
end

#stop(queue_command: false) ⇒ Object

Shorthand for performing action STOP

Parameters:

  • queue_command (Boolean) (defaults to: false)

    shift+command



219
220
221
# File 'lib/sc2ai/protocol/extensions/unit.rb', line 219

def stop(queue_command: false)
  action(ability_id: Api::AbilityId::STOP, queue_command:)
end

#unit_dataApi::UnitTypeData

Returns static [Api::UnitTypeData] for a unit

Returns:



19
20
21
# File 'lib/sc2ai/protocol/extensions/unit.rb', line 19

def unit_data
  @bot.data.units[unit_type]
end

#warp(unit_type_id:, target:, queue_command: false) ⇒ Object

Warps in unit type at target (location or pylon) Only works if the source is a Warp Gate

Parameters:

  • unit_type_id (Integer)

    Api::UnitTypeId the unit type you wish to build

  • target (Api::Point2D)

    a point, which should be inside an energy source

  • queue_command (Boolean) (defaults to: false)

    shift+command



590
591
592
# File 'lib/sc2ai/protocol/extensions/unit.rb', line 590

def warp(unit_type_id:, target:, queue_command: false)
  @bot.warp(units: self, unit_type_id:, target:, queue_command:)
end

#weapon(index = 0) ⇒ Api::Weapon

Gets a weapon for this unit at index (default weapon is index 0)

Parameters:

  • index (Integer) (defaults to: 0)

    default 0

Returns:



478
479
480
# File 'lib/sc2ai/protocol/extensions/unit.rb', line 478

def weapon(index = 0)
  unit_data.weapons[index]
end