chichilku3 5.0.1 → 14.0.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6eb2d898a5e9000e8d403b3095dc0f11b32ffcf6299636cce5f5ecbf0986e4d1
4
- data.tar.gz: 65a511ba7ef525ca52f9ee961d9478bd2aa15b8a0ee0078bcd5e1535460a917e
3
+ metadata.gz: 0e76757297dc1c7f9103fc505a4e6dc4983489f71c568a7f494dcd510df87a6c
4
+ data.tar.gz: 48321cf98b07848de50e286a3367fa10669f6b00bd173ba414d54e9af5f8c243
5
5
  SHA512:
6
- metadata.gz: 1f3c0294308be6d225b4a823d0cfffab0e669be8dab873da74517921bff83e453c1375d9dfe14ff254ff418109b45f4fe4a9d5d9ae88058258ff61a22c3eaddb
7
- data.tar.gz: f83514aa1de0afdce1880e3ed72294aa2f79a5ff605de76627b70d6a87430bd973dddcf665ef19b5b1314f561d963a5adb00e7499297e455b22c87173e2bf839
6
+ metadata.gz: 04261a4e08b759e26e26a734295ab9d1d2a412fb548d027839a81371d896d3044148317c9e0596ea7209297162068de7b3a6ead2598f8a571f7ba007e0ff9ac6
7
+ data.tar.gz: 0d8d25f82fc2c97ffecedc148434bdae9e34d38fd8a3809f803845385460f7c09a1ead35d7387369fd30115842d7c81c06c6ee169f24371206f85549ea2ee89b
@@ -2,5 +2,6 @@
2
2
  "ip": "localhost",
3
3
  "port": 9900,
4
4
  "username": "00000000",
5
- "fullscreen": false
5
+ "fullscreen": false,
6
+ "autorecord": false
6
7
  }
@@ -7,10 +7,11 @@ STATE_MENU = -1
7
7
  STATE_OFFLINE = 0
8
8
  STATE_CONNECTING = 1
9
9
  STATE_INGAME = 2
10
+ STATE_REC_PLAYBACK = 3
10
11
 
11
12
  # Networking part of the game clientside
12
13
  class Client
13
- attr_reader :id, :state
14
+ attr_reader :id, :state, :server_version
14
15
  def initialize(console, cfg)
15
16
  @id = nil
16
17
  @tick = 0
@@ -22,6 +23,13 @@ class Client
22
23
 
23
24
  @s = nil # network socket (set in connect() method)
24
25
 
26
+ @recording_ticks = []
27
+ @recording_ticks_len = 0
28
+ @recording_file = "autorec.txt"
29
+ @is_recording = false
30
+
31
+ @server_version = nil
32
+
25
33
  # state variables
26
34
  @req_playerlist = Time.now - 8
27
35
 
@@ -43,16 +51,65 @@ class Client
43
51
  @s = TCPSocket.open(ip, port)
44
52
  @s.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1) # nagle's algorithm-
45
53
  @state = STATE_CONNECTING
54
+ start_recording() if @cfg.data['autorecord']
46
55
  end
47
56
 
48
57
  def disconnect()
49
58
  return if @state == STATE_MENU
59
+
50
60
  @console.log "disconnecting from server."
51
61
  @s.close
52
62
  @s = nil
53
63
  reset
54
64
  end
55
65
 
