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

Virtual properties 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

#full_energy?Boolean (readonly)

Returns:

  • (Boolean)


197
198
199
# File 'lib/sc2ai/protocol/extensions/unit.rb', line 197

def full_energy?
  energy == energy_max
end

#full_health?Boolean (readonly)

Returns:

  • (Boolean)


185
186
187
# File 'lib/sc2ai/protocol/extensions/unit.rb', line 185

def full_health?
  health == health_max
end

#full_shields?Boolean (readonly)

Returns:

  • (Boolean)


191
192
193
# File 'lib/sc2ai/protocol/extensions/unit.rb', line 191

def full_shields?
  shield == shield_max
end

#is_active?Boolean (readonly)

Returns:

  • (Boolean)


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

def is_active? = is_active

#is_blip?Boolean (readonly)

Returns:

  • (Boolean)


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

def is_blip? = is_blip

#is_burrowed?Boolean (readonly)

Returns:

  • (Boolean)


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

def is_burrowed? = is_burrowed

#is_cloaked??Boolean (readonly)

Returns whether the unit is cloaked. Revealed cloak units also return true. For further distinction, use Unit#cloaked, which uses enum CloakedState

Returns:

  • (Boolean)


268
269
270
# File 'lib/sc2ai/protocol/extensions/unit.rb', line 268

def is_cloaked?
  cloak != :NOT_CLOAKED && cloak != :CLOAKED_UNKNOWN
end

#is_flying?Boolean (readonly)

Returns:

  • (Boolean)


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

def is_flying? = is_flying

#is_ground?Boolean (readonly)

Returns whether the unit is grounded (not flying).

Returns:

  • (Boolean)


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

def is_ground? = !is_flying?

#is_hallucination?Boolean (readonly)

Returns:

  • (Boolean)


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

def is_hallucination? = is_hallucination

#is_melee?Boolean (readonly)

Returns whether this is a melee (non-ranged) attacker Archon isn’t melee; 3 range Hellbat is melee, but Hellion isn’t melee; 5 range Roach isn’t melee; just an attack animation when nearby

Returns:

  • (Boolean)


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

def is_melee?
  Sc2::UnitGroup::TYPE_MELEE.include?(unit_type)
end

#is_on_screen?Boolean (readonly)

Returns:

  • (Boolean)


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

def is_on_screen? = is_on_screen

#is_powered?Boolean (readonly)

Returns:

  • (Boolean)


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

def is_powered? = is_powered

#is_ranged?Boolean (readonly)

Returns ranged attack units

Returns:

  • (Boolean)

See Also:



221
222
223
# File 'lib/sc2ai/protocol/extensions/unit.rb', line 221

def is_ranged?
  Sc2::UnitGroup::TYPE_RANGE.include?(unit_type)
end

#is_selected?Boolean (readonly)

Returns:

  • (Boolean)


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

def is_selected? = is_selected

#is_worker?Boolean (readonly)

Returns:

  • (Boolean)


203
204
205
# File 'lib/sc2ai/protocol/extensions/unit.rb', line 203

def is_worker?
  Sc2::UnitGroup::TYPE_WORKER.include?(unit_type)
end

#widthFloat

width = radius * 2

Returns:

  • (Float)


176
177
178
179
180
181
# File 'lib/sc2ai/protocol/extensions/unit.rb', line 176

def width = radius * 2.0
# @!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)


541
542
543
# File 'lib/sc2ai/protocol/extensions/unit.rb', line 541

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



289
290
291
# File 'lib/sc2ai/protocol/extensions/unit.rb', line 289

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



628
629
630
# File 'lib/sc2ai/protocol/extensions/unit.rb', line 628

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



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

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



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

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 an array of attributes for a unit

Returns:



94
95
96
# File 'lib/sc2ai/protocol/extensions/unit.rb', line 94

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



342
343
344
# File 'lib/sc2ai/protocol/extensions/unit.rb', line 342

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



651
652
653
654
655
656
657
658
659
660
661
662
# File 'lib/sc2ai/protocol/extensions/unit.rb', line 651

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, 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



666
667
668
669
670
671
672
673
674
675
676
# File 'lib/sc2ai/protocol/extensions/unit.rb', line 666

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, queue_command:)
end

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

Checks whether an ability can target a unit

Parameters:

Returns:

  • (Boolean)


565
566
567
568
569
570
571
572
# File 'lib/sc2ai/protocol/extensions/unit.rb', line 565

def can_ability_target_unit?(unit:, ability:)
  return false if unit.nil? || ability.nil?
  # 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: nil, ability_id: nil) ⇒ Boolean

Checks whether enemy is within range of weapon or ability and can target ground/air. By default, checks all weapons. Pass weapon_index or ability_id to target a specific source of damage.

Examples:

