Class: Quake::Game::PlayerState

Inherits:
Object
  • Object
show all
Defined in:
lib/quake/game/player_state.rb

Overview

Tracks player game state: health, armor, ammo, weapons. Separate from physics (Physics::Player handles movement/collision).

Constant Summary collapse

WEAPONS =
%i[axe shotgun super_shotgun nailgun super_nailgun
grenade_launcher rocket_launcher lightning_gun].freeze
WEAPON_MODELS =
{
  axe:              "progs/v_axe.mdl",
  shotgun:          "progs/v_shot.mdl",
  super_shotgun:    "progs/v_shot2.mdl",
  nailgun:          "progs/v_nail.mdl",
  super_nailgun:    "progs/v_nail2.mdl",
  grenade_launcher: "progs/v_rock.mdl",
  rocket_launcher:  "progs/v_rock2.mdl",
  lightning_gun:    "progs/v_light.mdl"
}.freeze
WEAPON_AMMO =

Ammo type per weapon

{
  axe:              nil,
  shotgun:          :shells,
  super_shotgun:    :shells,
  nailgun:          :nails,
  super_nailgun:    :nails,
  grenade_launcher: :rockets,
  rocket_launcher:  :rockets,
  lightning_gun:    :cells
}.freeze
MAX_HEALTH =

Max ammo capacities (from Quake defs.qc)

100
MAX_MEGA_HEALTH =
250
MAX_ARMOR =
200
MAX_SHELLS =
100
MAX_NAILS =
200
MAX_ROCKETS =
100
MAX_CELLS =
100
AMMO_CAPS =
{
  shells: MAX_SHELLS, nails: MAX_NAILS,
  rockets: MAX_ROCKETS, cells: MAX_CELLS
}.freeze

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initializePlayerState

Returns a new instance of PlayerState.



39
40
41
42
43
44
45
46
# File 'lib/quake/game/player_state.rb', line 39

def initialize
  @health = 100
  @armor = 0
  @armor_type = 0 # 0=none, 1=green(30%), 2=yellow(60%), 3=red(80%)
  @current_weapon = :shotgun
  @weapons_owned = Set.new([:axe, :shotgun])
  @ammo = { shells: 25, nails: 0, rockets: 0, cells: 0 }
end

Instance Attribute Details

#ammoObject (readonly)

Returns the value of attribute ammo.



37
38
39
# File 'lib/quake/game/player_state.rb', line 37

def ammo
  @ammo
end

#armorObject

Returns the value of attribute armor.



36
37
38
# File 'lib/quake/game/player_state.rb', line 36

def armor
  @armor
end

#armor_typeObject

Returns the value of attribute armor_type.



36
37
38
# File 'lib/quake/game/player_state.rb', line 36

def armor_type
  @armor_type
end

#current_weaponObject

Returns the value of attribute current_weapon.



36
37
38
# File 'lib/quake/game/player_state.rb', line 36

def current_weapon
  @current_weapon
end

#healthObject

Returns the value of attribute health.



36
37
38
# File 'lib/quake/game/player_state.rb', line 36

def health
  @health
end

#weapons_ownedObject (readonly)

Returns the value of attribute weapons_owned.



37
38
39
# File 'lib/quake/game/player_state.rb', line 37

def weapons_owned
  @weapons_owned
end

Instance Method Details

#add_ammo(type, amount) ⇒ Object

Add ammo, returns true if picked up



130
131
132
133
134
135
136
137
# File 'lib/quake/game/player_state.rb', line 130

def add_ammo(type, amount)
  cap = AMMO_CAPS[type]
  return false unless cap
  return false if @ammo[type] >= cap

  @ammo[type] = [@ammo[type] + amount, cap].min
  true
end

#add_armor(points, type) ⇒ Object

Add armor, returns true if picked up



119
120
121
122
123
124
125
126
127
# File 'lib/quake/game/player_state.rb', line 119

def add_armor(points, type)
  # Only pick up if it's better than current armor
  # type: 1=green(30%), 2=yellow(60%), 3=red(80%)
  return false if type < @armor_type && @armor > 0

  @armor = [points, MAX_ARMOR].min
  @armor_type = type
  true
end

#add_health(amount, mega: false) ⇒ Object

Add health, returns true if picked up



110
111
112
113
114
115
116
# File 'lib/quake/game/player_state.rb', line 110

def add_health(amount, mega: false)
  max = mega ? MAX_MEGA_HEALTH : MAX_HEALTH
  return false if @health >= max

  @health = [@health + amount, max].min
  true
end

#alive?Boolean

Returns:

  • (Boolean)


91
92
93
# File 'lib/quake/game/player_state.rb', line 91

def alive?
  @health > 0
end

#current_ammo_countObject



52
53
54
55
# File 'lib/quake/game/player_state.rb', line 52

def current_ammo_count
  type = current_ammo_type
  type ? @ammo[type] : nil # nil = infinite (axe)
end

#current_ammo_typeObject



48
49
50
# File 'lib/quake/game/player_state.rb', line 48

def current_ammo_type
  WEAPON_AMMO[@current_weapon]
end

#current_weapon_modelObject



57
58
59
# File 'lib/quake/game/player_state.rb', line 57

def current_weapon_model
  WEAPON_MODELS[@current_weapon]
end

#give_weapon(weapon, ammo_type: nil, ammo_amount: 0) ⇒ Object

Give weapon, returns true if picked up (always true for new weapons)



140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
# File 'lib/quake/game/player_state.rb', line 140

def give_weapon(weapon, ammo_type: nil, ammo_amount: 0)
  had_weapon = @weapons_owned.include?(weapon)
  @weapons_owned.add(weapon)

  ammo_picked = false
  if ammo_type && ammo_amount > 0
    ammo_picked = add_ammo(ammo_type, ammo_amount)
  end

  if !had_weapon
    @current_weapon = weapon
    true
  else
    ammo_picked
  end
end

#next_weaponObject

Cycle to next owned weapon (mousewheel or number keys)



62
63
64
65
66
67
68
69
70
71
# File 'lib/quake/game/player_state.rb', line 62

def next_weapon
  idx = WEAPONS.index(@current_weapon) || 0
  WEAPONS.size.times do
    idx = (idx + 1) % WEAPONS.size
    if @weapons_owned.include?(WEAPONS[idx])
      @current_weapon = WEAPONS[idx]
      return
    end
  end
end

#prev_weaponObject



73
74
75
76
77
78
79
80
81
82
# File 'lib/quake/game/player_state.rb', line 73

def prev_weapon
  idx = WEAPONS.index(@current_weapon) || 0
  WEAPONS.size.times do
    idx = (idx - 1) % WEAPONS.size
    if @weapons_owned.include?(WEAPONS[idx])
      @current_weapon = WEAPONS[idx]
      return
    end
  end
end

#select_weapon(slot) ⇒ Object

Select weapon by slot number (1-8)



85
86
87
88
89
# File 'lib/quake/game/player_state.rb', line 85

def select_weapon(slot)
  slot = slot.clamp(1, WEAPONS.size)
  weapon = WEAPONS[slot - 1]
  @current_weapon = weapon if @weapons_owned.include?(weapon)
end