2 const int PONG_SF_PLAYERSCORE = MINIG_SF_CUSTOM; // sent when reporting scores
3 const int PONG_SF_SINGLEPLAYER = MINIG_SF_CUSTOM<<1;// send minigame.pong_ai
6 .int pong_ai; // (minigame) when non-zero, singleplayer vs AI
7 .int pong_score; // (minigame_player) number of goals
8 .entity pong_paddles[2];// (minigame) paddles
9 .float pong_length;// (pong_paddle) size (0,1)
13 float autocvar_sv_minigames_pong_paddlesize = 0.3;
14 float autocvar_sv_minigames_pong_paddlespeed= 1;
15 float autocvar_sv_minigames_pong_ballwait = 1;
16 float autocvar_sv_minigames_pong_ballspeed = 1;
18 void pong_ball_think();
20 void pong_ball_thinkthrow()
24 angle = random()*M_PI*2;
25 while ( (angle > 0.44*M_PI && angle < 0.55*M_PI) ||
26 (angle > 1.44*M_PI && angle < 1.55*M_PI) );
27 self.velocity_x = cos(angle)*autocvar_sv_minigames_pong_ballspeed;
28 self.velocity_y = sin(angle)*autocvar_sv_minigames_pong_ballspeed;
29 self.SendFlags |= MINIG_SF_UPDATE;
30 self.think = pong_ball_think;
31 self.nextthink = time;
34 void pong_reset_ball(entity ball)
36 ball.velocity = '0 0 0';
37 ball.origin = '0.5 0.5 0';
38 ball.SendFlags |= MINIG_SF_UPDATE;
39 ball.think = pong_ball_thinkthrow;
40 ball.nextthink = time + autocvar_sv_minigames_pong_ballwait;
43 void pong_add_score(entity minigame, int pteam)
47 entity paddle = minigame.pong_paddles[pteam-1];
48 if ( paddle.realowner )
50 paddle.realowner.pong_score++;
51 paddle.realowner.SendFlags |= PONG_SF_PLAYERSCORE;
55 bool pong_goal(entity ball, int pteam)
57 entity paddle = ball.owner.pong_paddles[pteam-1];
60 if ( ball.origin_y < paddle.origin_y-paddle.pong_length/2 ||
61 ball.origin_y > paddle.origin_y+paddle.pong_length/2 )
63 pong_add_score(ball.owner,minigame_next_team(pteam, 2));
64 pong_reset_ball(ball);
70 void pong_ball_think()
72 float think_speed = autocvar_sys_ticrate;
73 self.nextthink = time + think_speed;
75 self.origin_x += self.velocity_x * think_speed;
76 self.origin_y += self.velocity_y * think_speed;
77 if ( self.origin_y <= 0 )
80 self.velocity_y *= -1;
82 else if ( self.origin_y >= 1 )
85 self.velocity_y *= -1;
88 if ( self.origin_x <= 0 )
90 if ( !pong_goal(self,2) )
93 self.velocity_x *= -1;
96 else if ( self.origin_x >= 1 )
98 if ( !pong_goal(self,1) )
101 self.velocity_x *= -1;
105 self.SendFlags |= MINIG_SF_UPDATE;
108 void pong_paddle_think()
110 float think_speed = autocvar_sys_ticrate;
111 self.nextthink = time + think_speed;
113 if ( self.realowner.movement.x > 0 && self.origin_y > self.pong_length/2 )
115 self.origin_y -= autocvar_sv_minigames_pong_paddlespeed * think_speed;
116 if ( self.origin_y < 0 )
118 self.SendFlags |= MINIG_SF_UPDATE;
120 else if ( self.realowner.movement.x < 0 && self.origin_y < 1-self.pong_length/2 )
122 self.origin_y += autocvar_sv_minigames_pong_paddlespeed * think_speed;
123 if ( self.origin_y > 1 )
125 self.SendFlags |= MINIG_SF_UPDATE;
130 // required function, handle server side events
131 int minigame_event_pong(entity minigame, string event, ...)
137 entity ball = msle_spawn(minigame,"pong_ball");
138 pong_reset_ball(ball);
146 int pl_num = minigame_count_players(minigame);
148 // Don't allow joining a single player match
149 if ( (minigame.pong_ai) && pl_num > 0 )
152 // Don't allow more than 2 players
153 if(pl_num >= 2) { return false; }
156 // Get the right team
157 if(minigame.minigame_players)
158 pl_team = minigame_next_team(minigame.minigame_players.team, 2);
161 entity player = ...(0,entity);
162 entity paddle = msle_spawn(minigame,"pong_paddle");// Note puddle isn't a typo
163 paddle.pong_length = autocvar_sv_minigames_pong_paddlesize;
164 paddle.origin_y = 0.5;
165 paddle.origin_x = pl_team == 1 ? 0.99 : 0.01;
166 paddle.think = pong_paddle_think;
167 paddle.nextthink = time;
168 paddle.team = pl_team;
169 paddle.realowner = player;
170 minigame.pong_paddles[pl_team-1] = paddle;
183 entity sent = ...(0,entity);
185 if ( sent.classname == "minigame_player" && (sf & PONG_SF_PLAYERSCORE ) )
187 WriteByte(MSG_ENTITY,sent.pong_score);
189 else if ( sent.classname == "minigame" && (sf & PONG_SF_SINGLEPLAYER) )
191 WriteByte(MSG_ENTITY,sent.pong_ai);
203 // Required function, draw the game board
204 void minigame_hud_board_pong(vector pos, vector mySize)
206 minigame_hud_fitsqare(pos, mySize);
207 minigame_hud_simpleboard(pos,mySize,minigame_texture("pong/board"));
211 vector ball_size = minigame_hud_denormalize_size('1 1 0' / 16,pos,mySize);
213 FOREACH_MINIGAME_ENTITY(e)
215 if ( e.classname == "pong_ball" )
217 obj_pos = minigame_hud_denormalize(e.origin,pos,mySize);
218 minigame_drawpic_centered( obj_pos, minigame_texture("pong/ball"),
219 ball_size, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL );
221 else if ( e.classname == "pong_paddle" )
223 obj_pos = minigame_hud_denormalize(e.origin,pos,mySize);
224 paddle_size = minigame_hud_denormalize_size(eX / 32 + eY*e.pong_length,pos,mySize);
225 minigame_drawpic_centered( obj_pos, minigame_texture("pong/paddle"),
226 paddle_size, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL );
232 // Required function, draw the game status panel
233 void minigame_hud_status_pong(vector pos, vector mySize)
237 ts = minigame_drawstring_wrapped(mySize_x,pos,active_minigame.descriptor.message,
238 hud_fontsize * 2, '0.25 0.47 0.72', panel_fg_alpha, DRAWFLAG_NORMAL,0.5);
243 vector player_fontsize = hud_fontsize * 1.75;
244 ts_y = ( mySize_y - 2*player_fontsize_y ) / 2;
247 vector tile_size = '48 48 0';
250 FOREACH_MINIGAME_ENTITY(e)
252 if ( e.classname == "minigame_player" )
256 mypos_y += player_fontsize_y + ts_y;
257 minigame_drawcolorcodedstring_trunc(mySize_x,mypos,
258 (e.minigame_playerslot ? GetPlayerName(e.minigame_playerslot-1) : _("AI")),
259 player_fontsize, panel_fg_alpha, DRAWFLAG_NORMAL);
261 mypos_y += player_fontsize_y;
263 drawstring(mypos,ftos(e.pong_score),tile_size,
264 '0.7 0.84 1', panel_fg_alpha, DRAWFLAG_NORMAL);
270 // Required function, handle client events
271 int minigame_event_pong(entity minigame, string event, ...)
278 switch ( ...(0,int) )
288 case "network_receive":
290 entity sent = ...(0,entity);
292 if ( sent.classname == "minigame_player" && (sf & PONG_SF_PLAYERSCORE ) )
294 sent.pong_score = ReadByte();
296 else if ( sent.classname == "minigame" && (sf & PONG_SF_SINGLEPLAYER) )
299 bool spawnai = ai && !sent.pong_ai;
304 entity aiplayer = spawn();
305 aiplayer.classname = "minigame_player";
306 aiplayer.owner = minigame;
308 aiplayer.minigame_playerslot = 0;
309 aiplayer.minigame_autoclean = 1;
310 // todo aiplayer.think
317 HUD_MinigameMenu_CustomEntry(...(0,entity),_("Single Player"),"singleplayer");
322 if ( ...(0,string) == "singleplayer" && !minigame.pong_ai )
324 if ( minigame_count_players(minigame) == 1 )
325 minigame_cmd("singleplayer");