queen.can_attack?(unit: enemy, weapon_index: 0) # Air attack
queen.can_attack?(unit: enemy, weapon_index: 1) # Ground attack
queen.can_attack?(unit: enemy) # Auto detect (scans all weapons)
ghost.can_attack?(unit: enemy, ability_id: Api::AbilityId::SNIPE)

Parameters:

  • unit (Api::Unit)

    enemy

  • weapon_index (Integer) (defaults to: nil)

    passing this will select a specific Weapon

  • ability_id (Integer) (defaults to: nil)

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

Returns:

  • (Boolean)


521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
# File 'lib/sc2ai/protocol/extensions/unit.rb', line 521

def can_attack?(unit:, weapon_index: nil, ability_id: nil)
  return false if unit.nil?
  if ability_id
    # ability
    ability = @bot.ability_data(ability_id)
    can_ability_target_unit?(unit:, ability:)
  elsif weapon_index
    # weapon
    source_weapon = weapon(weapon_index)
    can_weapon_target_unit?(unit:, weapon: source_weapon)
  else
    # auto-detect weapon
    unit_data.weapons.any? { |weapon| can_weapon_target_unit?(unit:, weapon:) }
  end
end

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

Checks whether a weapon can target a unit

Parameters:

Returns:

  • (Boolean)


549
550
551
552
553
554
555
556
557
558
559
# File 'lib/sc2ai/protocol/extensions/unit.rb', line 549

def can_weapon_target_unit?(unit:, weapon:)
  return false if unit.nil? || weapon.nil?
  # 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



375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
# File 'lib/sc2ai/protocol/extensions/unit.rb', line 375

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 (weapon range + radius)

Parameters:

  • weapon_index (Integer) (defaults to: 0)

    default first weapon, see UnitTypeData#weapons

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

    optional api color, default red



411
412
413
414
415
416
417
418
419
420
421
# File 'lib/sc2ai/protocol/extensions/unit.rb', line 411

def debug_fire_range(weapon_index = 0, color = nil)
  attack_range = unit_data.weapons[weapon_index]&.range
  return if attack_range.nil?
  attack_range += radius

  color = Api::Color.new(r: 255, b: 0, g: 0) if color.nil?
  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



427
428
429
430
431
432
# File 'lib/sc2ai/protocol/extensions/unit.rb', line 427

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



605
606
607
608
# File 'lib/sc2ai/protocol/extensions/unit.rb', line 605

def footprint_radius
  return 0.0 if unit_data.ability_id == 0
  @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)

Returns:

  • (Boolean)

    whether unit has attribute



102
103
104
# File 'lib/sc2ai/protocol/extensions/unit.rb', line 102

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)


279
280
281
# File 'lib/sc2ai/protocol/extensions/unit.rb', line 279

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



634
635
636
# File 'lib/sc2ai/protocol/extensions/unit.rb', line 634

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



645
646
647
# File 'lib/sc2ai/protocol/extensions/unit.rb', line 645

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



315
316
317
# File 'lib/sc2ai/protocol/extensions/unit.rb', line 315

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)


578
579
580
581
# File 'lib/sc2ai/protocol/extensions/unit.rb', line 578

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)


453
454
455
# File 'lib/sc2ai/protocol/extensions/unit.rb', line 453

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

#in_progress?Boolean

Returns true if build progress is < 100%

Returns:

  • (Boolean)


618
619
620
# File 'lib/sc2ai/protocol/extensions/unit.rb', line 618

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



114
115
116
# File 'lib/sc2ai/protocol/extensions/unit.rb', line 114

def is_armored?
  has_attribute?(Api::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)


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

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



120
121
122
# File 'lib/sc2ai/protocol/extensions/unit.rb', line 120

def is_biological?
  has_attribute?(Api::Attribute::BIOLOGICAL)
end

#is_cloaked?Boolean

Returns whether the unit is cloaked. Revealed cloak units also return true. For further distinction, use Unit#cloaked, which uses enum CloakedState

Returns:

  • (Boolean)


268
269
270
# File 'lib/sc2ai/protocol/extensions/unit.rb', line 268

def is_cloaked?
  cloak != :NOT_CLOAKED && cloak != :CLOAKED_UNKNOWN
end

#is_completed?Boolean

Returns true if build progress is 100%

Returns:

  • (Boolean)


612
613
614
# File 'lib/sc2ai/protocol/extensions/unit.rb', line 612

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)


497
498
499
500
501
502
503
504
505
506
507
# File 'lib/sc2ai/protocol/extensions/unit.rb', line 497

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



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

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



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

def is_heroic?
  has_attribute?(Api::Attribute::HEROIC)
end

#is_hover?Boolean

Checks if unit is hovering

Returns:

  • (Boolean)

    whether unit has attribute :HOVER



156
157
158
# File 'lib/sc2ai/protocol/extensions/unit.rb', line 156

def is_hover?
  has_attribute?(Api::Attribute::HOVER)
end

#is_idle?Boolean

Returns true if unit does not have orders

