Class: Manufactured::Ship

Inherits:
Object show all
Includes:
Entity::HasCargo, Entity::InSystem
Defined in:
lib/manufactured/ship.rb

Overview

A player owned vehicle, residing in a Cosmos::Entities::SolarSystem. Ships requires Cosmos::Entities::JumpGates to travel in between systems and may mine resources and attack other manufactured entities depending on the ship type

Constant Summary collapse

TYPES =

General ship classification, used to determine a ship's capabilities

[:frigate, :transport, :escort, :destroyer, :bomber, :corvette,
:battlecruiser, :exploration, :mining]
ATTACK_TYPES =

Types of ships with attack capabilities

[:escort, :destroyer, :bomber, :corvette, :battlecruiser]
SIZES =

Mapping of ship types to default sizes

{:frigate => 35,  :transport => 25, :escort => 20,
:destroyer => 30, :bomber => 25, :corvette => 25,
:battlecruiser => 35, :exploration => 23, :mining => 25}

Movement Properties collapse

Attack/Defense Properties collapse

Mining Properties collapse

Looting Properties collapse

Instance Attribute Summary collapse

Attributes included from Entity::HasCargo

#cargo_capacity, #resources, #transfer_distance

Attributes included from Entity::InSystem

#location, #solar_system, #system_id

Movement Properties collapse

Attack/Defense Properties collapse

Mining Properties collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Entity::HasCargo

#add_resource, #can_accept?, #can_transfer?, #cargo_empty?, #cargo_full?, #cargo_quantity, #cargo_space, #remove_resource, #resources_valid?

Methods included from Entity::InSystem

#movement_strategy, #movement_strategy=

Constructor Details

#initialize(args = {}) ⇒ Ship

Ship initializer

Options Hash (args):

  • :id,'id' (String)

    id to assign to the ship

  • :user_id,'user_id' (String)

    id of user that owns the ship

  • :type,'type' (SHIP_TYPE)

    type to assign to ship, if not set a random type will be assigned

  • :docked_at,'docked_at' (Manufactured::Station)

    station which ship is docked at

  • :docked_at_id,'docked_at_id' (String)

    id of station which ship is docked at

  • :attacking,'attacking' (Manufactured::Ship)

    ship which this ship is attacking

  • :attacking_id,'attacking_id' (String)

    id of ship which this ship is attacking

  • :mining,'mining' (Cosmos::Resource)

    resource source which the ship is mining

  • :notifications,'notifications' (Array<Manufactured::Callback>)

    array of manufactured callbacks to assign to ship

  • :resources,'resources' (Array<Resource>)

    list of resources to set on ship

  • :hp,'hp' (Float, Int)

    hit points to assign to ship

  • :shield_level,'shield_level' (Float, Int)

    shield_level to assign to ship

  • :solar_system,'solar_system' (Cosmos::SolarSystem)

    solar system which the ship is in

  • :location,'location' (Motel::Location)

    location of the ship in the solar system

  • :movement_strategy (Motel::MovementStrategy)

    convenience setter of ship's location's movement strategy


323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
# File 'lib/manufactured/ship.rb', line 323

def initialize(args = {})
  args[:location] =
    Motel::Location.new :coordinates => [0,0,1],
                        :orientation => [1,0,0]  unless args.has_key?(:location) ||
                                                        args.has_key?('location')

  attr_from_args args, :id                   => nil,
                       :user_id              => nil,
                       :type                 => nil,
                       :callbacks            =>  [],
                       :resources            =>  [],
                       :docked_at            => nil,
                       :docked_at_id         => @docked_at_id,
                       :attacking            => nil,
                       :attacking_id         => @attacking_id,
                       :mining               => nil,
                       :location             => nil,
                       :system_id            => nil,
                       :solar_system         => nil,
                       :cargo_capacity       => 100,
                       :transfer_distance    => 200,
                       :collection_distance  => 300,
                       :shield_level         =>   0,
                       :hp                   => nil

  @location.orientation = [0,0,1] if @location.orientation == [nil, nil, nil]
  @location.movement_strategy =
    args[:movement_strategy] if args.has_key?(:movement_strategy)

  @hp                   = Ship.base_hp(@type) if @hp.nil?
  @max_hp               = Ship.base_hp(@type)
  @movement_speed       = Ship.base_movement_speed(@type)
  @rotation_speed       = Ship.base_rotation_speed(@type)
  @attack_distance      = Ship.base_attack_distance(@type)
  @attack_rate          = Ship.base_attack_rate(@type)
  @damage_dealt         = Ship.base_damage_dealt(@type)
  @mining_rate          = Ship.base_mining_rate(@type)
  @mining_quantity      = Ship.base_mining_quantity(@type)
  @mining_distance      = Ship.base_mining_distance(@type)
  @max_shield_level     = Ship.base_shield_level(@type)
  @shield_refresh_rate  = Ship.base_shield_refresh_rate(@type)