66
+ def load_recording(recording_file)
67
+ recording_file = "#{@cfg.chichilku3_dir}recordings/#{recording_file}"
68
+ @recording_ticks = []
69
+ @tick = 0
70
+ update_state(STATE_REC_PLAYBACK)
71
+ File.readlines(recording_file).each do |data|
72
+ @recording_ticks << data[0..-2] # cut off newline
73
+ end
74
+ # TODO: check if this .length lookup eats performance in ruby
75
+ @recording_ticks_len = @recording_ticks.length
76
+ @console.log "loaded recording containing #{@recording_ticks.size} ticks"
77
+ end
78
+
79
+ def start_recording()
80
+ @recording_file = "autorec.txt"
81
+ rec_file = "#{@cfg.chichilku3_dir}recordings/#{@recording_file}"
82
+ @is_recording = true
83
+ File.delete(rec_file) if File.exists? rec_file
84
+ end
85
+
86
+ def recording_record_tick(data)
87
+ return unless @is_recording
88
+
89
+ recording_file = "#{@cfg.chichilku3_dir}recordings/#{@recording_file}"
90
+ IO.write(recording_file, data + "\n", mode: 'a')
91
+ end
92
+
93
+ def recording_playback_tick()
94
+ if @recording_ticks_len <= @tick
95
+ @console.log "finished playing back recording"
96
+ update_state(STATE_MENU)
97
+ return [[], @flags, nil]
98
+ end
99
+ data = @recording_ticks[@tick]
100
+ if data.length != SERVER_PACKAGE_LEN
101
+ @console.err "failed to parse recording data=#{data.length} server=#{SERVER_PACKAGE_LEN}"
102
+ return nil
103
+ end
104
+
105
+ @tick += 1
106
+ @flags[:skip] = false
107
+
108
+ # save protocol and cut it off
109
+ msg = handle_protocol(data[0].to_i, data[1], data[2..-1])
110
+ [@players, @flags, msg, [@tick, @recording_ticks_len]]
111
+ end
112
+
56
113
  def tick(client_data, protocol, tick)
57
114
  return nil if @state == STATE_MENU
58
115
 
@@ -67,8 +124,7 @@ class Client
67
124
  data = fetch_server_data
68
125
  return nil if data.nil?
69
126
 
70
- # only process the long packages and ignore ip packages here
71
- return nil if data.length != SERVER_PACKAGE_LEN
127
+ recording_record_tick(data)
72
128
 
73
129
  # save protocol and cut it off
74
130
  msg = handle_protocol(data[0].to_i, data[1], data[2..-1])
@@ -129,24 +185,20 @@ class Client
129
185
  if @id.nil?
130
186
  # request id has priority
131
187
  # resend after 100 ticks if no respond
132
- name = @cfg.data['username'].ljust(5, '-')
133
- net_write("1l#{name}") if (@tick % 200).zero?
188
+ net_write("1l#{GAME_VERSION}XXXXX") if (@tick % 200).zero?
134
189
  return
135
190
  end
136
191
 
137
192
  # if no playerlist yet -> request one
138
193
  if @players == [] && @req_playerlist < Time.now - 4
139
- net_write("3l#{id}#{GAME_VERSION}")
194
+ name = @cfg.data['username'].ljust(NAME_LEN, ' ')
195
+ net_write("3l#{name}")
140
196
  @console.log('requesting a playerlist')
141
197
  @req_playerlist = Time.now
142
198
  return
143
199
  end
144
200
 
145
- # prefix data with id
146
- # prot 2 = update pck
147
- # prot updated to dynamic becuase we now also send cmds
148
- # data = format("#{protocol}l%02d#{data.join('')}", @id) # old 2byte id
149
- data = "#{protocol}l#{@id}#{data.join('')}" # new 1byte id
201
+ data = "#{protocol}l#{@id.to_s(16)}#{data.join('')}"
150
202
  net_write(data)
151
203
  end
152
204
 
@@ -163,10 +215,10 @@ class Client
163
215
 
164
216
  def grab_id(data)
165
217
  @console.log 'Trying to read id...'
166
- @playercount = data[0..1]
167
- id = data[2..3].to_i
218
+ @playercount = net_unpack_int(data[0..1])
219
+ id = data[2].to_i(16)
168
220
  set_id(id)
169
- update_state(STATE_INGAME)
221
+ update_state(STATE_INGAME) unless @state == STATE_REC_PLAYBACK
170
222
  end
171
223
 
172
224
  def id_packet(data)
@@ -178,12 +230,20 @@ class Client
178
230
  end
179
231
 
180
232
  def get_server_version(data)
181
- server_version = data[4..8]
182
- @console.log "server version='#{server_version}'"
233
+ @server_version = data[4..7]
234
+ @console.log "server version='#{@server_version}'"
183
235
  end
184
236
 
185
237
  def fetch_server_data
