X-Git-Url: https://de.git.xonotic.org/?p=xonotic%2Fxonotic-data.pk3dir.git;a=blobdiff_plain;f=qcsrc%2Fcommon%2Fminigames%2Fminigame%2Fsnake.qc;h=d5f0ea0787bf63b8ec5887756b098495745a4be7;hp=cd31c0f0f7fd1ff3106859f8093d53669a6f62cf;hb=e424ba544c41fc40b241b17bd7c1d9c2fc930705;hpb=3af13071334aeb3eea2758476a3f610efee64e20 diff --git a/qcsrc/common/minigames/minigame/snake.qc b/qcsrc/common/minigames/minigame/snake.qc index cd31c0f0f..d5f0ea078 100644 --- a/qcsrc/common/minigames/minigame/snake.qc +++ b/qcsrc/common/minigames/minigame/snake.qc @@ -1,3 +1,4 @@ +#include "snake.qh" REGISTER_MINIGAME(snake, "Snake"); // SNAAAAKE const float SNAKE_TURN_MOVE = 0x0100; // the snake is moving, player must control it @@ -27,16 +28,18 @@ int autocvar_sv_minigames_snake_lives = 3; .float snake_delay; .vector snake_dir; +.entity snake_next, snake_last, snake_prev; + .bool snake_tail; -.int snake_lives; +.int snake_lives[SNAKE_TEAMS + 1]; .int snake_lost_teams; bool snake_alone(entity minig) { int headcount = 0; - entity e = world; + entity e = NULL; while ( ( e = findentity(e,owner,minig) ) ) if ( e.classname == "minigame_board_piece" && e.cnt == 1 ) ++headcount; @@ -47,21 +50,21 @@ bool snake_alone(entity minig) // find same game piece given its tile name entity snake_find_piece(entity minig, string tile) { - entity e = world; + entity e = NULL; while ( ( e = findentity(e,owner,minig) ) ) if ( e.classname == "minigame_board_piece" && e.netname == tile ) return e; - return world; + return NULL; } // find same game piece given its cnt entity snake_find_cnt(entity minig, int steam, int tile) { - entity e = world; + entity e = NULL; while ( ( e = findentity(e,owner,minig) ) ) if ( e.classname == "minigame_board_piece" && e.cnt == tile && e.team == steam ) return e; - return world; + return NULL; } // check if the tile name is valid (15x15 grid) @@ -76,11 +79,11 @@ bool snake_valid_tile(string tile) entity snake_find_head(entity minig, int steam) { - entity e = world; + entity e = NULL; while ( ( e = findentity(e,owner,minig) ) ) if ( e.classname == "minigame_board_piece" && e.cnt == 1 && e.team == steam ) return e; - return world; + return NULL; } void snake_new_mouse(entity minigame) @@ -92,7 +95,7 @@ void snake_new_mouse(entity minigame) { string pos = minigame_tile_buildname(i, j); if(!snake_find_piece(minigame, pos)) - RandomSelection_Add(world, 0, pos, 1, 1); + RandomSelection_Add(NULL, 0, pos, 1, 1); } entity piece = msle_spawn(minigame,"minigame_board_piece"); @@ -110,12 +113,11 @@ int snake_winning_team(entity minigame) for(int i = 1; i <= SNAKE_TEAMS; ++i) { entity pl = snake_get_player(minigame, i); - if(pl) - if(pl.snake_lives > 0) + if(pl && minigame.snake_lives[i] > 0) { if(winning_team) return 0; - winning_team = pl.team; + winning_team = i; } } @@ -133,8 +135,7 @@ void snake_check_winner(entity minigame) for(int i = 1; i <= SNAKE_TEAMS; ++i) { entity pl = snake_get_player(minigame, i); - if(pl) - if(pl.snake_lives > 0) + if(pl && minigame.snake_lives[i] > 0) ++alivecnt; } @@ -153,16 +154,16 @@ void snake_check_winner(entity minigame) } void snake_move_head(entity minigame, entity head); -void snake_head_think() +void snake_head_think(entity this) { - entity minigame = self.owner; + entity minigame = this.owner; if(minigame.minigame_flags & SNAKE_TURN_MOVE) - snake_move_head(minigame, self); + snake_move_head(minigame, this); snake_check_winner(minigame); - self.nextthink = time + self.snake_delay; + this.nextthink = time + this.snake_delay; } void minigame_setup_snake(entity minigame, int pteam) @@ -174,14 +175,17 @@ void minigame_setup_snake(entity minigame, int pteam) { string pos = minigame_tile_buildname(i, j); if(!snake_find_piece(minigame, pos)) - RandomSelection_Add(world, 0, pos, 1, 1); + RandomSelection_Add(NULL, 0, pos, 1, 1); } entity piece = msle_spawn(minigame,"minigame_board_piece"); piece.team = pteam; piece.netname = strzone(RandomSelection_chosen_string); piece.cnt = 1; - piece.think = snake_head_think; + piece.snake_next = NULL; + piece.snake_prev = NULL; + piece.snake_last = piece; + setthink(piece, snake_head_think); piece.snake_delay = autocvar_sv_minigames_snake_delay_initial; piece.nextthink = time + 0.1; minigame_server_sendflags(piece,MINIG_SF_ALL); @@ -200,16 +204,16 @@ entity snake_get_player(entity minigame, int pteam) #ifdef SVQC for(e = minigame.minigame_players; e; e = e.list_next) #elif defined(CSQC) - e = world; + e = NULL; while( (e = findentity(e,owner,minigame)) ) if ( e.classname == "minigame_player" ) #endif if(e.team == pteam) return e; - return world; + return NULL; } -void snake_add_score(entity minigame, int pteam, .int score_field, int thescore) +void snake_add_score(entity minigame, int pteam, int thescore) { #ifdef SVQC if(!minigame) @@ -217,7 +221,7 @@ void snake_add_score(entity minigame, int pteam, .int score_field, int thescore) entity pl = snake_get_player(minigame, pteam); if(pl) { - pl.score_field += thescore; + pl.snake_score += thescore; pl.SendFlags |= SNAKE_SF_PLAYERSCORE; } #endif @@ -225,58 +229,43 @@ void snake_add_score(entity minigame, int pteam, .int score_field, int thescore) void snake_move_body(entity minigame, entity head, bool ate_mouse) { - entity tail = world; - string tailpos = string_null; - vector taildir = '0 0 0'; - - int i, pieces = 0; - for(i = (SNAKE_NUM_CNT * SNAKE_LET_CNT); i >= 2; --i) + for(entity e = head.snake_last; e; e = e.snake_prev) { - entity piece = snake_find_cnt(minigame, head.team, i); - entity nextpiece = snake_find_cnt(minigame, head.team, i - 1); - if(!piece) - continue; + if(!e || e == head) { break; } - pieces++; + entity nextpiece = e.snake_prev; // can be head - if(!tail) - { - tail = piece; - tailpos = piece.netname; - taildir = piece.snake_dir; - } - - if(piece.netname) { strunzone(piece.netname); } - piece.netname = strzone(nextpiece.netname); - piece.snake_dir = nextpiece.snake_dir; - minigame_server_sendflags(piece, MINIG_SF_ALL); + if(e.netname) { strunzone(e.netname); } + e.netname = strzone(nextpiece.netname); + e.snake_dir = nextpiece.snake_dir; + minigame_server_sendflags(e, MINIG_SF_UPDATE); } - // just a head - if(!pieces) + if(ate_mouse) { - tail = head; - tailpos = head.netname; - taildir = head.snake_dir; - } + entity tail = head.snake_last; - if(tail && ate_mouse) - { tail.snake_tail = false; int newcnt = tail.cnt + 1; head.snake_delay = max(autocvar_sv_minigames_snake_delay_min, autocvar_sv_minigames_snake_delay_initial - (newcnt / autocvar_sv_minigames_snake_delay_multiplier)); - snake_add_score(minigame, head.team, snake_score, 1); + snake_add_score(minigame, head.team, 1); entity piece = msle_spawn(minigame,"minigame_board_piece"); piece.cnt = newcnt; piece.team = head.team; - piece.snake_dir = taildir; + piece.snake_prev = tail; + piece.snake_dir = tail.snake_dir; + piece.snake_next = NULL; piece.snake_tail = true; - piece.netname = strzone(tailpos); - minigame_server_sendflags(piece,MINIG_SF_ALL); + piece.netname = strzone(tail.netname); - minigame_server_sendflags(minigame,MINIG_SF_UPDATE); + tail.snake_next = piece; + head.snake_last = piece; + + minigame_server_sendflags(piece,MINIG_SF_UPDATE); + + //minigame_server_sendflags(minigame,MINIG_SF_UPDATE); } } @@ -285,22 +274,28 @@ void snake_eat_team(entity minigame, int pteam) entity head = snake_find_head(minigame, pteam); if(!head) { return; } - snake_add_score(minigame, pteam, snake_lives, -1); + minigame.snake_lives[pteam] -= 1; + + entity pl = snake_get_player(minigame, pteam); +#ifdef SVQC + pl.SendFlags |= SNAKE_SF_PLAYERSCORE; +#endif + head.nextthink = time + 1; // make sure they don't to eat us somehow - entity e = world; + entity e = NULL; while ( ( e = findentity(e,owner,minigame) ) ) if ( e.classname == "minigame_board_piece" && e.cnt && e.team == pteam ) { if(e.netname) { strunzone(e.netname); } - remove(e); + delete(e); } - entity pl = snake_get_player(minigame, pteam); - if(pl.snake_lives > 0) - minigame_setup_snake(minigame, pteam); - else + if(minigame.snake_lives[pteam] <= 0) minigame.snake_lost_teams |= BIT(pteam); + + if(pl && minigame.snake_lives[pteam] > 0) + minigame_setup_snake(minigame, pteam); } void snake_move_head(entity minigame, entity head) @@ -334,7 +329,7 @@ void snake_move_head(entity minigame, entity head) } else { - snake_add_score(minigame, head.team, snake_score, -1); + snake_add_score(minigame, head.team, -1); snake_eat_team(minigame, head.team); } @@ -348,19 +343,19 @@ void snake_move_head(entity minigame, entity head) if(head.netname) { strunzone(head.netname); } head.netname = strzone(newpos); - minigame_server_sendflags(head,MINIG_SF_ALL); + minigame_server_sendflags(head,MINIG_SF_UPDATE); // above check makes sure it's not our team if(hit.cnt) { snake_eat_team(minigame, hit.team); - snake_add_score(minigame, head.team, snake_score, 1); + snake_add_score(minigame, head.team, 1); } if(ate_mouse) { if(hit.netname) { strunzone(hit.netname); } - remove(hit); + delete(hit); snake_new_mouse(minigame); } @@ -413,16 +408,25 @@ int snake_server_event(entity minigame, string event, ...) snake_setup_pieces(minigame); minigame.minigame_flags = SNAKE_TURN_MOVE; minigame.snake_lost_teams = 0; + + if(SNAKE_TEAMS > 1) + { + for(int i = 1; i <= SNAKE_TEAMS; ++i) + minigame.snake_lives[i] = autocvar_sv_minigames_snake_lives; + } + else + minigame.snake_lives[1] = 1; + return true; } case "end": { - entity e = world; + entity e = NULL; while( (e = findentity(e, owner, minigame)) ) if(e.classname == "minigame_board_piece") { if(e.netname) { strunzone(e.netname); } - remove(e); + delete(e); } return false; } @@ -449,7 +453,8 @@ int snake_server_event(entity minigame, string event, ...) entity pl = ...(1,entity); if(pl) { - pl.snake_lives = ((SNAKE_TEAMS > 1) ? autocvar_sv_minigames_snake_lives : 1); + //pl.snake_lives = ((SNAKE_TEAMS > 1) ? autocvar_sv_minigames_snake_lives : 1); + // send score anyway, lives are set pl.SendFlags |= SNAKE_SF_PLAYERSCORE; } minigame_setup_snake(minigame, t); @@ -461,8 +466,8 @@ int snake_server_event(entity minigame, string event, ...) { switch(argv(0)) { - case "move": - snake_move(minigame, ...(0,entity), ((...(1,int)) >= 2 ? argv(1) : string_null), ((...(1,int)) == 3 ? argv(2) : string_null)); + case "move": + snake_move(minigame, ...(0,entity), ((...(1,int)) >= 2 ? argv(1) : string_null), ((...(1,int)) == 3 ? argv(2) : string_null)); return true; } @@ -474,15 +479,26 @@ int snake_server_event(entity minigame, string event, ...) int sf = ...(1,int); if ( sent.classname == "minigame_board_piece" && (sf & MINIG_SF_UPDATE) ) { + int letter = minigame_tile_letter(sent.netname); + int number = minigame_tile_number(sent.netname); + + WriteByte(MSG_ENTITY,letter); + WriteByte(MSG_ENTITY,number); + WriteByte(MSG_ENTITY,sent.cnt); WriteByte(MSG_ENTITY,sent.snake_tail); - WriteCoord(MSG_ENTITY,sent.snake_dir_x); - WriteCoord(MSG_ENTITY,sent.snake_dir_y); + + int dx = sent.snake_dir_x; + int dy = sent.snake_dir_y; + if(dx == -1) dx = 2; + if(dy == -1) dy = 2; + WriteByte(MSG_ENTITY,dx); + WriteByte(MSG_ENTITY,dy); } else if ( sent.classname == "minigame_player" && (sf & SNAKE_SF_PLAYERSCORE ) ) { WriteLong(MSG_ENTITY,sent.snake_score); - WriteByte(MSG_ENTITY,max(0, sent.snake_lives)); + WriteByte(MSG_ENTITY,max(0, minigame.snake_lives[sent.team])); } else if ( sent.classname == "minigame" && (sf & MINIG_SF_UPDATE ) ) { @@ -491,7 +507,7 @@ int snake_server_event(entity minigame, string event, ...) return false; } } - + return false; } @@ -524,7 +540,7 @@ void snake_hud_board(vector pos, vector mySize) minigame_hud_fitsqare(pos, mySize); snake_boardpos = pos; snake_boardsize = mySize; - + minigame_hud_simpleboard(pos,mySize,minigame_texture("snake/board")); vector tile_size = minigame_hud_denormalize_size('1 1 0' / SNAKE_TILE_SIZE,pos,mySize); @@ -584,7 +600,7 @@ void snake_hud_board(vector pos, vector mySize) { int thex = minigame_tile_letter(e.netname); int they = minigame_tile_number(e.netname); - entity t = snake_find_cnt(active_minigame, minigame_self.team, e.cnt - 1); + entity t = snake_find_cnt(active_minigame, e.team, e.cnt - 1); int tx = minigame_tile_letter(t.netname); int ty = minigame_tile_number(t.netname); @@ -618,14 +634,14 @@ void snake_hud_board(vector pos, vector mySize) } else { - minigame_drawpic_centered( tile_pos, + minigame_drawpic_centered( tile_pos, minigame_texture(thepiece), tile_size, tile_color, panel_fg_alpha, DRAWFLAG_NORMAL ); } } } - if ( (active_minigame.minigame_flags & SNAKE_TURN_LOSS) || (active_minigame.minigame_flags & SNAKE_TURN_WIN) || (minigame_self.snake_lives <= 0) ) + if ( (active_minigame.minigame_flags & SNAKE_TURN_LOSS) || (active_minigame.minigame_flags & SNAKE_TURN_WIN) || (active_minigame.snake_lives[minigame_self.team] <= 0) ) { int scores = minigame_self.snake_score; @@ -637,19 +653,19 @@ void snake_hud_board(vector pos, vector mySize) if(active_minigame.minigame_flags & SNAKE_TURN_WIN) if((active_minigame.minigame_flags & SNAKE_TURN_TEAM) == minigame_self.team) victory_text = "You win!"; - if(minigame_self.snake_lives <= 0) + if(active_minigame.snake_lives[minigame_self.team] <= 0) victory_text = "You ran out of lives!"; - + vector win_pos = pos+eY*(mySize_y-winfs_y)/2; vector win_sz; win_sz = minigame_drawcolorcodedstring_wrapped(mySize_x,win_pos, - sprintf("%s %s", victory_text, scores_text), + sprintf("%s %s", victory_text, scores_text), winfs, 0, DRAWFLAG_NORMAL, 0.5); - + drawfill(win_pos-eY*hud_fontsize_y,win_sz+2*eY*hud_fontsize_y,'0.3 0.3 1',0.8,DRAWFLAG_ADDITIVE); - + minigame_drawcolorcodedstring_wrapped(mySize_x,win_pos, - sprintf("%s %s", victory_text, scores_text), + sprintf("%s %s", victory_text, scores_text), winfs, panel_fg_alpha, DRAWFLAG_NORMAL, 0.5); } } @@ -662,22 +678,14 @@ void snake_hud_status(vector pos, vector mySize) 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); - + ts_y += hud_fontsize_y; pos_y += ts_y; mySize_y -= ts_y; vector player_fontsize = hud_fontsize * 1.75; - ts_y = ( mySize_y - 2*player_fontsize_y ) / SNAKE_TEAMS; + ts_y = ( mySize_y - SNAKE_TEAMS*player_fontsize_y ) / SNAKE_TEAMS; ts_x = mySize_x; vector mypos; - vector tile_size = '48 48 0'; - - mypos = pos; - if ( minigame_self.team > 1 ) - mypos_y += player_fontsize_y + (ts_y * (minigame_self.team - 1)); - drawfill(mypos,eX*mySize_x+eY*player_fontsize_y,'1 1 1',0.5,DRAWFLAG_ADDITIVE); - mypos_y += player_fontsize_y; - drawfill(mypos,eX*mySize_x+eY*tile_size_y,'1 1 1',0.25,DRAWFLAG_ADDITIVE); entity e; FOREACH_MINIGAME_ENTITY(e) @@ -685,28 +693,21 @@ void snake_hud_status(vector pos, vector mySize) if ( e.classname == "minigame_player" ) { mypos = pos; - if ( e.team > 1 ) - mypos_y += player_fontsize_y + (ts_y * (e.team - 1)); - minigame_drawcolorcodedstring_trunc(mySize_x,mypos, - GetPlayerName(e.minigame_playerslot-1), - player_fontsize, panel_fg_alpha, DRAWFLAG_NORMAL); + mypos_y += (e.team-1) * (player_fontsize_y + ts_y); - vector tile_color = snake_teamcolor(e.team); - - mypos_y += player_fontsize_y; - drawpic( mypos, - minigame_texture("snake/head"), - tile_size * 0.7, tile_color, panel_fg_alpha, DRAWFLAG_NORMAL ); + drawfill(mypos, ts, snake_teamcolor(e.team), 0.25, DRAWFLAG_ADDITIVE); - mypos_x += tile_size_x; + minigame_drawcolorcodedstring_trunc(mySize_x,mypos, + entcs_GetName(e.minigame_playerslot-1), + player_fontsize, panel_fg_alpha, DRAWFLAG_NORMAL); - drawstring(mypos,ftos(e.snake_score),tile_size, + drawstring(mypos+eY*player_fontsize_y,ftos(e.snake_score),'48 48 0' * (SNAKE_TEAMS * 0.1), '0.7 0.84 1', panel_fg_alpha, DRAWFLAG_NORMAL); + drawstring(mypos+(eY*player_fontsize_y) + (eX*player_fontsize_x),strcat("1UP: ", ftos(active_minigame.snake_lives[e.team])),'48 48 0' * (SNAKE_TEAMS * 0.1), + '1 0.44 0.54', panel_fg_alpha, DRAWFLAG_NORMAL); - mypos_x += tile_size_x; - - drawstring(mypos,strcat("1UP: ", ftos(e.snake_lives)),tile_size * 0.6, - '0.7 0.84 1', panel_fg_alpha, DRAWFLAG_NORMAL); + if ( e == minigame_self ) + drawborderlines(1, mypos, ts, snake_teamcolor(e.team), 1, DRAWFLAG_NORMAL); } } } @@ -724,9 +725,9 @@ string snake_turn_to_string(int turnflags) return _("You win!"); } - if(minigame_self.snake_lives <= 0) + if(active_minigame.snake_lives[minigame_self.team] <= 0) return _("You ran out of lives!"); - + if ( (snake_find_head(active_minigame, minigame_self.team)).snake_dir == '0 0 0' ) return _("Press an arrow key to begin the game"); @@ -735,7 +736,7 @@ string snake_turn_to_string(int turnflags) return _("Avoid the snake's body, collect the mice!"); else return _("Avoid the screen edges and the snake's body, collect the mice!"); - + return ""; } @@ -803,17 +804,29 @@ int snake_client_event(entity minigame, string event, ...) { if(sf & MINIG_SF_UPDATE) { + int letter = ReadByte(); + int number = ReadByte(); + if(sent.netname) { strunzone(sent.netname); } + sent.netname = strzone(minigame_tile_buildname(letter, number)); + sent.cnt = ReadByte(); sent.snake_tail = ReadByte(); - sent.snake_dir_x = ReadCoord(); - sent.snake_dir_y = ReadCoord(); + + int dx = ReadByte(); + int dy = ReadByte(); + + if(dx == 2) dx = -1; + if(dy == 2) dy = -1; + + sent.snake_dir_x = dx; + sent.snake_dir_y = dy; sent.snake_dir_z = 0; } } else if ( sent.classname == "minigame_player" && (sf & SNAKE_SF_PLAYERSCORE ) ) { sent.snake_score = ReadLong(); - sent.snake_lives = ReadByte(); + minigame.snake_lives[sent.team] = ReadByte(); } return false; @@ -823,4 +836,4 @@ int snake_client_event(entity minigame, string event, ...) return false; } -#endif \ No newline at end of file +#endif