end

Instance Attribute Details

#attack_distanceObject

Max distance ship may be for a target to attack it


105
106
107
# File 'lib/manufactured/ship.rb', line 105

def attack_distance
  @attack_distance
end

#attack_rateObject

Number of attacks per second ship can launch


119
120
121
# File 'lib/manufactured/ship.rb', line 119

def attack_rate
  @attack_rate
end

#callbacksObject

Callbacks to invoke on ship events


50
51
52
# File 'lib/manufactured/ship.rb', line 50

def callbacks
  @callbacks
end

#collection_distanceObject

Max distance ship may be from loot to collect it


269
270
271
# File 'lib/manufactured/ship.rb', line 269

def collection_distance
  @collection_distance
end

#damage_dealtObject

Damage ship deals per hit


133
134
135
# File 'lib/manufactured/ship.rb', line 133

def damage_dealt
  @damage_dealt
end

#destroyed_byObject

Ship which destroyed this one (or its id) if applicable


196
197
198
# File 'lib/manufactured/ship.rb', line 196

def destroyed_by
  @destroyed_by
end

#distance_movedObject

Total distance ship moved


32
33
34
# File 'lib/manufactured/ship.rb', line 32

def distance_moved
  @distance_moved
end

#docked_atObject

Manufactured::Station ship is docked to, nil if not docked TODO replace w/ foreign_reference


248
249
250
# File 'lib/manufactured/ship.rb', line 248

def docked_at
  @docked_at
end

#docked_at_idObject

String id of the station ship is docked to


251
252
253
# File 'lib/manufactured/ship.rb', line 251

def docked_at_id
  @docked_at_id
end

#hpObject

Hit points the ship has


147
148
149
# File 'lib/manufactured/ship.rb', line 147

def hp
  @hp
end

#idObject

Unique string id of the ship


21
22
23
# File 'lib/manufactured/ship.rb', line 21

def id
  @id
end

#max_hpObject

Max hp the ship can have


150
151
152
# File 'lib/manufactured/ship.rb', line 150

def max_hp
  @max_hp
end

#max_shield_levelObject

Max shield level of the ship


164
165
166
# File 'lib/manufactured/ship.rb', line 164

def max_shield_level
  @max_shield_level
end

#miningObject

Cosmos::Resource ship is mining, nil if not mining


264
265
266
# File 'lib/manufactured/ship.rb', line 264

def mining
  @mining
end

#mining_distanceObject

Max distance ship may be from entity to mine it


231
232
233
# File 'lib/manufactured/ship.rb', line 231

def mining_distance
  @mining_distance
end

#mining_quantityObject

Quatity of resource being mined that can be extracted each time mining operation is performed


217
218
219
# File 'lib/manufactured/ship.rb', line 217

def mining_quantity
  @mining_quantity
end

#mining_rateObject

Number of mining operations per second ship can perform


203
204
205
# File 'lib/manufactured/ship.rb', line 203

def mining_rate
  @mining_rate
end

#movement_speedObject

Distance ship travels during a single movement cycle


69
70
71
# File 'lib/manufactured/ship.rb', line 69

def movement_speed
  @movement_speed
end

#rotation_speedObject

Max angle ship can rotate in a single movmeent cycle


84
85
86
# File 'lib/manufactured/ship.rb', line 84

def rotation_speed
  @rotation_speed
end

#shield_levelObject

Current shield level of the ship