186
- server_data = save_read(@s, SERVER_PACKAGE_LEN)
238
+ server_data = save_read(@s, 3)
239
+ return nil if server_data == ''
240
+
241
+ if server_data[0] == "1"
242
+ len = net_unpack_int(server_data[2]) * PLAYER_PACKAGE_LEN
243
+ server_data += save_read(@s, len+1)
244
+ else
245
+ server_data += save_read(@s, SERVER_PACKAGE_LEN-3)
246
+ end
187
247
  return nil if server_data == ''
188
248
 
189
249
  @console.dbg "recived data: #{server_data}"
@@ -207,17 +267,18 @@ class Client
207
267
  # And its dependencies:
208
268
  def protocol_names(data)
209
269
  # 3 0 00 00000 00 00000 00 00000 000
210
- playercount = data[0].to_i
270
+ playercount = net_unpack_int(data[0])
211
271
  @flags[:gamestate] = data[1]
212
272
  data = data[2..-1]
213
273
  p_strs = protocol_names_to_player_strs(playercount, data)
214
274
  protocol_names_strs_to_objs(p_strs)
215
275
  end
216
276
 
217
- def protocol_names_to_player_strs(slots, data)
277
+ def protocol_names_to_player_strs(used_slots, data)
218
278
  players = []
219
- slots.times do |index|
220
- players[index] = data[index * 7..index * 7 + 6]
279
+ used_slots.times do |index|
280
+ size = NAME_LEN + 2 # id|score|name
281
+ players[index] = data[index * size..index * size + size-1]
221
282
  end
222
283
  players
223
284
  end
@@ -225,7 +286,7 @@ class Client
225
286
  def protocol_names_strs_to_objs(player_strs)
226
287
  players = []
227
288
  player_strs.each do |player_str|
228
- id = player_str[0].to_i
289
+ id = player_str[0].to_i(16)
229
290
  score = net_unpack_int(player_str[1])
230
291
  name = player_str[2..-1]
231
292
  players << Player.new(id, 0, 0, score, name) unless id.zero?
@@ -241,20 +302,20 @@ class Client
241
302
  def server_package_to_player_array(data)
242
303
  # /(?<count>\d{2})(?<player>(?<id>\d{2})(?<x>\d{3})(?<y>\d{3}))/
243
304
  # @console.log "data: #{data}"
244
- slots = data[0].to_i # save occupado slots
305
+ used_slots = net_unpack_int(data[0]) # save occupado slots
245
306
  # gamestate = data[1].to_i # save gamestate
246
307
  @flags[:gamestate] = data[1]
247
308
  # @console.log "gamestate: " + @flags[:gamestate]
248
309
  data = data[2..-1] # cut slots and gamestate off
249
- players = server_package_to_player_strs(slots, data)
310
+ players = server_package_to_player_strs(used_slots, data)
250
311
  # @console.log "players: \n#{players}"
251
312
  player_strs_to_objects(players)
252
313
  end
253
314
 
254
- def server_package_to_player_strs(slots, data)
315
+ def server_package_to_player_strs(used_slots, data)
255
316
  players = []
256
- slots.times do |index|
257
- players[index] = data[index * 8..index * 8 + 7]
317
+ used_slots.times do |index|
318
+ players[index] = data[index * PLAYER_PACKAGE_LEN..index * PLAYER_PACKAGE_LEN + PLAYER_PACKAGE_LEN-1]
258
319
  end
259
320
  players
260
321
  end
@@ -262,13 +323,17 @@ class Client
262
323
  def player_strs_to_objects(player_strs)
263
324
  players = []
264
325
  player_strs.each do |player_str|
265
- id = player_str[0].to_i
326
+ id = player_str[0].to_i(16)
266
327
  score = net_unpack_int(player_str[1])
267
- unused = player_str[2]
268
- net_state = player_str[3]
269
- x = net_unpack_bigint(player_str[4..5])
270
- y = net_unpack_bigint(player_str[6..7])
271
- # puts "id: #{id} x: #{x} y: #{y}"
328
+ net_state = player_str[2]
329
+ projR = player_str[3]
330
+ projX = net_unpack_bigint(player_str[4..5])
331
+ projY = net_unpack_bigint(player_str[6..7])
332
+ aimX = net_unpack_bigint(player_str[8..9])
333
+ aimY = net_unpack_bigint(player_str[10..11])
334
+ x = net_unpack_bigint(player_str[12..13])
335
+ y = net_unpack_bigint(player_str[14..15])
336
+ # puts "'#{player_str}' id: #{id} x: #{x} '#{player_str[12..13]}' y: #{y} '#{player_str[14..15]}'"
272
337
  # players << Player.new(id, x, y) unless id.zero?
