]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blobdiff - qcsrc/common/minigames/minigame/ttt.qc
Merge branch 'bones_was_here/strafehud_jumpheight' into Juhu/strafehud-fixes
[xonotic/xonotic-data.pk3dir.git] / qcsrc / common / minigames / minigame / ttt.qc
index 630462aa9fda2bc060f0605bb40e6e00e68a8560..73fa4c6e99805bb20b9a581b0350f76ceda364ad 100644 (file)
@@ -1,4 +1,5 @@
-REGISTER_MINIGAME(ttt, "Tic Tac Toe");
+#include "ttt.qh"
+REGISTER_MINIGAME(ttt, _("Tic Tac Toe"));
 
 const int TTT_TURN_PLACE = 0x0100; // player has to place a piece on the board
 const int TTT_TURN_WIN   = 0x0200; // player has won
@@ -14,6 +15,8 @@ const int TTT_TURN_TEAM  = 0x000f; // turn team mask
 const int TTT_SF_PLAYERSCORE  = MINIG_SF_CUSTOM;   // send minigame_player scores (won matches)
 const int TTT_SF_SINGLEPLAYER = MINIG_SF_CUSTOM<<1;// send minigame.ttt_ai
 
+const int TTT_SPECTATOR_TEAM = 255; // must be above max teams and equal to or below 255
+
 const int TTT_LET_CNT = 3;
 const int TTT_NUM_CNT = 3;
 const int TTT_TILE_SIZE = 3;