178
179
180
# File 'lib/manufactured/ship.rb', line 178

def shield_level
  @shield_level
end

#shield_refresh_rateObject

Shield refresh rate in units per second


181
182
183
# File 'lib/manufactured/ship.rb', line 181

def shield_refresh_rate
  @shield_refresh_rate
end

#sizeObject

Size of the ship


29
30
31
# File 'lib/manufactured/ship.rb', line 29

def size
  @size
end

#typeObject

SHIP_TYPE

General category / classification of ship


35
36
37
# File 'lib/manufactured/ship.rb', line 35

def type
  @type
end

#user_idObject

ID of user which ship belongs to


26
27
28
# File 'lib/manufactured/ship.rb', line 26

def user_id
  @user_id
end

Class Method Details

.base_attack_distance(type) ⇒ Integer

Base attack distance of a ship of the specified type.

TODO right now just return a fixed distance for every ship, eventually make more variable.


114
115
116
# File 'lib/manufactured/ship.rb', line 114

def self.base_attack_distance(type)
  400
end

.base_attack_rate(type) ⇒ Integer

Base attack rate of a ship of the specified type.

TODO right now just return a fixed rate for every ship, eventually make more variable.


128
129
130
# File 'lib/manufactured/ship.rb', line 128

def self.base_attack_rate(type)
  0.5
end

.base_damage_dealt(type) ⇒ Integer

Base damage dealt by a ship of the specified type.

TODO right now just return a fixed value for every ship, eventually make more variable.


142
143
144
# File 'lib/manufactured/ship.rb', line 142

def self.base_damage_dealt(type)
  2
end

.base_hp(type) ⇒ Integer

Base hp of a ship of the specified type.

TODO right now just return a fixed hp for every ship, eventually make more variable.


159
160
161
# File 'lib/manufactured/ship.rb', line 159

def self.base_hp(type)
  25
end

.base_mining_distance(type) ⇒ Integer

Base mining distance of a ship of the specified type.

TODO right now just return a fixed distance for every ship, eventually make more variable.


240
241
242
# File 'lib/manufactured/ship.rb', line 240

def self.base_mining_distance(type)
  400
end

.base_mining_quantity(type) ⇒ Integer

Base mining quantity of a ship of the specified type.

TODO right now just return a fixed quantity for every ship, eventually make more variable.


226
227
228
# File 'lib/manufactured/ship.rb', line 226

def self.base_mining_quantity(type)
  20
end

.base_mining_rate(type) ⇒ Integer

Base mining rate of a ship of the specified type.

TODO right now just return a fixed rate for every ship, eventually make more variable.


212
213
214
# File 'lib/manufactured/ship.rb', line 212

def self.base_mining_rate(type)
  0.10
end

.base_movement_speed(type) ⇒ Integer

Base movement speed of a ship of the specified type.

TODO right now just return a fixed speed for every ship, eventually make more variable.


78
79
80
# File 'lib/manufactured/ship.rb', line 78

def self.base_movement_speed(type)
  50
end

.base_rotation_speed(type) ⇒ Integer

Base rotation speed of a ship of the specified type.

TODO right now just return a fixed speed for every ship, eventually make more variable.


93
94
95
96
97
98
# File 'lib/manufactured/ship.rb', line 93

def self.base_rotation_speed(type)
  # XXX: if this is too large, rotation callback will be thrown off
  #      as entity may have rotated passed specified distance in
  #      movement interval
  Math::PI / 32
end

.base_shield_level(type) ⇒ Integer

Base shield level of a ship of the specified type.

TODO right now just return a fixed level for every ship, eventually make more variable.


173
174
175
# File 'lib/manufactured/ship.rb', line 173

def self.base_shield_level(type)
  10
end

.base_shield_refresh_rate(type) ⇒ Integer

Base shield refresh rate of a ship of the specified type.

TODO right now just return a fixed rate for every ship, eventually make more variable.


190
191
192
# File 'lib/manufactured/ship.rb', line 190

def self.base_shield_refresh_rate(type)
  1
end

.construction_cost(type) ⇒ Integer

Cost to construct a ship of the specified type

TODO right now just return a fixed cost for every ship, eventually make more variable