273
338
 
274
339
  @console.dbg "-- updt player id=#{id} score=#{score}--"
@@ -278,7 +343,10 @@ class Client
278
343
  next if p_index.nil?
279
344
 
280
345
  @console.dbg "got player: #{@players[p_index]}"
281
- new_player = Player.update_player(@players, id, x, y, score)
346
+ new_player = Player.update_player(@players, id, x, y, score, aimX, aimY)
347
+ new_player.projectile.r = projR
348
+ new_player.projectile.x = projX
349
+ new_player.projectile.y = projY
282
350
  new_player.net_to_state(net_state)
283
351
  @players[Player.get_player_index_by_id(@players, id)] = new_player
284
352
  end
@@ -2,7 +2,7 @@ require 'json'
2
2
  require_relative '../share/network'
3
3
  require_relative '../share/config'
4
4
 
5
- # The client side repository usign JSON
5
+ # The client side repository using JSON
6
6
  class ClientCfg < Config
7
7
  def sanitize_data(data)
8
8
  data = JSON.parse(File.read(@file))
@@ -26,6 +26,8 @@ MENU_MAIN = 0
26
26
  MENU_CONNECT = 1
27
27
  MENU_USERNAME = 2
28
28
 
29
+ MOUSE_RADIUS = 200
30
+
29
31
  $time_point=Time.now
30
32
  $time_buffer=0
31
33
 
@@ -42,10 +44,16 @@ class Gui < Gosu::Window
42
44
  self.caption = 'chichilku3'
43
45
  self.fullscreen = true if cfg.data['fullscreen']
44
46
  # images
47
+ @crosshair = Gosu::Image.new(img("crosshair128x128.png"))
45
48
  @background_image = Gosu::Image.new(img("battle1024x576.png"))
46
49
  @connecting_image = Gosu::Image.new(img("connecting1024x512.png"))
47
50
  @menu_image = Gosu::Image.new(img("menu1920x1080.png"))
48
- @stick = Gosu::Image.new(img("stick128/stick0.png"))
51
+ @arrow_image = Gosu::Image.new(img("arrow64.png"))
52
+ @stick_arm_images = []
53
+ @stick_arm_images << Gosu::Image.new(img("stick128/arm64/arm0.png"))
54
+ @stick_arm_images << Gosu::Image.new(img("stick128/arm64/arm1.png"))
55
+ @stick_arm_images << Gosu::Image.new(img("stick128/arm64/arm2.png"))
56
+ @stick_arm_images << Gosu::Image.new(img("stick128/arm64/arm3.png"))
49
57
  @stick_crouching = []
50
58
  @stick_crouching << Gosu::Image.new(img("stick128/stick_crouching0.png"))
51
59
  @stick_crouching << Gosu::Image.new(img("stick128/stick_crouching1.png"))
@@ -54,12 +62,23 @@ class Gui < Gosu::Window
54
62
  @stick_crouching << Gosu::Image.new(img("stick128/stick_crouching4.png"))
55
63
  @stick_crouching << Gosu::Image.new(img("stick128/stick_crouching5.png"))
56
64
  @stick_images = []