@@ -82,7 +85,7 @@ void ttt_move(entity minigame, entity player, string pos )
                if ( ttt_valid_tile(pos) )
                if ( !ttt_find_piece(minigame,pos) )
                {
-                       entity piece = msle_spawn(minigame,"minigame_board_piece");
+                       entity piece = msle_spawn(minigame,new(minigame_board_piece));
                        piece.team = player.team;
                        piece.netname = strzone(pos);
                        minigame_server_sendflags(piece,MINIG_SF_ALL);
@@ -146,7 +149,7 @@ int ttt_server_event(entity minigame, string event, ...)
                        while( (e = findentity(e, owner, minigame)) )
                        if(e.classname == "minigame_board_piece")
                        {
-                               if(e.netname) { strunzone(e.netname); }
+                               strfree(e.netname);
                                delete(e);
                        }
                        return false;
@@ -160,7 +163,7 @@ int ttt_server_event(entity minigame, string event, ...)
                                return false;
 
                        // Don't allow more than 2 players
-                       if(pl_num >= 2) { return false; }
+                       if(pl_num >= 2) { return TTT_SPECTATOR_TEAM; }
 
                        // Get the right team
                        if(minigame.minigame_players)
@@ -171,15 +174,23 @@ int ttt_server_event(entity minigame, string event, ...)
                }
                case "cmd":
                {
+                       entity player = ...(0,entity);
+                       bool event_blocked = (player.team == TTT_SPECTATOR_TEAM);
                        switch(argv(0))
                        {
                                case "move":
+                                       if(event_blocked)
+                                               return true;
                                        ttt_move(minigame, ...(0,entity), ...(1,int) == 2 ? argv(1) : string_null );
                                        return true;
                                case "next":
+                                       if(event_blocked)
+                                               return true;
                                        ttt_next_match(minigame,...(0,entity));
                                        return true;
                                case "singleplayer":
+                                       if(event_blocked)
+                                               return true;
                                        if ( minigame_count_players(minigame) == 1 )
                                        {
                                                minigame.ttt_ai = minigame_next_team(minigame.minigame_players.team, 2);
@@ -272,7 +283,7 @@ void ttt_hud_board(vector pos, vector mySize)
 // Required function, draw the game status panel
 void ttt_hud_status(vector pos, vector mySize)
 {
-       HUD_Panel_DrawBg(1);
+       HUD_Panel_DrawBg();
        vector ts;
        ts = minigame_drawstring_wrapped(mySize_x,pos,active_minigame.descriptor.message,
                hud_fontsize * 2, '0.25 0.47 0.72', panel_fg_alpha, DRAWFLAG_NORMAL,0.5);
@@ -289,7 +300,7 @@ void ttt_hud_status(vector pos, vector mySize)
        entity e;
        FOREACH_MINIGAME_ENTITY(e)
        {
-               if ( e.classname == "minigame_player" )
+               if ( e.classname == "minigame_player" && e.team != TTT_SPECTATOR_TEAM )
                {
                        mypos = pos;
                        if ( e.team == 2 )
@@ -314,19 +325,24 @@ void ttt_hud_status(vector pos, vector mySize)
 // Turn a set of flags into a help message
 string ttt_turn_to_string(int turnflags)
 {
+       if(minigame_self.team == TTT_SPECTATOR_TEAM)
+               return _("You are spectating");
+
        if ( turnflags & TTT_TURN_DRAW )
                return _("Draw");
 
        if ( turnflags & TTT_TURN_WIN )
        {
-               if ( (turnflags&TTT_TURN_TEAM) != minigame_self.team )
-                       return _("You lost the game!\nSelect \"^1Next Match^7\" on the menu for a rematch!");
-               return _("You win!\nSelect \"^1Next Match^7\" on the menu to start a new match!");
+               // translator-friendly messages composed of 2 existing messages
+               // TODO: proper "you win" banner instead of hijacking the help message
+               if ( (turnflags & TTT_TURN_TEAM) != minigame_self.team )
+                       return strcat(_("You lost the game!"), "\n", _("Select \"^1Next Match^7\" on the menu for a rematch!"));
+               return strcat(_("You win!"), "\n", _("Select \"^1Next Match^7\" on the menu to start a new match!"));
        }
 
        if ( turnflags & TTT_TURN_NEXT )
        {
-               if ( (turnflags&TTT_TURN_TEAM) != minigame_self.team )
+               if ( (turnflags & TTT_TURN_TEAM) != minigame_self.team )
                        return _("Select \"^1Next Match^7\" on the menu to start a new match!");
                return _("Wait for your opponent to confirm the rematch");
        }
@@ -417,11 +433,11 @@ int ttt_ai_random(int piecemask)
        for ( int i = 0; i < 9; i++ )
        {
                if ( piecemask & f )
-                       RandomSelection_Add(NULL, f, string_null, 1, 1);
+                       RandomSelection_AddFloat(f, 1, 1);
                f <<= 1;
        }
 
-       LOG_TRACE(sprintf("TTT AI: selected %x from %x\n",
+       LOG_TRACE(sprintf("TTT AI: selected %x from %x",
                        RandomSelection_chosen_float, piecemask) );
        return RandomSelection_chosen_float;
 }
@@ -439,7 +455,7 @@ int ttt_ai_block3 ( int piecemask, int piecemask_free )
        r |= ttt_ai_1of3(piecemask,TTT_AI_POSFLAG_A3,TTT_AI_POSFLAG_B3,TTT_AI_POSFLAG_C3);
        r |= ttt_ai_1of3(piecemask,TTT_AI_POSFLAG_A1,TTT_AI_POSFLAG_B2,TTT_AI_POSFLAG_C3);
        r |= ttt_ai_1of3(piecemask,TTT_AI_POSFLAG_A3,TTT_AI_POSFLAG_B2,TTT_AI_POSFLAG_C1);
-       LOG_TRACE(sprintf("TTT AI: possible 3 in a rows in %x: %x (%x)\n",piecemask,r, r&piecemask_free));
+       LOG_TRACE(sprintf("TTT AI: possible 3 in a rows in %x: %x (%x)",piecemask,r, r&piecemask_free));
        r &= piecemask_free;
        return ttt_ai_random(r);
 }
@@ -452,15 +468,15 @@ string ttt_ai_choose_simple(int piecemask_self, int piecemask_opponent, int piec
 {
        int move = 0;
 
-       LOG_TRACE("TTT AI: checking winning move\n");
+       LOG_TRACE("TTT AI: checking winning move");
        if (( move = ttt_ai_block3(piecemask_self,piecemask_free) ))
                return ttt_ai_piece_flag2pos(move); // place winning move
 
-       LOG_TRACE("TTT AI: checking opponent's winning move\n");
+       LOG_TRACE("TTT AI: checking opponent's winning move");
        if (( move = ttt_ai_block3(piecemask_opponent,piecemask_free) ))
                return ttt_ai_piece_flag2pos(move); // block opponent
 
-       LOG_TRACE("TTT AI: random move\n");
+       LOG_TRACE("TTT AI: random move");
        return ttt_ai_piece_flag2pos(ttt_ai_random(piecemask_free));
 }
 
@@ -510,16 +526,16 @@ void ttt_aimove(entity minigame)
                }
 
                // TODO multiple AI difficulties
-               LOG_TRACE(sprintf("TTT AI: self: %x opponent: %x free: %x\n",
+               LOG_TRACE(sprintf("TTT AI: self: %x opponent: %x free: %x",
                                piecemask_self, piecemask_opponent, piecemask_free));
                pos = ttt_ai_choose_simple(piecemask_self, piecemask_opponent, piecemask_free);
-               LOG_TRACE("TTT AI: chosen move: ",pos,"\n\n");
+               LOG_TRACE("TTT AI: chosen move: ", pos);
                if ( !pos )
-                       LOG_TRACE("Tic Tac Toe AI has derped!\n");
+                       LOG_TRACE("Tic Tac Toe AI has derped!");
                else
                        ttt_move(minigame,aiplayer,pos);
        }
-       minigame.message = ttt_turn_to_string(minigame.minigame_flags);
+       strcpy(minigame.message, ttt_turn_to_string(minigame.minigame_flags));
 }
 
 // Make the correct move
@@ -539,8 +555,7 @@ void ttt_make_move(entity minigame)
 
 void ttt_set_curr_pos(string s)
 {
-       if ( ttt_curr_pos )
-               strunzone(ttt_curr_pos);
+       strfree(ttt_curr_pos);
        if ( s )
                s = strzone(s);
        ttt_curr_pos = s;
@@ -554,17 +569,27 @@ int ttt_client_event(entity minigame, string event, ...)
                case "activate":
                {
                        ttt_set_curr_pos("");
-                       minigame.message = ttt_turn_to_string(minigame.minigame_flags);
+                       strcpy(minigame.message, ttt_turn_to_string(minigame.minigame_flags));
+                       return false;
+               }
+               case "deactivate":
+               {
+                       strfree(minigame.message);
                        return false;
                }
                case "key_pressed":
+               case "key_released":
                {
-                       if((minigame.minigame_flags & TTT_TURN_TEAM) == minigame_self.team)
+                       bool event_blocked = ((event == "key_released")
+                               || ((minigame.minigame_flags & TTT_TURN_TEAM) != minigame_self.team));
+                       if (!(minigame.minigame_flags & TTT_TURN_WIN) && !(minigame.minigame_flags & TTT_TURN_DRAW))
                        {
                                switch ( ...(0,int) )
                                {
                                        case K_RIGHTARROW:
                                        case K_KP_RIGHTARROW:
+                                               if (event_blocked)
+                                                       return true;
                                                if ( ! ttt_curr_pos )
                                                        ttt_set_curr_pos("a3");
                                                else
@@ -572,6 +597,8 @@ int ttt_client_event(entity minigame, string event, ...)
                                                return true;
                                        case K_LEFTARROW:
                                        case K_KP_LEFTARROW:
+                                               if (event_blocked)
+                                                       return true;
                                                if ( ! ttt_curr_pos )
                                                        ttt_set_curr_pos("c3");
                                                else
@@ -579,6 +606,8 @@ int ttt_client_event(entity minigame, string event, ...)
                                                return true;
                                        case K_UPARROW:
                                        case K_KP_UPARROW:
+                                               if (event_blocked)
+                                                       return true;
                                                if ( ! ttt_curr_pos )
                                                        ttt_set_curr_pos("a1");
                                                else
@@ -586,6 +615,8 @@ int ttt_client_event(entity minigame, string event, ...)
                                                return true;
                                        case K_DOWNARROW:
                                        case K_KP_DOWNARROW:
+                                               if (event_blocked)
+                                                       return true;
                                                if ( ! ttt_curr_pos )
                                                        ttt_set_curr_pos("a3");
                                                else
@@ -594,6 +625,8 @@ int ttt_client_event(entity minigame, string event, ...)
                                        case K_ENTER:
                                        case K_KP_ENTER:
                                        case K_SPACE:
+                                               if (event_blocked)
+                                                       return true;
                                                ttt_make_move(minigame);
                                                return true;
                                }
@@ -605,6 +638,7 @@ int ttt_client_event(entity minigame, string event, ...)
                {
                        if(...(0,int) == K_MOUSE1)
                        {
+                               ttt_client_event(minigame, "mouse_moved");
                                ttt_make_move(minigame);
                                return true;
                        }
@@ -629,7 +663,7 @@ int ttt_client_event(entity minigame, string event, ...)
                        {
                                if ( sf & MINIG_SF_UPDATE )
                                {
-                                       sent.message = ttt_turn_to_string(sent.minigame_flags);
+                                       strcpy(sent.message, ttt_turn_to_string(sent.minigame_flags));
                                        if ( sent.minigame_flags & minigame_self.team )
                                                minigame_prompt();
                                }