292
293
294
# File 'lib/manufactured/ship.rb', line 292

def self.construction_cost(type)
  100
end

.construction_time(type) ⇒ Float

Time (in seconds) to construct a ship of the specified type

TODO right now just return a fixed time for every ship, eventually make more variable


302
303
304
# File 'lib/manufactured/ship.rb', line 302

def self.construction_time(type)
  5
end

.json_create(o) ⇒ Object

Create new ship from json representation


563
564
565
566
# File 'lib/manufactured/ship.rb', line 563

def self.json_create(o)
  ship = new(o['data'])
  return ship
end

Instance Method Details

#alive?Boolean

Return true / false indicating if the ship's hp > 0


437
438
439
# File 'lib/manufactured/ship.rb', line 437

def alive?
  @hp > 0
end

#attacking?true, false

Return boolean indicating if ship is currently attacking


498
499
500
# File 'lib/manufactured/ship.rb', line 498

def attacking?
  !self.attacking.nil?
end

#can_attack?(entity) ⇒ true, false

Return true / false indicating if ship can attack entity


455
456
457
458
459
460
# File 'lib/manufactured/ship.rb', line 455

def can_attack?(entity)
  ATTACK_TYPES.include?(@type) && !self.docked? &&
  (@location.parent_id == entity.location.parent_id) &&
  (@location - entity.location) <= @attack_distance  &&
  alive? && entity.alive?
end

#can_dock_at?(station) ⇒ true, false

Return true / false indicating if ship can dock at station


444
445
446
447
448
449
# File 'lib/manufactured/ship.rb', line 444

def can_dock_at?(station)
  (@location.parent_id == station.location.parent_id) &&
  (@location - station.location) <= station.docking_distance &&
  alive?
  # TODO ensure not already docked
end

#can_mine?(resource, quantity = resource.quantity) ⇒ true, false

Return true / false indicating if ship can mine entity


466
467
468
469
470
471
472
# File 'lib/manufactured/ship.rb', line 466

def can_mine?(resource, quantity=resource.quantity)
  # TODO eventually filter per specific resource mining capabilities
   @type == :mining && !self.docked? && alive? &&
  (@location.parent_id == resource.entity.location.parent_id) &&
  (@location - resource.entity.location) <= @mining_distance &&
  (cargo_quantity + quantity) <= @cargo_capacity
end

#dock_at(station) ⇒ Object

Dock ship at the specified station


485
486
487
# File 'lib/manufactured/ship.rb', line 485

def dock_at(station)
  self.docked_at = station
end

#docked?true, false

Return boolean indicating if ship is currently docked


478
479
480
# File 'lib/manufactured/ship.rb', line 478

def docked?
  !self.docked_at_id.nil?
end

#mining?true, false

Return boolean indicating if ship is currently mining


518
519
520
# File 'lib/manufactured/ship.rb', line 518

def mining?
  !@mining.nil?
end

#remove_callbacks(args = {}) ⇒ Object

Remove callbacks matching the specified args


59
60
61
62
63
64
# File 'lib/manufactured/ship.rb', line 59

def remove_callbacks(args={})
  @callbacks.reject! { |cb|
    (!args.has_key?(:event_type)  || cb.event_type  == args[:event_type]) &&
    (!args.has_key?(:endpoint_id) || cb.endpoint_id == args[:endpoint_id])
  }
end

#run_callbacks(type, *args) ⇒ Object

Run callbacks


53
54
55
56
# File 'lib/manufactured/ship.rb', line 53

def run_callbacks(type, *args)
  @callbacks.select { |c| c.event_type == type }.
             each   { |c| c.invoke self, *args  }
end

#start_attacking(defender) ⇒ Object

Set ship's attack target


505
506
507
# File 'lib/manufactured/ship.rb', line 505

def start_attacking(defender)
  self.attacking = defender
end

#start_mining(resource) ⇒ Object

Set ship's mining target


525
526
527
# File 'lib/manufactured/ship.rb', line 525

def start_mining(resource)
  @mining = resource
end

#stop_attackingObject

Clear ship's attacking target


510
511
512
# File 'lib/manufactured/ship.rb', line 510