57
- @stick_images << Gosu::Image.new(img("stick128/stick0.png"))
58
- @stick_images << Gosu::Image.new(img("stick128/stick1.png"))
59
- @stick_images << Gosu::Image.new(img("stick128/stick2.png"))
60
- @stick_images << Gosu::Image.new(img("stick128/stick3.png"))
61
- @stick_images << Gosu::Image.new(img("stick128/stick4.png"))
62
- @stick_images << Gosu::Image.new(img("stick128/stick5.png"))
65
+ @stick_images << Gosu::Image.new(img("stick128/stick_noarms.png"))
66
+ @stick_images << Gosu::Image.new(img("stick128/stick_noarms.png"))
67
+ @stick_images << Gosu::Image.new(img("stick128/stick_noarms.png"))
68
+ @stick_images << Gosu::Image.new(img("stick128/stick_noarms.png"))
69
+ @stick_images << Gosu::Image.new(img("stick128/stick_noarms.png"))
70
+ @bow_images = []
71
+ @bow_images << Gosu::Image.new(img("bow64/bow0.png"))
72
+ @bow_images << Gosu::Image.new(img("bow64/bow1.png"))
73
+ @bow_images << Gosu::Image.new(img("bow64/bow2.png"))
74
+ @bow_images << Gosu::Image.new(img("bow64/bow3.png"))
75
+ # TODO: add arms back in if no bow is in use
76
+ # @stick_images << Gosu::Image.new(img("stick128/stick0.png"))
77
+ # @stick_images << Gosu::Image.new(img("stick128/stick1.png"))
78
+ # @stick_images << Gosu::Image.new(img("stick128/stick2.png"))
79
+ # @stick_images << Gosu::Image.new(img("stick128/stick3.png"))
80
+ # @stick_images << Gosu::Image.new(img("stick128/stick4.png"))
81
+ # @stick_images << Gosu::Image.new(img("stick128/stick5.png"))
63
82
  @x = 0
64
83
  @y = 0
65
84
  @players = []
@@ -85,6 +104,7 @@ class Gui < Gosu::Window
85
104
  @menu_items = []
86
105
  @selected_menu_item = 0
87
106
  @menu_textfield = TextField.new(self, 60, 200)
107
+ @demo_ticks = [0,0]
88
108
  # @chat_inp_stream = nil #TextInput.new
89
109
  # @chat_inp_stream.text # didnt get it working <--- nobo xd
90
110
 
@@ -93,6 +113,11 @@ class Gui < Gosu::Window
93
113
  # depreciated ._.
94
114
  # @con_msg = Gosu::Image.from_text(self, "connecting to #{@cfg.data['ip']}:#{@cfg.data['port']}...", Gosu.default_font_name, 45)
95
115
  init_menu()
116
+
117
+ if ARGV.length > 0
118
+ port = ARGV.length > 1 ? ARGV[1].to_i : 9900
119
+ connect(ARGV[0], port)
120
+ end
96
121
  end
97
122
 
98
123
  def img(path)
@@ -187,7 +212,7 @@ class Gui < Gosu::Window
187
212
  ip = @menu_textfield.text.split(":")
188
213
  @cfg.data['ip'] = ip[0]
189
214
  @cfg.data['port'] = ip[1] if ip.length > 1
190
- connect
215
+ connect(@cfg.data['ip'], @cfg.data['port'])
191
216
  end
192
217
  else
193
218
  @last_key = nil
@@ -221,17 +246,21 @@ class Gui < Gosu::Window
221
246
  @state = STATE_MENU
222
247
  @net_client.disconnect
223
248
  return
249
+ elsif @state == STATE_REC_PLAYBACK
250
+ @state = STATE_MENU
251
+ return
224
252
  end
225
253
  end
226
254
  net_request = '0000'.split('')
255
+ net_request << "!!!!"
227
256
  protocol = 2
228
257
 
229
258
  if @is_chat
230
259
  msg = chat_tick
231
260
  if !msg.nil?
232
261
  # @console.dbg "rawmsg: #{msg}"
233
- msg = msg.ljust(4, '0')
234
- net_request = msg[0..3].split('')
262
+ msg = msg.ljust(8, '0')
263
+ net_request = msg[0..CMD_LEN].split('')
235
264
  # @console.dbg "prepedmsg: #{net_request}"
236
265
  protocol = 4
237
266
  end
@@ -241,13 +270,13 @@ class Gui < Gosu::Window
241
270
  net_request[0] = '1'
242
271
  end
243
272
  if button_down?(KEY_A)
244
- net_request[1] = '1'
273
+ net_request[1] = 'l'
245
274
  end
246
275
  if button_down?(KEY_D)
247
- net_request[2] = '1'
276
+ net_request[1] = 'r'
248
277
  end
249
278
  if button_down?(Gosu::KB_SPACE)
