hlockey 6 → 7

Sign up to get free protection for your applications and to get access to all the features.
@@ -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]