def stop_attacking
  self.attacking = nil
end

#stop_miningObject

Clear ship's mining target


530
531
532
# File 'lib/manufactured/ship.rb', line 530

def stop_mining
  @mining = nil
end

#to_json(*a) ⇒ Object

Convert ship to json representation and return it TODO also add 'optimized' or some other mode/flag just returning variable properties


536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
# File 'lib/manufactured/ship.rb', line 536

def to_json(*a)
  {
    'json_class' => self.class.name,
    'data'       =>
      {:id => id, :user_id => user_id,
       :type => type, :size => size,
       :hp => @hp, :shield_level => @shield_level,
       :max_hp => @max_hp, :max_shield_level => @max_shield_level,
       :cargo_capacity => @cargo_capacity,
       :attack_distance => @attack_distance,
       :mining_distance => @mining_distance,
       :transfer_distance => @transfer_distance,
       :docked_at_id => @docked_at_id,
       :attacking_id => @attacking_id,
       :mining    => @mining,
       :location => @location,
       :system_id => (@solar_system.nil? ? @system_id : @solar_system.id),
       :resources => @resources}
  }.to_json(*a)
end

#to_sObject

Convert ship to human readable string and return it


558
559
560
# File 'lib/manufactured/ship.rb', line 558

def to_s
  "ship-#{@id}"
end

#undockObject

Undock ship from docked station


490
491
492
493
# File 'lib/manufactured/ship.rb', line 490

def undock
  # TODO check to see if station has given ship undocking clearance
  self.docked_at = nil
end

#update(ship) ⇒ Object

Update this ship's attributes from other ship


369
370
371
372
373
374
# File 'lib/manufactured/ship.rb', line 369

def update(ship)
  update_from(ship, :hp, :shield_level, :distance_moved, :resources,
                    :parent_id, :parent, :system_id, :solar_system,
                    :location, :mining, :attacking, :attacking_id,
                    :docked_at, :docked_at_id)
end

#valid?Boolean

Return boolean indicating if this ship is valid

Tests the various attributes of the Ship, returning true if everything is consistent, else false.

Current tests

  • id is set to a valid (non-empty) string

  • location is set to a Motel::Location

  • user id is set to a string

  • type is one of valid TYPES

  • size corresponds to the correct value for type

  • docked_at is set to a Manufactured::Station which permits docking

  • docked_at_id is valid if ship is docked

  • attacking is set to Manufactured::Ship that can be attacked

  • attacking_id is valid if ship is attacking

  • mining is set to Cosmos::Resource that can be mined

  • solar system is set to Cosmos::SolarSystem

  • notification_callbacks is an array of Manufactured::Callbacks

  • resources is a list of resources

At a minimum the following should be set on the default ship to be valid:

  • id

  • user_id

  • solar_system

  • type


402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
# File 'lib/manufactured/ship.rb', line 402

def valid?
  !@id.nil? && @id.is_a?(String) && @id != "" &&
  !@user_id.nil? && @user_id.is_a?(String) &&

  !@location.nil? && @location.is_a?(Motel::Location) &&
  !@system_id.nil? &&
  (@solar_system.nil? || @solar_system.is_a?(Cosmos::Entities::SolarSystem)) &&

  !@type.nil? && TYPES.include?(@type) &&
  !@size.nil? && @size == SIZES[@type] &&

   @shield_level <= @max_shield_level &&

  (@docked_at.nil? ||
   (@docked_at.is_a?(Manufactured::Station) && can_dock_at?(@docked_at) &&
    !@docked_at_id == @docked_at.id)) && # ???

  (@attacking.nil? ||
   (@attacking.is_a?(Manufactured::Ship) && can_attack?(@attacking) &&
    @attacking_id == @attacking.id)) &&

  (@mining.nil? ||
   (@mining.is_a?(Cosmos::Resource) && can_mine?(@mining))) &&

  @callbacks.is_a?(Array) &&
  @callbacks.select { |c|
    !c.kind_of?(Manufactured::Callback)
  }.empty? && # TODO ensure validity of callbacks

  self.resources_valid?

  # TODO validate cargo, mining, attack properties when they become variable
end