250
- net_request[3] = '1'
279
+ net_request[2] = '1'
251
280
  end
252
281
  if button_press?(KEY_M)
253
282
  @is_debug = !@is_debug
@@ -257,15 +286,27 @@ class Gui < Gosu::Window
257
286
  @is_chat = true
258
287
  @chat_msg = ""
259
288
  end
289
+ if button_down?(Gosu::MsLeft)
290
+ net_request[3] = '1'
291
+ end
292
+ # TODO: check for active window
293
+ # do not leak mouse movement in other applications than chichilku3
294
+ net_request[4] = net_pack_bigint(self.mouse_x.to_i.clamp(0, 8834), 2)
295
+ net_request[5] = net_pack_bigint(self.mouse_y.to_i.clamp(0, 8834), 2)
260
296
  @is_scoreboard = button_down?(Gosu::KB_TAB)
261
297
  end
262
298
 
263
- # Networking
264
- begin
265
- net_data = @net_client.tick(net_request, protocol, @tick)
266
- rescue Errno::ECONNRESET, Errno::EPIPE
267
- net_data = [@players, @flags, [0, NET_ERR_DISCONNECT, "connection to server lost"]]
268
- @net_client.disconnect
299
+ if @state == STATE_REC_PLAYBACK
300
+ net_data = @net_client.recording_playback_tick()
301
+ @demo_ticks = net_data[3] unless net_data.nil?
302
+ else
303
+ # Networking
304
+ begin
305
+ net_data = @net_client.tick(net_request, protocol, @tick)
306
+ rescue Errno::ECONNRESET, Errno::EPIPE
307
+ net_data = [@players, @flags, [0, NET_ERR_DISCONNECT, "connection to server lost"]]
308
+ @net_client.disconnect
309
+ end
269
310
  end
270
311
  return if net_data.nil?
271
312
 
@@ -353,6 +394,13 @@ class Gui < Gosu::Window
353
394
  @events[:blood] = bloods
354
395
  end
355
396
 
397
+ def draw_debug(x, y, s=1)
398
+ return unless @is_debug
399
+
400
+ draw_rect(x, y, 4*s, 4*s, 0xFFFF0000, 1)
401
+ draw_rect(x+1*s, y+1*s, 2*s, 2*s, 0xFF00FF00, 1)
402
+ end
403
+
356
404
  def draw
357
405
  # draw_quad(0, 0, 0xffff8888, WINDOW_SIZE_X, WINDOW_SIZE_Y, 0xffffffff, 0, 0, 0xffffffff, WINDOW_SIZE_X, WINDOW_SIZE_Y, 0xffffffff, 0)
358
406
  if @state == STATE_MENU
@@ -369,22 +417,61 @@ class Gui < Gosu::Window
369
417
  end
370
418
  elsif @state == STATE_CONNECTING
371
419
  @connecting_image.draw(0, 0, 0)
372
- @font.draw_text("connecting to #{@cfg.data['ip']}:#{@cfg.data['port']}...", 20, 20, 0, 2, 5)
420
+ @font.draw_text("connecting to #{@cfg.data['ip']}:#{@cfg.data['port']}...", 20, 20, 0, 3, 3)
373
421
  # @con_msg.draw(100,200,0)
374
- elsif @state == STATE_INGAME
422
+ elsif @state == STATE_INGAME || @state == STATE_REC_PLAYBACK
375
423
  @background_image.draw(0, 0, 0)
424
+ @crosshair.draw(self.mouse_x-16, self.mouse_y-16, 0, 0.25, 0.25)
425
+ # useless mouse trap
426
+ # since its buggo and your character moves maybe keep it free
427
+ # mouse players should go fullscreen
428
+ # self.mouse_x = (WINDOW_SIZE_X / 2) + MOUSE_RADIUS - 1 if self.mouse_x > (WINDOW_SIZE_X / 2) + MOUSE_RADIUS
429
+ # self.mouse_x = (WINDOW_SIZE_X / 2) - MOUSE_RADIUS + 1 if self.mouse_x < (WINDOW_SIZE_X / 2) - MOUSE_RADIUS
430
+ # self.mouse_y = (WINDOW_SIZE_Y / 2) + MOUSE_RADIUS - 1 if self.mouse_y > (WINDOW_SIZE_Y / 2) + MOUSE_RADIUS
431
+ # self.mouse_y = (WINDOW_SIZE_Y / 2) - MOUSE_RADIUS + 1 if self.mouse_y < (WINDOW_SIZE_Y / 2) - MOUSE_RADIUS
376
432
  @players.each do |player|
