hlockey 6 → 7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,46 @@
1
+ {
2
+ "season_day": "Season %{season} day %{day}",
3
+ "season_starts": "Season %{season} starts at %{time}.",
4
+ "season_champion": "Your season %{season} champions are the %{team}!",
5
+ "season_off": "no games right now. it is the offseason. join the Hlockey Discord for updates.",
6
+
7
+ "game_start": "Hocky!",
8
+ "game_end": "Game over.\n%{winning_team} win!",
9
+ "game_score": "%{home} %{home_score}, %{away} %{away_score}",
10
+ "game_period_start": "Start of period %{period}.",
11
+ "game_period_end": "End of period %{period}.",
12
+ "game_faceoff": "%{winning_player} wins the faceoff!",
13
+ "game_pass": "%{sender} passes to %{receiver}.",
14
+ "game_pass_intercept": "%{sender}'s pass to %{receiver} is intercepted by %{interceptor}!",
15
+ "game_hit": "%{defender} hits %{puck_holder}.",
16
+ "game_shot": "%{shooter} takes a shot...",
17
+ "game_shot_audacious": "%{shooter} takes an audacious shot...",
18
+ "game_shot_scored": "%{shooter} scores!",
19
+ "game_shot_blocked": "%{blocker} blocks the shot.",
20
+ "game_partying": "%{player} is partying!",
21
+ "game_possession_change": "%{player} takes the puck!\n%{new_puck_team} have possession.",
22
+
23
+ "fight_start": "%{home_player} and %{away_player} start fighting!",
24
+ "fight_player_join": "%{player} from %{team} joins the fight!",
25
+ "fight_player_withdraw": "%{player} withdraws from the fight!",
26
+ "fight_attack": "%{player} is going for a punch...",
27
+ "fight_hit": "The punch lands to hit %{player}!",
28
+ "fight_block": "%{player} blocks the punch!",
29
+ "fight_dodge": "%{player} dodges the punch!",
30
+ "fight_end": "The fight has ended.",
31
+ "fight_end_morale_gain": "%{team} gains %{num} morale.",
32
+ "fight_end_morale_loss": "%{team} loses %{num} morale.",
33
+
34
+ "weather_chicken_event": "%{prev_player} chickened out!\nReplaced by %{next_player} for the game.",
35
+ "weather_incline_event": "The incline favors %{team}.",
36
+ "weather_stars_event": "The stars align for %{team}. They get half a goal.",
37
+ "weather_waves_event": "%{prev_player} is washed away by the waves...\nReplaced by %{next_player} for the season.",
38
+
39
+ "mod_immaterial_event": "%{hitting_player} goes right through %{player}!",
40
+ "mod_fence_event": "%{player} is a fence%{type}.\n%{player} swaps with %{swap_player} instead.",
41
+ "mod_handholding_event": "%{player} is holding %{other_player}'s hand.\n%{other_player} follows %{player} by swapping with %{swap_player}.",
42
+ "mod_locked_event": "%{player} is locked and does not get swapped with %{swap_player}",
43
+ "mod_powernap_start": "%{player} gets a boost from powernapping!",
44
+ "mod_powernap_end": "%{player}'s powernap boost has ended.",
45
+ "mod_punchy_event": "%{player} is looking for a fight..."
46
+ }
@@ -1,35 +1,28 @@
1
1
  {
2
- "vote_amt": 159,
2
+ "vote_amt": 91,
3
3
  "categories": {
4
- "Bribery (49 votes)": {
5
- "Winning bribe": {
6
- "winner": "Mods Help (23 votes)"
7
- }
8
- },
9
- "Treasure (83 votes)": {
4
+ "Treasure (64 votes)": {
10
5
  "Dave": {
11
- "winner": "Pica Acid (2 votes / 21 total)",
12
- "most_votes": "Sydney Thinkers (6 votes)"
6
+ "winner": "Cape Town Transplants (2 votes / 7 total)"
13
7
  },
14
8
  "Nice": {
15
- "winner": "Nice Backflippers (2 votes / 15 total)",
16
- "most_votes": "Dawson City Impostors (7 votes)"
9
+ "winner": "Stony Brook Reapers (1 vote / 15 total)",
10
+ "most_votes": "Dawson City Impostors (9 votes)"
17
11
  },
18
12
  "Vengabus": {
19
- "winner": "Antalya Pirates (2 votes / 22 total)",
20
- "most_votes": "Stony Brook Reapers (11 votes)"
21
- },
22
- "Unvengabus": {
23
- "winner": "Rio de Janeiro Directors (Dry Warm) (0 votes / 0 total)"
13
+ "winner": "Stony Brook Reapers (1 vote / 11 total)",
14
+ "most_votes": "Rio de Janeiro Directors (4 votes)"
24
15
  },
25
16
  "Shared Training": {
26
- "winner": "Pompei Eruptions (Dry Warm) (4 votes / 16 total)"
17
+ "winner": "Pompei Eruptions (Dry Warm) (1 votes / 15 total)",
18
+ "most_votes": "Kyoto Payphones (3 votes)"
27
19
  },
28
20
  "Theft": {
29
- "winner": "Sydney Thinkers (8 votes / 9 total)"
21
+ "winner": "Baden Hallucinations (1 vote / 14 total)",
22
+ "most_votes": "Rio de Janeiro Directors (3 votes)"
30
23
  },
31
- "Hidden Treasure - Evolve": {
32
- "winner": "Baden Hallucinations (0 votes / 0 total)"
24
+ "Shadow Lock": {
25
+ "winner": "Nagqu Paint (2 votes / 2 total)"
33
26
  }
34
27
  },
35
28
  "Coaching (27 votes)": {
@@ -37,62 +30,62 @@
37
30
  "winner": "Draft (1 vote / 1 total)"
38
31
  },
39
32
  "Baden Hallucinations": {
40
- "winner": "Draft (0 votes / 0 total)"
33
+ "winner": "Draft (2 votes / 2 total)"
41
34
  },
42
35
  "Kópavogur Seals": {
43
- "winner": "Big Gamble (0 votes / 0 total)"
36
+ "winner": "Please Block Shots (0 votes / 0 total)"
44
37
  },
45
38
  "Lagos Soup": {
46
39
  "winner": "Small Gamble (0 votes / 0 total)"
47
40
  },
48
41
  "Pica Acid": {
49
- "winner": "Please Block Shots (2 votes / 2 total)"
42
+ "winner": "Big Gamble (0 votes / 0 total)"
50
43
  },
51
44
  "Dawson City Impostors": {
52
- "winner": "Draft (4 votes / 4 total)"
45
+ "winner": "Please Block Shots (2 votes / 5 total)"
53
46
  },
54
47
  "Erlangen Ohms": {
55
- "winner": "Please Win Faceoffs (1 vote / 2 total)"
48
+ "winner": "Clock Wise (1 vote / 1 total)"
56
49
  },
57
50
  "Pompei Eruptions": {
58
- "winner": "Please Win Faceoffs (0 votes / 0 total)"
51
+ "winner": "Please Win Faceoffs (1 vote / 1 total)"
59
52
  },
60
53
  "Rio de Janeiro Directors": {
61
- "winner": "Please Win Faceoffs (1 vote / 1 total)"
54
+ "winner": "Please Win Faceoffs (3 votes / 3 total)"
62
55
  },
63
56
  "Wyrzysk Rockets": {
64
- "winner": "Big Gamble (0 votes / 0 total)"
57
+ "winner": "Revolution (0 votes / 0 total)"
65
58
  },
66
59
  "Cape Town Transplants": {
67
- "winner": "Draft (1 vote / 2 total)"
60
+ "winner": "Small Gamble (0 votes / 0 total)"
68
61
  },
69
62
  "Manbij Fish": {
70
- "winner": "Draft (1 vote / 1 total)"
63
+ "winner": "Clock Wise (0 votes / 0 total)"
71
64
  },
72
65
  "Nagqu Paint": {
73
- "winner": "Draft (1 vote / 1 total)"
66
+ "winner": "Please Win Faceoffs (1 vote / 1 total)"
74
67
  },
75
68
  "Nice Backflippers": {
76
- "winner": "Draft (1 vote / 1 total)"
69
+ "winner": "Please Block Shots (1 vote / 1 total)"
77
70
  },
78
71
  "Orcadas Base Fog": {
79
- "winner": "Draft (2 votes / 2 total)"
72
+ "winner": "Small Gamble (1 vote / 1 total)"
80
73
  },
81
74
  "Baghdad Abacuses": {
82
- "winner": "Clock Unwise (0 votes / 0 total)"
75
+ "winner": "Please Win Faceoffs (0 votes / 0 total)"
83
76
  },
84
77
  "Jakarta Architects": {
85
- "winner": "Clock Wise (0 votes / 0 total)"
78
+ "winner": "Please Win Faceoffs (0 votes / 0 total)"
86
79
  },
87
80
  "Kyoto Payphones": {
88
- "winner": "Small Gamble (1 vote / 2 total)"
81
+ "winner": "Big Gamble (6 votes / 6 total)"
89
82
  },
90
83
  "Stony Brook Reapers": {
91
- "winner": "Please Win Faceoffs (1 vote / 1 total)"
84
+ "winner": "Clock Unwise (1 vote / 1 total)"
92
85
  },
93
86
  "Sydney Thinkers": {
94
- "winner": "Clock Wise (7 votes / 7 total)"
87
+ "winner": "Draft (3 votes / 4 total)"
95
88
  }
96
89
  }
97
90
  }
98
- }
91
+ }
@@ -1,5 +1,6 @@
1
1
  require("hlockey/actions")
