30 float autocvar_sv_minigames_pong_paddle_size;
31 float autocvar_sv_minigames_pong_paddle_speed;
33 float autocvar_sv_minigames_pong_ball_wait;
34 float autocvar_sv_minigames_pong_ball_speed;
35 float autocvar_sv_minigames_pong_ball_radius;
36 float autocvar_sv_minigames_pong_ball_number;
38 float autocvar_sv_minigames_pong_ai_thinkspeed;
39 float autocvar_sv_minigames_pong_ai_tolerance;
41 void pong_ball_think(
entity this);
44 void pong_ball_throw(
entity ball)
50 ball.velocity_x =
cos(angle)*autocvar_sv_minigames_pong_ball_speed;
51 ball.velocity_y =
sin(angle)*autocvar_sv_minigames_pong_ball_speed;
53 ball.nextthink =
time;
59 void pong_ball_throwthink(
entity this)
61 pong_ball_throw(
this);
65 void pong_ball_reset(
entity ball)
67 ball.velocity =
'0 0 0';
68 ball.origin =
'0.5 0.5 0';
72 setthink(ball, pong_ball_throwthink);
73 ball.nextthink =
time + autocvar_sv_minigames_pong_ball_wait;
77 void pong_add_score(
entity minigame,
int team_thrower,
int team_receiver,
int delta)
82 if ( team_thrower == 0 )
83 team_thrower = team_receiver;
85 if ( team_thrower == team_receiver )
88 entity paddle_thrower = minigame.pong_paddles[team_thrower-1];
89 if ( paddle_thrower.realowner.minigame_players )
91 paddle_thrower.realowner.minigame_players.pong_score += delta;
99 return vec2( p.x > box_max.x ? box_max.x : ( p.x < box_min.x ? box_min.x : p.x ),
100 p.y > box_max.y ? box_max.y : ( p.y < box_min.y ? box_min.y : p.y ) );
103 void pong_paddle_bounce(
entity ball,
int pteam)
107 case 1: ball.velocity_x = -
fabs(ball.velocity_x);
break;
108 case 2: ball.velocity_x =
fabs(ball.velocity_x);
break;
109 case 3: ball.velocity_y =
fabs(ball.velocity_y);
break;
110 case 4: ball.velocity_y = -
fabs(ball.velocity_y);
break;
113 float angle = atan2(ball.velocity_y, ball.velocity_x);
117 ball.velocity_y = speed *
sin(angle);
118 ball.velocity_x = speed *
cos(angle);
122 bool pong_paddle_hit(
entity ball,
int pteam)
124 entity paddle = ball.owner.pong_paddles[pteam-1];
129 vector near_point = box_nearest(paddle.m_mins+paddle.origin,
130 paddle.m_maxs+paddle.origin, ball.origin);
131 return vdist(near_point - ball.origin, <=, ball.pong_length);
133 return boxesoverlap(paddle.m_mins + paddle.origin, paddle.m_maxs + paddle.origin, ball.m_mins + ball.origin, ball.m_maxs + ball.origin);
138 bool pong_goal(
entity ball,
int pteam)
140 entity paddle = ball.owner.pong_paddles[pteam-1];
144 if ( !pong_paddle_hit(ball, pteam) )
146 pong_add_score(ball.owner ,ball.team, pteam, 1);
147 pong_ball_reset(ball);
155 void pong_ball_think(
entity this)
160 this.origin_x += this.velocity_x * think_speed;
161 this.origin_y += this.velocity_y * think_speed;
166 if ( pong_paddle_hit(
this, i) )
168 pong_paddle_bounce(
this,i);
176 if ( !pong_goal(
this,3) )
179 this.velocity_y *= -1;
184 if ( !pong_goal(
this,4) )
187 this.velocity_y *= -1;
193 if ( !pong_goal(
this,2) )
196 this.velocity_x *= -1;
201 if ( !pong_goal(
this,1) )
204 this.velocity_x *= -1;
211 void pong_ai_think(
entity this)
213 float think_speed = autocvar_sv_minigames_pong_ai_thinkspeed;
218 float min_distance = 1;
222 if ( mayball.classname ==
"pong_ball" )
224 distance =
vlen(mayball.origin-
this.pong_ai_paddle.origin);
225 next_distance =
vlen(mayball.origin+mayball.velocity-
this.pong_ai_paddle.origin);
226 if ( distance < min_distance && ( distance < 0.5 || next_distance < distance ) )
228 min_distance = distance;
237 if ( this.
team <= 2 )
240 target = ball.origin_y + ball.velocity_y*think_speed;
246 target = ball.origin_x + ball.velocity_x*think_speed;
250 distance = this.
pong_length/2 * autocvar_sv_minigames_pong_ai_tolerance
251 + autocvar_sv_minigames_pong_paddle_speed * think_speed;
253 if (target < my_pos - distance)
255 else if (target > my_pos + distance)
264 ai.minigame_players = ai;
265 ai.team = paddle.team;
268 ai.pong_ai_paddle = paddle;
270 paddle.realowner = ai;
276 void pong_paddle_think(
entity this)
281 if ( this.
realowner.minigame_players.pong_keys == PONG_KEY_INCREASE ||
282 this.realowner.minigame_players.pong_keys == PONG_KEY_DECREASE )
284 float pmovement = autocvar_sv_minigames_pong_paddle_speed * think_speed;
287 if ( this.
realowner.minigame_players.pong_keys == PONG_KEY_DECREASE )
291 this.origin_x =
bound(halflen, this.origin_x+pmovement, 1-halflen);
293 this.origin_y =
bound(halflen, this.origin_y+pmovement, 1-halflen);
299 vector pong_team_to_box_halfsize(
int nteam,
float length,
float width)
302 return vec2(length/2, width/2);
303 return vec2(width/2, length/2);
306 vector pong_team_to_paddlepos(
int nteam)
310 case 1:
return '0.99 0.5 0';
311 case 2:
return '0.01 0.5 0';
312 case 3:
return '0.5 0.01 0';
313 case 4:
return '0.5 0.99 0';
314 default:
return '0 0 0';
323 paddle.pong_length = autocvar_sv_minigames_pong_paddle_size;
324 paddle.origin = pong_team_to_paddlepos(pl_team);
325 setthink(paddle, pong_paddle_think);
326 paddle.nextthink =
time;
327 paddle.team = pl_team;
328 paddle.m_mins = pong_team_to_box_halfsize(pl_team,-paddle.pong_length,-1/16);
329 paddle.m_maxs = pong_team_to_box_halfsize(pl_team,paddle.pong_length,1/16);
331 if ( real_player ==
NULL )
332 pong_ai_spawn(paddle);
334 paddle.realowner = real_player;
336 minigame.pong_paddles[pl_team-1] = paddle;
343 int pong_server_event(
entity minigame,
string event, ...)
355 if ( minigame.minigame_flags & PONG_STATUS_PLAY )
362 if ( minigame.pong_paddles[i] ==
NULL )
364 pong_paddle_spawn(minigame,i+1,player);
379 paddle = minigame.pong_paddles[i];
380 if ( paddle !=
NULL && paddle.realowner == player )
382 ai = pong_ai_spawn(paddle);
383 ai.pong_score = player.minigame_players.pong_score;
399 if ( minigame.minigame_flags & PONG_STATUS_WAIT )
401 minigame.minigame_flags = PONG_STATUS_PLAY |
402 (minigame.minigame_flags & ~PONG_STATUS_WAIT);
406 for (
int j = 0; j < autocvar_sv_minigames_pong_ball_number; j++ )
409 ball.pong_length = autocvar_sv_minigames_pong_ball_radius;
410 ball.m_mins =
vec2(-ball.pong_length, -ball.pong_length);
411 ball.m_maxs =
vec2(ball.pong_length, ball.pong_length);
412 pong_ball_reset(ball);
429 player.pong_keys &= ~PONG_KEY_INCREASE;
434 player.pong_keys &= ~PONG_KEY_DECREASE;
449 if ( minigame.minigame_flags & PONG_STATUS_WAIT )
453 if ( minigame.pong_paddles[j] ==
NULL )
455 pong_paddle_spawn(minigame,j+1,
NULL);
459 sprint(player.minigame_players,
"Cannot spawn AI\n");
466 if ( minigame.minigame_flags & PONG_STATUS_WAIT )
469 for (
int j = PONG_MAX_PLAYERS-1; j >= 0; j-- )
471 paddle = minigame.pong_paddles[j];
472 if ( paddle !=
NULL &&
473 paddle.realowner.classname ==
"pong_ai" )
475 minigame.pong_paddles[j] =
NULL;
476 delete(paddle.realowner);
482 sprint(player.minigame_players,
"Cannot remove AI\n");
493 if ( sent.classname ==
"minigame_player" && (sf & PONG_SF_PLAYERSCORE ) )
508 float pong_team_to_angle(
int nteam)
515 case 3:
return M_PI*3/2;
516 case 4:
return M_PI/2;
520 vector pong_team_to_color(
int nteam)
524 case 1:
return '1 0 0';
525 case 2:
return '0 0 1';
526 case 3:
return '1 1 0';
527 case 4:
return '1 0 1';
528 default:
return '1 1 1';
532 int pong_keys_pressed;
533 int pong_keys_pressed_old;
538 if(pong_keys_pressed != pong_keys_pressed_old)
540 pong_keys_pressed_old = pong_keys_pressed;
550 if ( e.classname ==
"pong_ball" )
560 obj_size, pong_team_to_color(e.team),
563 else if ( e.classname ==
"pong_paddle" )
568 drawrotpic(obj_pos, pong_team_to_angle(e.team),
minigame_texture(
"pong/paddle-glow"),
569 obj_size, obj_size/2, pong_team_to_color(e.team),
572 drawrotpic(obj_pos, pong_team_to_angle(e.team),
minigame_texture(
"pong/paddle"),
573 obj_size, obj_size/2,
'1 1 1',
587 ts_y += hud_fontsize_y;
592 ts_y = ( mySize_y - PONG_MAX_PLAYERS*player_fontsize_y ) / PONG_MAX_PLAYERS;
599 if ( (e.classname ==
"minigame_player" || e.classname ==
"pong_ai") && e.team != PONG_SPECTATOR_TEAM )
602 mypos_y += (e.team-1) * (player_fontsize_y + ts_y);
607 (e.minigame_playerslot ? entcs_GetName(e.minigame_playerslot-1) : _(
"AI")),
620 string pong_message(
int mgflags)
622 string rmessage =
"";
624 rmessage = _(
"You are spectating");
625 else if (mgflags & PONG_STATUS_WAIT)
626 rmessage = _(
"Press ^1Start Match^7 to start the match with the current players");
631 int pong_client_event(
entity minigame,
string event, ...)
644 if ((minigame.minigame_flags & PONG_STATUS_PLAY) &&
minigame_self.team != PONG_SPECTATOR_TEAM)
645 switch ( ...(0,
int) )
651 if (event ==
"key_pressed")
659 pong_keys_pressed &= ~PONG_KEY_DECREASE;
666 if (event ==
"key_pressed")
674 pong_keys_pressed &= ~PONG_KEY_INCREASE;
679 case "network_receive":
683 if ( sent.classname ==
"minigame_player" && (sf & PONG_SF_PLAYERSCORE ) )
685 sent.pong_score = ReadLong();
687 else if ( sent.classname ==
"minigame" )
691 strcpy(sent.message, pong_message(sent.minigame_flags));
706 if( cmd ==
"pong_throw" && minigame.minigame_flags & PONG_STATUS_WAIT )
710 else if ( cmd ==
"pong_aimore" || cmd ==
"pong_ailess" )
void HUD_MinigameMenu_CustomEntry(entity parent, string menumessage, string event_arg)
#define FOREACH_MINIGAME_ENTITY(entityvar)
vector minigame_hud_denormalize_size(vector v, vector pos, vector mySize)
#define minigame_hud_fitsqare(pos, mySize)
entity msle_spawn(entity minigame_session, entity e)
float autocvar_sys_ticrate
const int PONG_STATUS_PLAY
const int PONG_STATUS_WAIT
const int PONG_SPECTATOR_TEAM
const int MINIG_SF_UPDATE
const int PONG_MAX_PLAYERS
const float DRAWFLAG_ADDITIVE
const int MINIG_SF_CUSTOM
#define HUD_Panel_DrawBg()
void minigame_drawpic_centered(vector pos, string texture, vector sz, vector color, float thealpha, int drawflags)
string minigame_texture(string name)
REGISTER_MINIGAME(pong, _("Pong"))
ERASEABLE float boxesoverlap(vector m1, vector m2, vector m3, vector m4)
requires that m2>m1 in all coordinates, and that m4>m3
spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 f1 s1 strcat(_("Level %s: "), "^BG%s\3\, _("^BGPress ^F2%s^BG to enter the game"))
const float DRAWFLAG_NORMAL
#define minigame_cmd(...)
const int PONG_KEY_INCREASE
vector(float skel, float bonenum) _skel_get_boneabs_hidden
void SUB_NullThink(entity this)
#define vdist(v, cmp, f)
Vector distance comparison, avoids sqrt()
vector minigame_hud_denormalize(vector v, vector pos, vector mySize)
void drawborderlines(float thickness, vector pos, vector dim, vector color, float theAlpha, float drawflag)
const int PONG_SF_BALLTEAM
void minigame_drawcolorcodedstring_trunc(float maxwidth, vector pos, string text, vector fontsize, float theAlpha, int drawflags)
const int PONG_KEY_DECREASE
void minigame_hud_simpleboard(vector pos, vector mySize, string board_texture)
const int PONG_SF_PLAYERSCORE
entity pong_paddles[PONG_MAX_PLAYERS]
vector minigame_drawstring_wrapped(float maxwidth, vector pos, string text, vector fontsize, vector color, float theAlpha, int drawflags, float align)