377
433
  event_blood(player.x, player.y) if player.state[:bleeding]
378
434
  player.draw_tick
379
435
  @console.dbg "drawing player id=#{player.id} pos=#{player.x}/#{player.y}"
380
436
  # draw_rect(player.x, player.y, TILE_SIZE, TILE_SIZE, Gosu::Color::WHITE)
381
- # @stick.draw(player.x, player.y, 0)
382
437
  if player.state[:crouching]
383
438
  @stick_crouching[player.img_index].draw(player.x, player.y, 0, 0.5, 0.5)
384
439
  else
385
440
  @stick_images[player.img_index].draw(player.x, player.y, 0, 0.5, 0.5)
441
+ x = player.aimX - player.x
442
+ y = player.aimY - player.y
443
+ rot = Math.atan2(x, y) * 180 / Math::PI * -1 + 90 * -1
444
+ rot2 = Math.atan2(x, y) * 180 / Math::PI * -1 + 270 * -1
445
+ stick_center_x = player.x + TILE_SIZE/4
446
+ stick_center_y = player.y + TILE_SIZE/2
447
+ d = -8
448
+ d += player.state[:fire] * 3
449
+ arr_x = stick_center_x + (d * Math.cos((rot2 + 180) / 180 * Math::PI))
450
+ arr_y = stick_center_y + (d * Math.sin((rot2 + 180) / 180 * Math::PI))
451
+ @bow_images[player.state[:fire]].draw_rot(stick_center_x, stick_center_y, 0, rot, 0.5, 0.5, 0.5, 0.5)
452
+ @stick_arm_images[player.state[:fire]].draw_rot(stick_center_x, stick_center_y, 0, rot, 0.5, 0.5, 0.5, 0.5)
453
+ if player.projectile.x == 0 and player.projectile.y == 0
454
+ @arrow_image.draw_rot(arr_x, arr_y, 0, rot2, 0.5, 0.5, 0.5, 0.5)
455
+ end
456
+ if @is_debug
457
+ draw_debug(arr_x, arr_y, 2)
458
+ draw_debug(stick_center_x, stick_center_y, 1)
459
+ draw_line(arr_x, arr_y, 0xFFFF0000, stick_center_x, stick_center_y, 0xFF000000)
460
+ @font.draw_text("rot=#{rot.to_i} rot2=#{rot2.to_i}", player.x - 60, player.y - 100, 0, 1, 1, 0xFF000000)
461
+ @font.draw_text("d=#{d} (#{stick_center_x}/#{stick_center_y}) -> (#{arr_x.to_i}/#{arr_y.to_i})", player.x - 80, player.y - 80, 0, 1, 1, 0xFF000000)
462
+ end
463
+ end
464
+ unless player.projectile.x == 0 or player.projectile.y == 0
465
+ rot = player.projectile.r.to_i * 45
466
+ @arrow_image.draw_rot(player.projectile.x, player.projectile.y, 0, rot, 0.5, 0.5, 0.5, 0.5)
386
467
  end
387
468
  if @is_debug # print id
469
+ # aim
470
+ draw_rect(player.aimX - 2, player.aimY - 16, 4, 32, 0xCC33FF33)
471
+ draw_rect(player.aimX - 16, player.aimY - 2, 32, 4, 0xCC33FF33)
472
+ draw_rect(player.aimX, player.aimY - 15, 1, 30, 0xAA000000)
473
+ draw_rect(player.aimX - 15, player.aimY, 30, 1, 0xAA000000)
474
+ # text background
388
475
  draw_rect(player.x - 2, player.y - 60, 32, 20, 0xAA000000)
389
476
  @font.draw_text("#{player.id}:#{player.score}", player.x, player.y - 60, 0, 1, 1)