2
2
  require("hlockey/message")
3
+ require("hlockey/mod/punchy")
3
4
 
4
5
  module Hlockey
5
6
  class Game
@@ -8,21 +9,20 @@ module Hlockey
8
9
  class Fight
9
10
  include(Actions)
10
11
 
11
- # @return [Hash<Symbol => Array<Player>>] the players in the fight
12
+ # @return [Hash<Symbol => Array<Team::Player>>] the players in the fight
12
13
  attr_reader(:players)
13
14
 
14
15
  # @return [Hash<Symbol => Integer>] the amount of successful punches for each team
15
16
  attr_reader(:score)
16
17
 
17
18
  # @param game [Game] the game the fight is a part of
19
+ # @param starting_player [Team::Player] the player that started the fight, if any
18
20
  def initialize(game, starting_player = nil)
19
- @home = game.home
20
- @away = game.away
21
- @prng = game.prng
21
+ @game = game
22
22
  @actions = 0
23
23
  @players = { home: [], away: [] }
24
24
  @players.each_key do |team|
25
- add_player(if send(team).roster.value?(starting_player)
25
+ add_player(if @game.send(team).roster.value?(starting_player)
26
26
  starting_player
27
27
  else
28
28
  get_joining_player(team)
@@ -33,11 +33,19 @@ module Hlockey
33
33
  @score = { home: 0, away: 0 }
34
34
  end
35
35
 
36
- # @return [Message] the message to add to the game stream
37
36
  def next_action
38
37
  @actions += 1
39
38
 
40
- case @prng.rand(@actions)
39
+ # If fight has a single player on one side who is outnumbered,
40
+ # there is a chance that player will withdraw, ending the fight.
41
+ if @players[:home].length == 1
42
+ return if @players[:away].length > 1 && player_withdraws?(@players[:home].first,
43
+ :home)
44
+ elsif @players[:away].length == 1
45
+ return if player_withdraws?(@players[:away].first, :away)
46
+ end
47
+
48
+ case @game.prng.rand(@actions)
41
49
  when 0..3 # attack
42
50
  attack
43
51
  when 4..7 # player joins
@@ -47,52 +55,93 @@ module Hlockey
47
55
  if player_joining.nil?
48
56
  team_joining = opposite(team_joining)
49
57
  player_joining = get_joining_player(team_joining)
50
- return attack if player_joining.nil?
58
+ if player_joining.nil?
59
+ attack
60
+ return
61
+ end
51
62
  end
52
63
 
53
64
  add_player(player_joining, team_joining)
54
65
  else # fight ends
55
- Message.FightEnded
66
+ @game.stream << Message.new(:fight_end)
56
67
  end
57
68
  end
58
69
 
59
70
  private
60
71
 
61
- # private readers so #send works
62
- # @return [Team] a team in the fight
63
- attr_reader(:home, :away)
64
-
65
- # @return [Message] returned by #next_action for same purpose
66
72
  def attack
67
73
  attacking_team = rand_team
68
74
  defending_team = opposite(attacking_team)
69
75
 
70
- attacking_player = @players[attacking_team].sample(random: @prng)
71
- defending_player = @players[defending_team].sample(random: @prng)
72
-
73
- blocked = action_succeeds?(defending_player.stats[:defense],
74
- attacking_player.stats[:offense])
75
-
76
- @score[attacking_team] += 1 unless blocked
76
+ attacking_player = @players[attacking_team].sample(random: @game.prng)
77
+ @game.stream << Message.new(:fight_attack, player: attacking_player)
78
+
79
+ defending_player = @players[defending_team].sample(random: @game.prng)
80
+
81
+ if action_succeeds?(defending_player.stats[:defense],
82
+ defending_player.stats[:agility],
83
+ prng: @game.prng)
84
+ # Try to block the punch
85
+ if action_succeeds?(defending_player.stats[:defense],
86
+ attacking_player.stats[:offense],
87
+ prng: @game.prng)
88
+ # Punch sucessfully blocked
89
+ @game.stream << Message.new(:fight_block, player: defending_player)
90
+ return
91
+ end
92
+ # Try to dodge the punch
93
+ elsif action_succeeds?(defending_player.stats[:agility],
94
+ attacking_player.stats[:offense],
95
+ prng: @game.prng)
96
+ # Punch sucessfully dodged
97
+ @game.stream << Message.new(:fight_dodge, player: defending_player)
98
+ return
99
+ end
77
100
 
78
- Message.FightAttack(attacking_player, defending_player, blocked)
101
+ # Punch lands
102
+ @game.stream << Message.new(:fight_hit, player: defending_player)
103
+ @score[attacking_team] += 1
104
+ player_withdraws?(defending_player, defending_team)
79
105
  end
80
106
 
81
107
  # @param team [:home, :away]
82
108
  # @return [Team::Player, nil]
83
109
  def get_joining_player(team) =
84
- (send(team).roster.values - @players[team]).sample(random: @prng)
110
+ (@game.send(team).roster.values - @players[team]).sample(random: @game.prng)
85
111
 
86
112
  # @param player [Team::Player]
87
113
  # @param team [:home, :away]
88
- # @return [Message] the join message
89
114
  def add_player(player, team)
115
+ @game.stream << Message.new(:fight_player_join, player:, team: player.team)
116
+
90
117
  mods_res = player.mods_do(:on_join_fight)
91
- player = mods_res if mods_res
118
+ if mods_res # Mod would return a joining player to replace them
119
+ @game.stream << Message.new(:fight_player_withdraw, player:)
120
+ player = mods_res
121
+ @game.stream << Message.new(:fight_player_join, player:, team: player.team)
122
+ end
92
123
 
93
124
  @players[team] << player
125
+ end
126
+
127
+ # @param player [Team::Player]
128
+ # @param team [:home, :away]
129
+ # @return [Boolean] if the player withdrew
130
+ def player_withdraws?(player, team)
131
+ return false unless player.mods.none? { _1.is_a?(Mod::Punchy) } &&
132
+ @game.prng.rand(50).zero?
133
+
134
+ # Player withdraws
135
+ @game.stream << Message.new(:fight_player_withdraw, player:)
136
+ @players[team].delete(player)
137
+
138
+ if @players[team].empty?
139
+ @game.stream << Message.new(:fight_end)
140
+ @score[team] = 0
141
+ @score[opposite(team)] = 10
142
+ end
94
143
 
95
- Message.PlayerJoinedFight(player)
144
+ true
96
145
  end
97
146
 
98
147
  # @return [:home, :away] randomly selected based on amount of players in fight
@@ -104,10 +153,10 @@ module Hlockey
104
153
 
105
154
  # @return [Boolean] if randomly selected team is home team
106
155
  def rand_is_home?
107
- home_player_amount = @home.roster.values.length
108
- away_player_amount = @away.roster.values.length
156
+ home_player_amount = @game.home.roster.values.length
157
+ away_player_amount = @game.away.roster.values.length
109
158
 
110
- @prng.rand(home_player_amount + away_player_amount) < home_player_amount
159
+ @game.prng.rand(home_player_amount + away_player_amount) < home_player_amount
111
160
  end
112
161
  end
113
162
  end
@@ -29,7 +29,8 @@ module Hlockey
29
29
 
30
30
  @chickened_out[team][pos] = shadows_idx
31
31
 
32
- @game.stream << Message.ChickenedOut(*swap(team, pos, shadows_idx))
32
+ @game.stream << Message.new(:weather_chicken_event,
33
+ **swap(team, pos, shadows_idx))
33
34
  end
34
35
 
35
36
  def on_game_end
@@ -24,7 +24,8 @@ module Hlockey
24
24
  def on_action
25
25
  return unless @incline_changed
26
26
 
27
- @game.stream << Message.InclineFavors(@game.send(@favored_team))
27
+ @game.stream << Message.new(:weather_incline_event,
28
+ team: @game.send(@favored_team))
28
29
  @incline_changed = false
29
30
  end
30
31
 
@@ -15,7 +15,7 @@ module Hlockey
15
15
 
16
16
  team = @game.score.min_by { |_, v| v }.first
17
17
  @game.score[team] += 0.5
18
- @game.stream << Message.StarsAlign(@game.send(team))
18
+ @game.stream << Message.new(:weather_stars_event, team: @game.send(team))
19
19
  end
20
20
  end
21
21
  end
@@ -9,9 +9,7 @@ module Hlockey
9
9
  class Sunset
10
10
  include(Weatherable)
11
11
 
12
- def on_game_start
13
- @score_amt = { home: 0, away: 0 }
14
- end
12
+ def on_game_start = @score_amt = { home: 0, away: 0 }
15
13
 
16
14
  def on_goal(scoring_team)
17
15
  @score_amt[scoring_team] += 1
@@ -17,15 +17,13 @@ module Hlockey
17
17
 
18
18
  team_sym = rand_team
19
19
  team = @game.send(team_sym)
20
- @game.stream << Message.WavesWashedAway(
21
- *swap(team_sym,
22
- if @prng.rand(5).zero?
23
- team.roster.keys.sample(random: @prng)
24
- else
25
- team.worst_player_pos
26
- end,
27
- @prng.rand(team.shadows.length))
28
- )
20
+ player_leaving_pos = if @prng.rand(5).zero?
21
+ team.roster.keys.sample(random: @prng)
22
+ else
23
+ team.worst_player_pos
24
+ end
25
+ swap_res = swap(team_sym, player_leaving_pos, @prng.rand(team.shadows.length))
26
+ @game.stream << Message.new(:weather_waves_event, **swap_res)
29
27
  end
30
28
  end
31
29
  end
@@ -33,7 +33,7 @@ module Hlockey
33
33
  # @param team_sym [:home, :away]
34
34
  # @param pos [Symbol] position of roster player swapped out
35
35
  # @param shadows_idx [Integer] index of shadows player swapped in
36
- # @return [Array<Team::Player>] the players that were swapped
36
+ # @return [Hash<[:prev_player, :next_player] => Team::Player>] the swapped players
37
37
  def swap(team_sym, pos, shadows_idx)
38
38
  team = @game.send(team_sym)
39
39
 
@@ -49,10 +49,10 @@ module Hlockey
49
49
  player_array[player_idx] = next_player unless player_idx.nil?
50
50
  end
51
51
 
52
- prev_player.mods_do(:on_swap, false, shadows_idx, pos, @prng)
53
- next_player.mods_do(:on_swap, true, pos, shadows_idx, @prng)
52
+ prev_player.mods_do(:on_swap, false, shadows_idx, pos)
53
+ next_player.mods_do(:on_swap, true, pos, shadows_idx)
54
54
 
55
- [prev_player, next_player]
55
+ { prev_player:, next_player: }
56
56
  end
57
57
 
58
58
  # @return [:home, :away]