Class: Manufactured::Commands::Attack

Inherits:
Omega::Server::Command show all
Includes:
Omega::Server::CommandHelpers
Defined in:
lib/manufactured/commands/attack.rb

Overview

Represents action of one Ship attacking another

Registered with the registry by a client when attacker commences attacking and periodically run by registry until attacked stops, defender is destroyed, or one of several other conditions occur.

Invokes Omega::Server::Callbacks registered with the attacker and defender before/during/after the attack cycle with the event type, the attacking ship, and the defending ship as params

The callback events/types invoked include:

  • 'attacked_stop' - invoked on the attacker when attacker stops attacking

  • 'attacked_stop' - invoked on the defender when attacker stops attacking

  • 'attacked' - invoked on the attacker when attacker actually launches the attack

  • 'defended' - invoked on the defender when attacker actually launches the attack

  • 'destroyed' - invoked on the defender if this attack cycle resulted in the defender hp becoming <= 0

Instance Attribute Summary collapse

Attributes inherited from Omega::Server::Command

#added_at, #exec_rate, #hooks, #last_ran_at, #node, #ran_first_hooks, #registry

Instance Method Summary collapse

Methods included from Omega::Server::CommandHelpers

#invoke, #retrieve, #run_callbacks, #update_registry

Methods inherited from Omega::Server::Command

#cmd_json, json_create, #run_hooks, #to_s, #update

Constructor Details

#initialize(args = {}) ⇒ Attack

Manufactured::Commands::Attack initializer

Options Hash (args):


58
59
60
61
62
# File 'lib/manufactured/commands/attack.rb', line 58

def initialize(args = {})
  attr_from_args args, :attacker => nil,
                       :defender => nil
  super(args)
end

Instance Attribute Details

#attackerObject

Ship performing the attack


34
35
36
# File 'lib/manufactured/commands/attack.rb', line 34

def attacker
  @attacker
end

#defenderObject

Ship receiving that attack


37
38
39
# File 'lib/manufactured/commands/attack.rb', line 37

def defender
  @defender
end

Instance Method Details

#after_hookObject


81
82
83
84
85
# File 'lib/manufactured/commands/attack.rb', line 81

def after_hook
  # persist entities to the registry
  update_registry(@attacker)
  update_registry(@defender)
end

#before_hookObject


69
70
71
72
73
74
75
76
77
78
79
# File 'lib/manufactured/commands/attack.rb', line 69

def before_hook
  # update entities from registry
  @attacker = retrieve(@attacker.id)
  @defender = retrieve(@defender.id)

  # update locations from motel
  @attacker.location =
    invoke 'motel::get_location', 'with_id', @attacker.location.id
  @defender.location =
    invoke 'motel::get_location', 'with_id', @defender.location.id
end

#first_hookObject


64
65
66
67
# File 'lib/manufactured/commands/attack.rb', line 64

def first_hook
  @attacker.start_attacking(@defender)
  update_registry(@attacker)
end

#idObject

Return the unique id of this attack command.

Currently a ship may only attack one other at a time, TODO incorporate multiple weapons and area based weapons (multiple defenders) into this


44
45
46
47
# File 'lib/manufactured/commands/attack.rb', line 44

def id
  id = @attacker.nil? ? "" : @attacker.id.to_s
  "attack-cmd-#{id}"
end

#last_hookObject


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
# File 'lib/manufactured/commands/attack.rb', line 87

def last_hook
  @attacker.stop_attacking

  # check if defender has been destroyed
  if @defender.hp == 0
    ::RJR::Logger.debug "#{@attacker.id} destroyed #{@defender.id}"

    # update ship's movement strategy to stopped
    @defender.location.movement_strategy = Motel::MovementStrategies::Stopped.instance
    invoke("motel::update_location", @defender.location)

    # TODO issue call to motel to lock destroyed ship's location
    # (when that operation is supported)

    # Stop commands related to destroyed ship.
    # All commands should auto-stop if related entity is not alive
    # but this stops the commands immediately so that it's done w/
    registry.stop_commands_for(@defender)

    # set user attributes
    invoke('users::update_attribute', @attacker.user_id,
           Users::Attributes::ShipsUserDestroyed.id,  1)
    invoke('users::update_attribute', @defender.user_id,
           Users::Attributes::UserShipsDestroyed.id,  1)

    # create loot if necessary
    unless @defender.cargo_empty?
      # two entities (ship/loot) sharing same location
      loot = Manufactured::Loot.new :id => "#{@defender.id}-loot",
               :location          => @defender.location,
               :system_id         => @defender.system_id,
               :movement_strategy => Motel::MovementStrategies::Stopped.instance,
               :cargo_capacity    => @defender.cargo_capacity
      @defender.resources.each { |r| loot.add_resource r }
      registry << loot
    end

    # invoke defender's 'destroyed' callbacks
    run_callbacks(@defender, 'destroyed_by', @attacker)

    # Dispatch new entity_destroyed event to registry
    event = Manufactured::Events::EntityDestroyed.new(:entity => @defender)
    registry << event
  end

  # invoke attackers's 'attacked_stop' callbacks
  run_callbacks(@attacker, 'attacked_stop', @defender)

  # invoke defender's 'defended_stop' callbacks
  run_callbacks(@defender, 'defended_stop', @attacker)
end

#processes?(entity) ⇒ Boolean


49
50
51
52
# File 'lib/manufactured/commands/attack.rb', line 49

def processes?(entity)
  entity.is_a?(Manufactured::Ship) &&
  (entity.id == attacker.id || entity.id == defender.id)
end

#remove?Boolean


174
175
176
177
# File 'lib/manufactured/commands/attack.rb', line 174

def remove?
  # remove if defender is destroyed
  @defender.hp == 0 || !@attacker.can_attack?(@defender)
end

#run!Object


143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
# File 'lib/manufactured/commands/attack.rb', line 143

def run!
  super
  ::RJR::Logger.debug "invoking attack command #{@attacker.id} -> #{@defender.id}"

  # TODO incorporate a hit / miss probability into this
  # TODO incorporate AC / other defense mechanisms into this
  # TODO delay between launching attack and it arriving at defender
  #   (depending on distance and projectile speed)

  # first reduce defender's shield then hp
  if @attacker.damage_dealt <= @defender.shield_level
    @defender.shield_level -= @attacker.damage_dealt

  else
    pips = (@attacker.damage_dealt - @defender.shield_level)
    @defender.hp -= pips
    @defender.shield_level = 0

    if @defender.hp <= 0
      @defender.hp = 0
      @defender.destroyed_by = @attacker
    end
  end

  # invoke attacker's 'attacked' callbacks
  run_callbacks(@attacker, 'attacked', @defender)

  # invoke defender's 'defended' callbacks
  run_callbacks(@defender, 'defended', @attacker)
end

#should_run?Boolean


139
140
141
# File 'lib/manufactured/commands/attack.rb', line 139

def should_run?
  super && @attacker.can_attack?(@defender)
end

#to_json(*a) ⇒ Object

Convert command to json representation and return it


180
181
182
183
184
185
186
187
# File 'lib/manufactured/commands/attack.rb', line 180

def to_json(*a)
  {
    'json_class' => self.class.name,
    'data'       =>
      {:attacker => attacker,
       :defender => defender}.merge(cmd_json)
  }.to_json(*a)
end