390
477
  # @font.draw_text("#{player.id}:#{player.img_index}", player.x, player.y - TILE_SIZE * 2, 0, 1, 1)
@@ -393,7 +480,9 @@ class Gui < Gosu::Window
393
480
  else
394
481
  draw_rect(player.x, player.y, TILE_SIZE/2, TILE_SIZE, 0xAA00EE00)
395
482
  end
396
- else
483
+ unless player.projectile.x == 0 or player.projectile.y == 0
484
+ draw_rect(player.projectile.x, player.projectile.y, player.projectile.w, player.projectile.h, 0xAA00EE00)
485
+ end
397
486
  end
398
487
  @font.draw_text(player.name, player.x - (TILE_SIZE/6), player.y - TILE_SIZE / 2, 0, 1, 1, 0xff_000000)
399
488
  end
@@ -411,10 +500,12 @@ class Gui < Gosu::Window
411
500
  if @is_debug
412
501
  player = Player.get_player_by_id(@players, @flags[:id])
413
502
  unless player.nil?
414
- draw_rect(5, 10, 295, 75, 0xAA000000)
503
+ draw_rect(5, 10, 290, 85, 0xAA000000)
415
504
  @font.draw_text("Press m to deactivate debug mode", 10, 10, 0, 1, 1)
416
505
  @font.draw_text("x: #{player.x} y: #{player.y}", 10, 30, 0, 1, 1)
506
+ @font.draw_text("aimX: #{player.aimX} aimY: #{player.aimY}", 10, 45, 0, 1, 1)
417
507
  @font.draw_text("gamestate: #{@flags[:gamestate]}", 10, 60, 0 , 1, 1)
508
+ @font.draw_text("server version: #{@net_client.server_version}", 10, 75, 0 , 1, 1)
418
509
  # thats useless because collide/delta speed is not sent over the network
419
510
  # @font.draw_text("dx: #{player.dx} dy: #{player.dy}", 10, 50, 0, 1, 1)
420
511
  # @font.draw_text(player.collide_string, 10, 70, 0, 1, 1)
@@ -424,7 +515,10 @@ class Gui < Gosu::Window
424
515
  draw_events()
425
516
 
426
517
  if @is_scoreboard
427
- draw_scoreboard(WINDOW_SIZE_X, WINDOW_SIZE_Y, @players, @font)
518
+ draw_scoreboard(WINDOW_SIZE_X, WINDOW_SIZE_Y, @players, @font, @is_debug)
519
+ end
520
+ if @state == STATE_REC_PLAYBACK && !(@demo_ticks.nil?)
521
+ @font.draw_text("#{@demo_ticks[0]}/#{@demo_ticks[1]}", 10, WINDOW_SIZE_Y - 20, 0)
428
522
  end
429
523
  elsif @state == STATE_ERROR
430
524
  net_err_code = @net_err[0]
@@ -445,9 +539,10 @@ class Gui < Gosu::Window
445
539
 
446
540
  private
447
541
 
448
- def connect()
542
+ def connect(ip, port)
543
+ @console.log "connecting to server '#{ip}:#{port}' ..."
449
544
  begin
450
- @net_client.connect(@cfg.data['ip'], @cfg.data['port'])
545
+ @net_client.connect(ip, port)
451
546
  @state = STATE_CONNECTING;
452
547
  @menu_page = MENU_MAIN
453
548
  rescue Errno::ECONNREFUSED
@@ -482,11 +577,17 @@ class Gui < Gosu::Window
482
577
  end
483
578
  end
484
579
 
580
+ def play_recording()
581
+ @net_client.load_recording('autorec.txt')
582
+ @state = STATE_REC_PLAYBACK
583
+ end
584
+
485
585
  def init_menu()
486
586
  @menu_items = []
487
587
  add_menu_item("[c]onnect", Proc.new { connect_menu() })
488
588
  add_menu_item("username", Proc.new { username_page() })
489
589
  add_menu_item("fullscreen", Proc.new { toggle_fullscreen() })
590
+ add_menu_item("recording", Proc.new { play_recording() })
490
591
  add_menu_item("[q]uit", Proc.new { exit() })
491
592
  end
492
593