Xonotic QuakeC
The free, fast arena FPS with crisp movement and a wide array of weapons
nmm.qc
Go to the documentation of this file.
1#include "nmm.qh"
2
3REGISTER_MINIGAME(nmm, _("Nine Men's Morris"));
4
5const int NMM_TURN_PLACE = 0x0100; // player has to place a piece on the board
6const int NMM_TURN_MOVE = 0x0200; // player has to move a piece by one tile
7const int NMM_TURN_FLY = 0x0400; // player has to move a piece anywhere
8const int NMM_TURN_TAKE = 0x0800; // player has to take a non-mill piece
9const int NMM_TURN_TAKEANY=0x1000; // combine with NMM_TURN_TAKE, can take mill pieces
10const int NMM_TURN_WIN = 0x2000; // player has won
11const int NMM_TURN_TYPE = 0xff00;
12const int NMM_TURN_TEAM1 = 0x0001;
13const int NMM_TURN_TEAM2 = 0x0002;
14const int NMM_TURN_TEAM = 0x00ff;
15
16const int NMM_PIECE_DEAD = 0x0; // captured by the enemy
17const int NMM_PIECE_HOME = 0x1; // not yet placed
18const int NMM_PIECE_BOARD = 0x2; // placed on the board
19
20const int NMM_SPECTATOR_TEAM = 255; // must be above max teams and equal to or below 255
21
26
27// build a string containing the indices of the tile to check for a horizontal mill
29{
30 int number = minigame_tile_number(tile.netname);
31 int letter = minigame_tile_letter(tile.netname);
32 if ( number == letter || number+letter == 6 )
33 {
34 int add = letter < 3 ? 1 : -1;
35 return strcat(tile.netname," ",
36 minigame_tile_buildname(letter+add*tile.nmm_tile_distance,number)," ",
37 minigame_tile_buildname(letter+add*2*tile.nmm_tile_distance,number) );
38 }
39 else if ( letter == 3 )
40 return strcat(minigame_tile_buildname(letter-tile.nmm_tile_distance,number)," ",
41 tile.netname," ",
42 minigame_tile_buildname(letter+tile.nmm_tile_distance,number) );
43 else if ( letter < 3 )
47 else
51}
52
53// build a string containing the indices of the tile to check for a vertical mill
55{
56 int letter = minigame_tile_letter(tile.netname);
57 int number = minigame_tile_number(tile.netname);
58 if ( letter == number || letter+number == 6 )
59 {
60 int add = number < 3 ? 1 : -1;
61 return strcat(tile.netname," ",
62 minigame_tile_buildname(letter,number+add*tile.nmm_tile_distance)," ",
63 minigame_tile_buildname(letter,number+add*2*tile.nmm_tile_distance) );
64 }
65 else if ( number == 3 )
66 return strcat(minigame_tile_buildname(letter,number-tile.nmm_tile_distance)," ",
67 tile.netname," ",
68 minigame_tile_buildname(letter,number+tile.nmm_tile_distance) );
69 else if ( number < 3 )
70 return strcat(minigame_tile_buildname(letter,0)," ",
71 minigame_tile_buildname(letter,1)," ",
72 minigame_tile_buildname(letter,2) );
73 else
74 return strcat(minigame_tile_buildname(letter,4)," ",
75 minigame_tile_buildname(letter,5)," ",
76 minigame_tile_buildname(letter,6) );
77}
78
79// Create an new tile
80// \param id Tile index (eg: a1)
81// \param minig Owner minigame instance
82// \param distance Distance from adjacent tiles
83void nmm_spawn_tile(string id, entity minig, int distance)
84{
85 // TODO global variable + list_next for simpler tile loops
86 entity e = new(minigame_nmm_tile);
87 e.origin = minigame_tile_pos(id,7,7);
88 e.netname = id;
89 e.owner = minig;
90 e.team = 0;
91 e.nmm_tile_distance = distance;
92 e.nmm_tile_hmill = strzone(nmm_tile_build_hmill(e));
93 e.nmm_tile_vmill = strzone(nmm_tile_build_vmill(e));
94}
95
96// Create a tile square and recursively create inner squares
97// \param minig Owner minigame instance
98// \param offset Index offset (eg: 1 to start the square at b2, 0 at a1 etc.)
99// \param skip Number of indices to skip between tiles (eg 1: a1, a3)
100void nmm_spawn_tile_square( entity minig, int offset, int skip )
101{
102 int letter = offset;
103 int number = offset;
104 for ( int i = 0; i < 3; ++i )
105 {
106 number = offset;
107 for ( int j = 0; j < 3; ++j )
108 {
109 if ( i != 1 || j != 1 )
111 number += skip+1;
112 }
113 letter += skip+1;
114 }
115
116 if ( skip > 0 )
117 nmm_spawn_tile_square(minig,offset+1,skip-1);
118}
119
120// Remove tiles of a NMM minigame
122{
123 entity e = NULL;
124 while ( ( e = findentity(e,owner,minig) ) )
125 if ( e.classname == "minigame_nmm_tile" )
126 {
127 strfree(e.netname);
128 strfree(e.nmm_tile_hmill);
129 strfree(e.nmm_tile_vmill);
130 delete(e);
131 }
132}
133
134// Create the tiles of a NMM minigame
136{
137 nmm_spawn_tile_square(minig,0,2);
138}
139
140// Find a tile by its id
141entity nmm_find_tile(entity minig, string id)
142{
143 entity e = NULL;
144 while ( ( e = findentity(e,owner,minig) ) )
145 if ( e.classname == "minigame_nmm_tile" && e.netname == id )
146 return e;
147 return NULL;
148}
149
150// Check whether two tiles are adjacent
152{
153
154 int dnumber = fabs ( minigame_tile_number(tile1.netname) - minigame_tile_number(tile2.netname) );
155 int dletter = fabs ( minigame_tile_letter(tile1.netname) - minigame_tile_letter(tile2.netname) );
156
157 return ( dnumber == 0 && ( dletter == 1 || dletter == tile1.nmm_tile_distance ) ) ||
158 ( dletter == 0 && ( dnumber == 1 || dnumber == tile1.nmm_tile_distance ) );
159}
160
161// Returns 1 if there is at least 1 free adjacent tile
163{
164 entity e = NULL;
165 while ( ( e = findentity(e,owner,tile.owner) ) )
166 if ( e.classname == "minigame_nmm_tile" && !e.nmm_tile_piece
167 && nmm_tile_adjacent(e,tile) )
168 {
169 return true;
170 }
171 return false;
172}
173
174// Check if the given tile id appears in the string
175bool nmm_in_mill_string(entity tile, string s)
176{
177 int argc = tokenize(s);
178 for ( int i = 0; i < argc; ++i )
179 {
180 entity e = nmm_find_tile(tile.owner,argv(i));
181 if ( !e || !e.nmm_tile_piece || e.nmm_tile_piece.team != tile.nmm_tile_piece.team )
182 return false;
183 }
184 return true;
185}
186
187// Check if a tile is in a mill
189{
190 return tile.nmm_tile_piece && (
191 nmm_in_mill_string(tile,tile.nmm_tile_hmill) ||
192 nmm_in_mill_string(tile,tile.nmm_tile_vmill) );
193}
194
195
196#ifdef SVQC
197// Find a NMM piece matching some of the given flags and team number
198entity nmm_find_piece(entity start, entity minigame, int teamn, int pieceflags)
199{
200 entity e = start;
201 while ( ( e = findentity(e,owner,minigame) ) )
202 if ( e.classname == "minigame_board_piece" &&
203 (e.minigame_flags & pieceflags) && e.team == teamn )
204 return e;
205 return NULL;
206}
207
208// Count NMM pieces matching flags and team number
209int nmm_count_pieces(entity minigame, int teamn, int pieceflags)
210{
211 int n = 0;
212 entity e = NULL;
213 while (( e = nmm_find_piece(e,minigame, teamn, pieceflags) ))
214 n++;
215 return n;
216}
217
218// required function, handle server side events
219int nmm_server_event(entity minigame, string event, ...)
220{
221 if ( event == "start" )
222 {
223 minigame.minigame_flags = NMM_TURN_PLACE|NMM_TURN_TEAM1;
224 nmm_init_tiles(minigame);
225 entity e;
226 for ( int i = 0; i < 7; ++i )
227 {
228 e = msle_spawn(minigame,new(minigame_board_piece));
229 e.team = 1;
230 e.minigame_flags = NMM_PIECE_HOME;
231 e = msle_spawn(minigame,new(minigame_board_piece));
232 e.team = 2;
233 e.minigame_flags = NMM_PIECE_HOME;
234 }
235
236 return 1;
237 }
238 else if ( event == "end" )
239 {
240 nmm_kill_tiles(minigame);
241 }
242 else if ( event == "join" )
243 {
244 int n = 0;
245 entity e;
246 for ( e = minigame.minigame_players; e; e = e.list_next )
247 n++;
248 if ( n >= 2 )
249 return NMM_SPECTATOR_TEAM;
250 if ( minigame.minigame_players && minigame.minigame_players.team == 1 )
251 return 2;
252 return 1;
253 }
254 else if ( event == "cmd" )
255 {
256 entity e = ...(0,entity);
257 int argc = ...(1,int);
258 entity tile = NULL;
259 entity piece = NULL;
260 bool move_ok = false;
261
262 if ( e && argc >= 2 && argv(0) == "move" &&
263 ( minigame.minigame_flags & NMM_TURN_TEAM ) == e.team )
264 {
265 tile = nmm_find_tile(minigame,argv(1));
266 if ( !tile )
267 {
268 move_ok = false;
269 }
270 else if ( minigame.minigame_flags & NMM_TURN_PLACE )
271 {
272 piece = nmm_find_piece(NULL,minigame,e.team,NMM_PIECE_HOME);
273 if ( !tile.nmm_tile_piece && piece )
274 {
275 tile.nmm_tile_piece = piece;
276 piece.minigame_flags = NMM_PIECE_BOARD;
277 piece.origin = tile.origin;
278 piece.SendFlags |= MINIG_SF_UPDATE;
279 move_ok = true;
280 }
281 }
282 else if ( minigame.minigame_flags & NMM_TURN_MOVE )
283 {
284 if ( tile.nmm_tile_piece && tile.nmm_tile_piece.team == e.team )
285 {
286 piece = tile.nmm_tile_piece;
287 entity tile2 = nmm_find_tile(minigame,argv(2));
288 if ( tile2 && nmm_tile_adjacent(tile,tile2) && !tile2.nmm_tile_piece )
289 {
290 tile.nmm_tile_piece = NULL;
291 tile2.nmm_tile_piece = piece;
292 piece.origin = tile2.origin;
293 piece.SendFlags |= MINIG_SF_UPDATE;
294 tile = tile2;
295 move_ok = true;
296 }
297 }
298
299 }
300 else if ( minigame.minigame_flags & NMM_TURN_FLY )
301 {
302 if ( tile.nmm_tile_piece && tile.nmm_tile_piece.team == e.team )
303 {
304 piece = tile.nmm_tile_piece;
305 entity tile2 = nmm_find_tile(minigame,argv(2));
306 if ( tile2 && !tile2.nmm_tile_piece )
307 {
308 tile.nmm_tile_piece = NULL;
309 tile2.nmm_tile_piece = piece;
310 piece.origin = tile2.origin;
311 piece.SendFlags |= MINIG_SF_UPDATE;
312 tile = tile2;
313 move_ok = true;
314 }
315 }
316
317 }
318 else if ( minigame.minigame_flags & NMM_TURN_TAKE )
319 {
320 piece = tile.nmm_tile_piece;
321 if ( piece && piece.nmm_tile_piece.team != e.team )
322 {
323 tile.nmm_tile_piece = NULL;
324 piece.minigame_flags = NMM_PIECE_DEAD;
325 piece.SendFlags |= MINIG_SF_UPDATE;
326 move_ok = true;
327 }
328 }
329
330 int nextteam = e.team % 2 + 1;
331 int npieces = nmm_count_pieces(minigame,nextteam,NMM_PIECE_HOME|NMM_PIECE_BOARD);
332
333 if ( npieces < 3 )
334 {
335 minigame.minigame_flags = NMM_TURN_WIN | e.team;
336 minigame.SendFlags |= MINIG_SF_UPDATE;
337 }
338 else if ( move_ok)
339 {
340 if ( !(minigame.minigame_flags & NMM_TURN_TAKE) && nmm_in_mill(tile) )
341 {
342 minigame.minigame_flags = NMM_TURN_TAKE|e.team;
343 int takemill = NMM_TURN_TAKEANY;
344 entity f = NULL;
345 while ( ( f = findentity(f,owner,minigame) ) )
346 if ( f.classname == "minigame_nmm_tile" && f.nmm_tile_piece &&
347 f.nmm_tile_piece.team == nextteam && !nmm_in_mill(f) )
348 {
349 takemill = 0;
350 break;
351 }
352 minigame.minigame_flags |= takemill;
353 }
354 else
355 {
356 if ( nmm_find_piece(NULL,minigame,nextteam,NMM_PIECE_HOME) )
357 minigame.minigame_flags = NMM_TURN_PLACE|nextteam;
358 else if ( npieces == 3 )
359 minigame.minigame_flags = NMM_TURN_FLY|nextteam;
360 else
361 {
362 minigame.minigame_flags = NMM_TURN_WIN|e.team;
363 entity f = NULL;
364 while ( ( f = findentity(f,owner,minigame) ) )
365 if ( f.classname == "minigame_nmm_tile" && f.nmm_tile_piece &&
366 f.nmm_tile_piece.team == nextteam && nmm_tile_canmove(f) )
367 {
368 minigame.minigame_flags = NMM_TURN_MOVE|nextteam;
369 break;
370 }
371 }
372 }
373 minigame.SendFlags |= MINIG_SF_UPDATE;
374 }
375 else
376 LOG_TRACE("Invalid move: ", ...(2, string));
377 return 1;
378 }
379 }
380 return 0;
381}
382
383#elif defined(CSQC)
384
385entity nmm_currtile;
386entity nmm_fromtile;
387
388vector nmm_boardpos;
389vector nmm_boardsize;
390
391// whether the given tile is a valid selection
392bool nmm_valid_selection(entity tile)
393{
394 if ( ( tile.owner.minigame_flags & NMM_TURN_TEAM ) != minigame_self.team )
395 return false; // not our turn
396 if ( tile.owner.minigame_flags & NMM_TURN_PLACE )
397 return !tile.nmm_tile_piece; // need to put a piece on an empty spot
398 if ( tile.owner.minigame_flags & NMM_TURN_MOVE )
399 {
400 if ( tile.nmm_tile_piece && tile.nmm_tile_piece.team == minigame_self.team &&
401 nmm_tile_canmove(tile) )
402 return true; // movable tile
403 if ( nmm_fromtile ) // valid destination
404 return !tile.nmm_tile_piece && nmm_tile_adjacent(nmm_fromtile,tile);
405 return false;
406 }
407 if ( tile.owner.minigame_flags & NMM_TURN_FLY )
408 {
409 if ( nmm_fromtile )
410 return !tile.nmm_tile_piece;
411 else
412 return tile.nmm_tile_piece && tile.nmm_tile_piece.team == minigame_self.team;
413 }
414 if ( tile.owner.minigame_flags & NMM_TURN_TAKE )
415 return tile.nmm_tile_piece && tile.nmm_tile_piece.team != minigame_self.team &&
416 ( (tile.owner.minigame_flags & NMM_TURN_TAKEANY) || !nmm_in_mill(tile) );
417 return false;
418}
419
420// whether it should highlight valid tile selections
421bool nmm_draw_avaliable(entity tile)
422{
423 if ( ( tile.owner.minigame_flags & NMM_TURN_TEAM ) != minigame_self.team )
424 return false;
425 if ( (tile.owner.minigame_flags & NMM_TURN_TAKE) )
426 return true;
427 if ( (tile.owner.minigame_flags & (NMM_TURN_FLY|NMM_TURN_MOVE)) && nmm_fromtile )
428 return !tile.nmm_tile_piece;
429 return false;
430}
431
432// Required function, draw the game board
433void nmm_hud_board(vector pos, vector mySize)
434{
435 minigame_hud_fitsqare(pos, mySize);
436 nmm_boardpos = pos;
437 nmm_boardsize = mySize;
438 minigame_hud_simpleboard(pos,mySize,minigame_texture("nmm/board"));
439
440 vector tile_size = minigame_hud_denormalize_size('1 1 0'/7,pos,mySize);
441 vector tile_pos;
442 entity e;
444 {
445 if ( e.classname == "minigame_nmm_tile" )
446 {
447 tile_pos = minigame_hud_denormalize(e.origin,pos,mySize);
448
449 if ( e == nmm_fromtile )
450 {
451 minigame_drawpic_centered( tile_pos, minigame_texture("nmm/tile_active"),
452 tile_size, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL );
453 }
454 else if ( nmm_draw_avaliable(e) && nmm_valid_selection(e) )
455 {
456 minigame_drawpic_centered( tile_pos, minigame_texture("nmm/tile_available"),
457 tile_size, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL );
458 }
459
460 if ( e == nmm_currtile )
461 {
462 minigame_drawpic_centered( tile_pos, minigame_texture("nmm/tile_selected"),
463 tile_size, '1 1 1', panel_fg_alpha, DRAWFLAG_ADDITIVE );
464 }
465
466 if ( e.nmm_tile_piece )
467 {
469 minigame_texture(strcat("nmm/piece",ftos(e.nmm_tile_piece.team))),
470 tile_size*0.8, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL );
471 }
472
473 //drawstring(tile_pos, e.netname, hud_fontsize, '1 0 0', 1, DRAWFLAG_NORMAL);
474 }
475 }
476
477 if ( active_minigame.minigame_flags & NMM_TURN_WIN )
478 {
479 vector winfs = hud_fontsize*2;
480 string pname = "";
482 if ( e.classname == "minigame_player" &&
483 e.team == (active_minigame.minigame_flags & NMM_TURN_TEAM) )
484 pname = entcs_GetName(e.minigame_playerslot-1);
485
486 vector win_pos = pos+eY*(mySize_y-winfs_y)/2;
487 vector win_sz;
488 win_sz = minigame_drawcolorcodedstring_wrapped(mySize_x,win_pos,
489 sprintf(_("%s^7 won the game!"), pname),
490 winfs, 0, DRAWFLAG_NORMAL, 0.5);
491
492 drawfill(win_pos-eY*hud_fontsize_y,win_sz+2*eY*hud_fontsize_y,'1 1 1',0.5*panel_fg_alpha,DRAWFLAG_ADDITIVE);
493
495 sprintf(_("%s^7 won the game!"), pname),
496 winfs, panel_fg_alpha, DRAWFLAG_NORMAL, 0.5);
497 }
498
499 minigame_show_allspecs(nmm_boardpos, nmm_boardsize);
500}
501
502// Required function, draw the game status panel
503void nmm_hud_status(vector pos, vector mySize)
504{
506 vector ts;
507 ts = minigame_drawstring_wrapped(mySize_x,pos,active_minigame.descriptor.message,
508 hud_fontsize * 2, '0.25 0.47 0.72', panel_fg_alpha, DRAWFLAG_NORMAL,0.5);
509 pos_y += ts_y;
510 mySize_y -= ts_y;
511
512 vector player_fontsize = hud_fontsize * 1.75;
513 ts_y = ( mySize_y - 2*player_fontsize_y ) / 2;
514 ts_x = mySize_x;
515
516 float player1x = 0;
517 float player2x = 0;
518 vector piece_sz = '48 48 0';
519 float piece_space = piece_sz_x + ( ts_x - 7 * piece_sz_x ) / 6;
520 vector mypos;
521 float piece_light = 1;
522 entity e = NULL;
523
525 {
526 mypos = pos;
527 if ( (active_minigame.minigame_flags&NMM_TURN_TEAM) == 2 )
528 mypos_y += player_fontsize_y + ts_y;
529 drawfill(mypos,eX*mySize_x+eY*player_fontsize_y,'1 1 1',0.5*panel_fg_alpha,DRAWFLAG_ADDITIVE);
530 mypos_y += player_fontsize_y;
531 drawfill(mypos,eX*mySize_x+eY*piece_sz_y,'1 1 1',0.25*panel_fg_alpha,DRAWFLAG_ADDITIVE);
532 }
533
535 {
536 if ( e.classname == "minigame_player" && e.team != NMM_SPECTATOR_TEAM )
537 {
538 mypos = pos;
539 if ( e.team == 2 )
540 mypos_y += player_fontsize_y + ts_y;
542 entcs_GetName(e.minigame_playerslot-1),
543 player_fontsize, panel_fg_alpha, DRAWFLAG_NORMAL);
544 }
545 else if ( e.classname == "minigame_board_piece" )
546 {
547 mypos = pos;
548 mypos_y += player_fontsize_y;
549 if ( e.team == 2 )
550 {
551 mypos_x += player2x;
552 player2x += piece_space;
553 mypos_y += player_fontsize_y + ts_y;
554 }
555 else
556 {
557 mypos_x += player1x;
558 player1x += piece_space;
559 }
560 if ( e.minigame_flags == NMM_PIECE_HOME )
561 piece_light = 0.5;
562 else if ( e.minigame_flags == NMM_PIECE_BOARD )
563 piece_light = 1;
564 else
565 piece_light = 0.15;
566
567 drawpic(mypos, minigame_texture(strcat("nmm/piece",ftos(e.team))), piece_sz,
568 '1 1 1'*piece_light, panel_fg_alpha, DRAWFLAG_NORMAL );
569 }
570 }
571}
572
573// Make the correct move
574void nmm_make_move(entity minigame)
575{
576 if ( nmm_currtile )
577 {
578 if ( minigame.minigame_flags & (NMM_TURN_PLACE|NMM_TURN_TAKE) )
579 {
580 minigame_cmd("move ",nmm_currtile.netname);
581 nmm_fromtile = NULL;
582 }
583 else if ( (minigame.minigame_flags & (NMM_TURN_MOVE|NMM_TURN_FLY)) )
584 {
585 if ( nmm_fromtile == nmm_currtile )
586 {
587 nmm_fromtile = NULL;
588 }
589 else if ( nmm_currtile.nmm_tile_piece && nmm_currtile.nmm_tile_piece.team == minigame_self.team )
590 {
591 nmm_fromtile = nmm_currtile;
592 }
593 else if ( nmm_fromtile )
594 {
595 minigame_cmd("move ",nmm_fromtile.netname," ",nmm_currtile.netname);
596 nmm_fromtile = NULL;
597 }
598 }
599 }
600 else
601 nmm_fromtile = NULL;
602}
603
604string nmm_turn_to_string(int turnflags)
605{
607 return _("You are spectating");
608
609 if ( turnflags & NMM_TURN_WIN )
610 {
611 if ( (turnflags&NMM_TURN_TEAM) != minigame_self.team )
612 return _("You lost the game!");
613 return _("You win!");
614 }
615
616 if ( (turnflags&NMM_TURN_TEAM) != minigame_self.team )
617 return _("Wait for your opponent to make their move");
618 if ( turnflags & NMM_TURN_PLACE )
619 return _("Click on the game board to place your piece");
620 if ( turnflags & NMM_TURN_MOVE )
621 return _("You can select one of your pieces to move it to one of the surrounding places");
622 if ( turnflags & NMM_TURN_FLY )
623 return _("You can select one of your pieces to move it anywhere on the board");
624 if ( turnflags & NMM_TURN_TAKE )
625 return _("You can take one of the opponent's pieces");
626
627 return "";
628}
629
630// Required function, handle client events
631int nmm_client_event(entity minigame, string event, ...)
632{
633 if ( event == "activate" )
634 {
635 nmm_fromtile = NULL;
636 nmm_init_tiles(minigame);
637 strcpy(minigame.message, nmm_turn_to_string(minigame.minigame_flags));
638 }
639 else if ( event == "deactivate" )
640 {
641 nmm_fromtile = NULL;
642 nmm_kill_tiles(minigame);
643 strfree(minigame.message);
644 }
645 else if ( (event == "key_pressed" || event == "key_released") )
646 {
647 bool event_blocked = ((event == "key_released")
648 || ((minigame.minigame_flags & NMM_TURN_TEAM) != minigame_self.team));
649 if (!(minigame.minigame_flags & NMM_TURN_WIN))
650 {
651 switch ( ...(0,int) )
652 {
653 case K_RIGHTARROW:
654 case K_KP_RIGHTARROW:
655 if (event_blocked)
656 return true;
657 if ( ! nmm_currtile )
658 nmm_currtile = nmm_find_tile(active_minigame,"a7");
659 else
660 {
661 string tileid = nmm_currtile.netname;
662 nmm_currtile = NULL;
663 while ( !nmm_currtile )
664 {
665 tileid = minigame_relative_tile(tileid,1,0,7,7);
666 nmm_currtile = nmm_find_tile(active_minigame,tileid);
667 }
668 }
669 return 1;
670 case K_LEFTARROW:
671 case K_KP_LEFTARROW:
672 if (event_blocked)
673 return true;
674 if ( ! nmm_currtile )
675 nmm_currtile = nmm_find_tile(active_minigame,"g7");
676 else
677 {
678 string tileid = nmm_currtile.netname;
679 nmm_currtile = NULL;
680 while ( !nmm_currtile )
681 {
682 tileid = minigame_relative_tile(tileid,-1,0,7,7);
683 nmm_currtile = nmm_find_tile(active_minigame,tileid);
684 }
685 }
686 return 1;
687 case K_UPARROW:
688 case K_KP_UPARROW:
689 if (event_blocked)
690 return true;
691 if ( ! nmm_currtile )
692 nmm_currtile = nmm_find_tile(active_minigame,"a1");
693 else
694 {
695 string tileid = nmm_currtile.netname;
696 nmm_currtile = NULL;
697 while ( !nmm_currtile )
698 {
699 tileid = minigame_relative_tile(tileid,0,1,7,7);
700 nmm_currtile = nmm_find_tile(active_minigame,tileid);
701 }
702 }
703 return 1;
704 case K_DOWNARROW:
705 case K_KP_DOWNARROW:
706 if (event_blocked)
707 return true;
708 if ( ! nmm_currtile )
709 nmm_currtile = nmm_find_tile(active_minigame,"a7");
710 else
711 {
712 string tileid = nmm_currtile.netname;
713 nmm_currtile = NULL;
714 while ( !nmm_currtile )
715 {
716 tileid = minigame_relative_tile(tileid,0,-1,7,7);
717 nmm_currtile = nmm_find_tile(active_minigame,tileid);
718 }
719 }
720 return 1;
721 case K_ENTER:
722 case K_KP_ENTER:
723 case K_SPACE:
724 if (event_blocked)
725 return true;
726 nmm_make_move(minigame);
727 return 1;
728 }
729 }
730 return 0;
731 }
732 else if ( event == "mouse_pressed" && ...(0,int) == K_MOUSE1 )
733 {
734 nmm_client_event(minigame, "mouse_moved");
735 nmm_make_move(minigame);
736 return 1;
737 }
738 else if ( event == "mouse_moved" )
739 {
740 nmm_currtile = NULL;
741 vector tile_pos;
742 vector tile_size = minigame_hud_denormalize_size('1 1 0'/7,nmm_boardpos,nmm_boardsize);
743 entity e;
745 {
746 if ( e.classname == "minigame_nmm_tile" )
747 {
748 tile_pos = minigame_hud_denormalize(e.origin,nmm_boardpos,nmm_boardsize)-tile_size/2;
749 if ( minigame_hud_mouse_in(tile_pos, tile_size) && nmm_valid_selection(e) )
750 {
751 nmm_currtile = e;
752 break;
753 }
754 }
755 }
756 return 1;
757 }
758 else if ( event == "network_receive" )
759 {
760 entity sent = ...(0,entity);
761
762 if ( sent.classname == "minigame_board_piece" && ( ...(1,int) & MINIG_SF_UPDATE ) )
763 {
764 entity e;
765 string tileid = "";
766 if ( sent.minigame_flags & NMM_PIECE_BOARD )
767 tileid = minigame_tile_name(sent.origin,7,7);
769 {
770 if ( e.classname == "minigame_nmm_tile" )
771 {
772 if ( e.nmm_tile_piece == sent )
773 e.nmm_tile_piece = NULL;
774 if ( e.netname == tileid )
775 e.nmm_tile_piece = sent;
776 }
777 }
778 }
779 else if ( sent.classname == "minigame" && ( ...(1,int) & MINIG_SF_UPDATE ) )
780 {
781 strcpy(sent.message, nmm_turn_to_string(sent.minigame_flags));
782 if ( sent.minigame_flags & minigame_self.team )
784 }
785 }
786
787 return 0;
788}
789
790#endif
var entity(vector mins, vector maxs,.entity tofield) findbox_tofield_OrFallback
void minigame_drawcolorcodedstring_trunc(float maxwidth, vector pos, string text, vector fontsize, float theAlpha, int drawflags)
void minigame_show_allspecs(vector boardpos, vector boardsize)
void minigame_prompt()
vector minigame_drawstring_wrapped(float maxwidth, vector pos, string text, vector fontsize, vector color, float theAlpha, int drawflags, float align)
bool minigame_hud_mouse_in(vector pos, vector sz)
void minigame_hud_simpleboard(vector pos, vector mySize, string board_texture)
string minigame_texture(string name)
vector minigame_hud_denormalize_size(vector v, vector pos, vector mySize)
vector minigame_drawcolorcodedstring_wrapped(float maxwidth, vector pos, string text, vector fontsize, float theAlpha, int drawflags, float align)
vector minigame_hud_denormalize(vector v, vector pos, vector mySize)
void minigame_drawpic_centered(vector pos, string texture, vector sz, vector color, float thealpha, int drawflags)
#define REGISTER_MINIGAME(name, nicename)
entity minigame_self
entity active_minigame
#define minigame_hud_fitsqare(pos, mySize)
#define minigame_cmd(...)
#define FOREACH_MINIGAME_ENTITY(entityvar)
#define drawpic(position, pic, size, rgb, alpha, flag)
Definition draw.qh:21
#define drawfill(position, size, rgb, alpha, flag)
Definition draw.qh:36
vector hud_fontsize
Definition main.qh:77
entity owner
Definition main.qh:87
const float DRAWFLAG_NORMAL
const float DRAWFLAG_ADDITIVE
string entcs_GetName(int i)
Definition ent_cs.qh:151
float panel_fg_alpha
Definition hud.qh:169
#define HUD_Panel_DrawBg()
Definition hud.qh:55
float K_KP_RIGHTARROW
Definition keycodes.qc:60
float K_UPARROW
Definition keycodes.qc:15
float K_DOWNARROW
Definition keycodes.qc:16
float K_MOUSE1
Definition keycodes.qc:129
float K_RIGHTARROW
Definition keycodes.qc:18
float K_KP_UPARROW
Definition keycodes.qc:64
float K_SPACE
Definition keycodes.qc:10
float K_KP_LEFTARROW
Definition keycodes.qc:57
float K_ENTER
Definition keycodes.qc:8
float K_KP_DOWNARROW
Definition keycodes.qc:53
float K_LEFTARROW
Definition keycodes.qc:17
float K_KP_ENTER
Definition keycodes.qc:74
#define int
Definition _all.inc:20
#define LOG_TRACE(...)
Definition log.qh:76
entity findentity(entity start,.entity field, entity match)
string ftos(float f)
float fabs(float f)
float tokenize(string s)
string strzone(string s)
string argv(float n)
entity msle_spawn(entity minigame_session, entity e)
Definition minigames.qc:87
string minigame_relative_tile(string start_id, int dx, int dy, int rows, int columns)
Definition minigames.qc:40
int minigame_tile_letter(string id)
Definition minigames.qc:12
string minigame_tile_name(vector pos, int rows, int columns)
Definition minigames.qc:54
vector minigame_tile_pos(string id, int rows, int columns)
Definition minigames.qc:27
string minigame_tile_buildname(int letter, int number)
Definition minigames.qc:34
int minigame_tile_number(string id)
Definition minigames.qc:21
const int MINIG_SF_UPDATE
Definition minigames.qh:109
bool nmm_tile_canmove(entity tile)
Definition nmm.qc:162
const int NMM_TURN_TEAM1
Definition nmm.qc:12
int nmm_count_pieces(entity minigame, int teamn, int pieceflags)
Definition nmm.qc:209
int nmm_server_event(entity minigame, string event,...)
Definition nmm.qc:219
string nmm_tile_vmill
Definition nmm.qc:25
void nmm_init_tiles(entity minig)
Definition nmm.qc:135
bool nmm_in_mill(entity tile)
Definition nmm.qc:188
const int NMM_TURN_FLY
Definition nmm.qc:7
const int NMM_TURN_PLACE
Definition nmm.qc:5
const int NMM_TURN_TEAM2
Definition nmm.qc:13
const int NMM_TURN_TEAM
Definition nmm.qc:14
bool nmm_in_mill_string(entity tile, string s)
Definition nmm.qc:175
const int NMM_TURN_TAKEANY
Definition nmm.qc:9
entity nmm_tile_piece
Definition nmm.qc:23
string nmm_tile_hmill
Definition nmm.qc:24
string nmm_tile_build_vmill(entity tile)
Definition nmm.qc:54
bool nmm_tile_adjacent(entity tile1, entity tile2)
Definition nmm.qc:151
string nmm_tile_build_hmill(entity tile)
Definition nmm.qc:28
const int NMM_PIECE_DEAD
Definition nmm.qc:16
int nmm_tile_distance
Definition nmm.qc:22
const int NMM_TURN_TYPE
Definition nmm.qc:11
void nmm_kill_tiles(entity minig)
Definition nmm.qc:121
entity nmm_find_tile(entity minig, string id)
Definition nmm.qc:141
const int NMM_PIECE_BOARD
Definition nmm.qc:18
const int NMM_TURN_TAKE
Definition nmm.qc:8
const int NMM_SPECTATOR_TEAM
Definition nmm.qc:20
void nmm_spawn_tile(string id, entity minig, int distance)
Definition nmm.qc:83
entity nmm_find_piece(entity start, entity minigame, int teamn, int pieceflags)
Definition nmm.qc:198
const int NMM_TURN_MOVE
Definition nmm.qc:6
void nmm_spawn_tile_square(entity minig, int offset, int skip)
Definition nmm.qc:100
const int NMM_TURN_WIN
Definition nmm.qc:10
const int NMM_PIECE_HOME
Definition nmm.qc:17
strcat(_("^F4Countdown stopped!"), "\n^BG", _("Teams are too unbalanced."))
#define NULL
Definition post.qh:14
vector
Definition self.qh:92
int int number
Definition impulse.qc:89
#define strfree(this)
Definition string.qh:59
#define strcpy(this, s)
Definition string.qh:52
const vector eY
Definition vector.qh:45
const vector eX
Definition vector.qh:44