Returns:

  • (Boolean)

    whether unit is idle



693
694
695
# File 'lib/sc2ai/protocol/extensions/unit.rb', line 693

def is_idle?
  orders.empty?
end

#is_light?Boolean

Checks if unit is light

Returns:

  • (Boolean)

    whether unit has attribute :LIGHT



108
109
110
# File 'lib/sc2ai/protocol/extensions/unit.rb', line 108

def is_light?
  has_attribute?(Api::Attribute::LIGHT)
end

#is_massive?Boolean

Checks if unit is massive

Returns:

  • (Boolean)

    whether unit has attribute :MASSIVE



144
145
146
# File 'lib/sc2ai/protocol/extensions/unit.rb', line 144

def is_massive?
  has_attribute?(Api::Attribute::MASSIVE)
end

#is_mechanical?Boolean

Checks if unit is mechanical

Returns:

  • (Boolean)

    whether unit has attribute :MECHANICAL



126
127
128
# File 'lib/sc2ai/protocol/extensions/unit.rb', line 126

def is_mechanical?
  has_attribute?(Api::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)


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

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



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

def is_psionic?
  has_attribute?(Api::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)


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

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



132
133
134
# File 'lib/sc2ai/protocol/extensions/unit.rb', line 132

def is_robotic?
  has_attribute?(Api::Attribute::ROBOTIC)
end

#is_structure?Boolean

Checks if unit is structure

Returns:

  • (Boolean)

    whether unit has attribute :STRUCTURE



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

def is_structure?
  has_attribute?(Api::Attribute::STRUCTURE)
end

#is_summoned?Boolean

Checks if unit is summoned

Returns:

  • (Boolean)

    whether unit has attribute :SUMMONED



168
169
170
# File 'lib/sc2ai/protocol/extensions/unit.rb', line 168

def is_summoned?
  has_attribute?(Api::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



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

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



303
304
305
# File 'lib/sc2ai/protocol/extensions/unit.rb', line 303

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:



439
440
441
442
443
444
445
446
447
448
449
# File 'lib/sc2ai/protocol/extensions/unit.rb', line 439

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
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
# 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

  self.display_type = new_unit.display_type
  self.alliance = new_unit.alliance
  self.tag = new_unit.tag
  self.unit_type = new_unit.unit_type
  self.owner = new_unit.owner
  self.pos = new_unit.pos
  self.facing = new_unit.facing
  self.radius = new_unit.radius
  self.build_progress = new_unit.build_progress
  self.cloak = new_unit.cloak
  self.buff_ids = new_unit.buff_ids
  self.detect_range = new_unit.detect_range
  self.radar_range = new_unit.radar_range
  self.is_selected = new_unit.is_selected
  self.is_on_screen = new_unit.is_on_screen
  self.is_blip = new_unit.is_blip
  self.is_powered = new_unit.is_powered
  self.is_active = new_unit.is_active
  self.attack_upgrade_level = new_unit.attack_upgrade_level
  self.armor_upgrade_level = new_unit.armor_upgrade_level
  self.shield_upgrade_level = new_unit.shield_upgrade_level
  self.health = new_unit.health
  self.health_max = new_unit.health_max
  self.shield = new_unit.shield
  self.shield_max = new_unit.shield_max
  self.energy = new_unit.energy
  self.energy_max = new_unit.energy_max
  self.mineral_contents = new_unit.mineral_contents
  self.vespene_contents = new_unit.vespene_contents
  self.is_flying = new_unit.is_flying
  self.is_burrowed = new_unit.is_burrowed
  self.is_hallucination = new_unit.is_hallucination
  self.orders = new_unit.orders
  self.add_on_tag = new_unit.add_on_tag
  self.passengers = new_unit.passengers
  self.cargo_space_taken = new_unit.cargo_space_taken
  self.cargo_space_max = new_unit.cargo_space_max
  self.assigned_harvesters = new_unit.assigned_harvesters
  self.ideal_harvesters = new_unit.ideal_harvesters
  self.weapon_cooldown = new_unit.weapon_cooldown
  self.engaged_target_tag = new_unit.engaged_target_tag
  self.buff_duration_remain = new_unit.buff_duration_remain
  self.buff_duration_max = new_unit.buff_duration_max
  self.rally_targets = new_unit.rally_targets

  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



356
357
358
# File 'lib/sc2ai/protocol/extensions/unit.rb', line 356

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



363
364
365
# File 'lib/sc2ai/protocol/extensions/unit.rb', line 363

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



296
297
298
# File 'lib/sc2ai/protocol/extensions/unit.rb', line 296

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



309
310
311
# File 'lib/sc2ai/protocol/extensions/unit.rb', line 309

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



685
686
687
# File 'lib/sc2ai/protocol/extensions/unit.rb', line 685

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:



586
587
588
# File 'lib/sc2ai/protocol/extensions/unit.rb', line 586

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