1 #include "minigames.qh"
3 void player_clear_minigame(entity player)
5 player.active_minigame = NULL;
6 player.minigame_players = NULL;
7 if ( IS_PLAYER(player) )
8 set_movetype(player, MOVETYPE_WALK);
10 set_movetype(player, MOVETYPE_FLY_WORLDONLY);
11 player.team_forced = 0;
14 void minigame_rmplayer(entity minigame_session, entity player)
17 entity p = minigame_session.minigame_players;
19 if ( p.minigame_players == player )
21 if ( p.list_next == NULL )
23 end_minigame(minigame_session);
26 minigame_session.minigame_event(minigame_session,"part",player);
27 GameLogEcho(strcat(":minigame:part:",minigame_session.netname,":",
28 ftos(etof(player)),":",player.netname));
29 minigame_session.minigame_players = p.list_next;
31 player_clear_minigame(player);
35 for ( e = p.list_next; e != NULL; e = e.list_next )
37 if ( e.minigame_players == player )
39 minigame_session.minigame_event(minigame_session,"part",player);
40 GameLogEcho(strcat(":minigame:part:",minigame_session.netname,":",
41 ftos(etof(player)),":",player.netname));
42 p.list_next = e.list_next;
44 player_clear_minigame(player);
53 #define FIELD(Flags, Type,Name) if ( sf & (Flags) ) Write##Type(MSG_ENTITY, this.Name);
54 #define MSLE(Name,Fields) \
55 else if ( this.classname == #Name ) { \
56 if ( sf & MINIG_SF_CREATE ) WriteString(MSG_ENTITY,this.owner.netname); \
59 // Send an entity to a client
60 // only use on minigame entities or entities with a minigame owner
61 bool minigame_SendEntity(entity this, entity to, int sf)
63 WriteHeader(MSG_ENTITY, ENT_CLIENT_MINIGAME);
64 WriteByte(MSG_ENTITY, sf);
66 if ( sf & MINIG_SF_CREATE )
68 WriteShort(MSG_ENTITY,msle_id(this.classname));
69 WriteString(MSG_ENTITY,this.netname);
72 entity minigame_ent = this.owner;
74 if ( this.classname == "minigame" )
78 if ( sf & MINIG_SF_CREATE )
79 WriteString(MSG_ENTITY,this.descriptor.netname);
81 if ( sf & MINIG_SF_UPDATE )
82 WriteLong(MSG_ENTITY,this.minigame_flags);
84 else if ( this.classname == "minigame_player" )
86 if ( sf & MINIG_SF_CREATE )
88 WriteString(MSG_ENTITY,this.owner.netname);
89 WriteLong(MSG_ENTITY,etof(this.minigame_players));
91 if ( sf & MINIG_SF_UPDATE )
92 WriteByte(MSG_ENTITY,this.team);
94 MINIGAME_SIMPLELINKED_ENTITIES
96 minigame_ent.minigame_event(minigame_ent,"network_send",this,sf);
104 // Force resend all minigame entities
105 void minigame_resend(entity minigame)
107 minigame.SendFlags = MINIG_SF_ALL;
109 while (( e = findentity(e,owner,minigame) ))
111 e.SendFlags = MINIG_SF_ALL;
115 bool minigame_CheckSend(entity this, entity client)
118 for ( e = this.owner.minigame_players; e != NULL; e = e.list_next )
119 if ( e.minigame_players == client )
124 int minigame_addplayer(entity minigame_session, entity player)
126 if ( player.active_minigame )
128 if ( player.active_minigame == minigame_session )
130 minigame_rmplayer(player.active_minigame,player);
132 entity player_pointer = new(minigame_player);
133 int mgteam = minigame_session.minigame_event(minigame_session,"join",player,player_pointer);
137 player_pointer.owner = minigame_session;
138 player_pointer.minigame_players = player;
139 player_pointer.team = mgteam;
140 player_pointer.list_next = minigame_session.minigame_players;
141 minigame_session.minigame_players = player_pointer;
142 player.active_minigame = minigame_session;
143 player.minigame_players = player_pointer;
144 setcefc(player_pointer, minigame_CheckSend);
145 Net_LinkEntity(player_pointer, false, 0, minigame_SendEntity);
147 if ( !IS_OBSERVER(player) && autocvar_sv_minigames_observer )
149 PutObserverInServer(player);
151 if ( autocvar_sv_minigames_observer == 2 )
152 player.team_forced = -1;
154 minigame_resend(minigame_session);
156 else { remove(player_pointer); }
157 GameLogEcho(strcat(":minigame:join",(mgteam?"":"fail"),":",minigame_session.netname,":",
158 ftos(etof(player)),":",player.netname));
163 entity start_minigame(entity player, string minigame )
165 if ( !autocvar_sv_minigames || !IS_REAL_CLIENT(player) )
168 entity e = minigame_get_descriptor(minigame);
171 entity minig = new(minigame);
172 minig.netname = strzone(strcat(e.netname,"_",ftos(etof(minig))));
173 minig.descriptor = e;
174 minig.minigame_event = e.minigame_event;
175 minig.minigame_event(minig,"start");
176 GameLogEcho(strcat(":minigame:start:",minig.netname));
177 if ( ! minigame_addplayer(minig,player) )
179 LOG_TRACE("Minigame ",minig.netname," rejected the first player join!\n");
183 Net_LinkEntity(minig, false, 0, minigame_SendEntity);
185 if ( !minigame_sessions )
186 minigame_sessions = minig;
189 minigame_sessions.owner = minig;
190 minig.list_next = minigame_sessions;
191 minigame_sessions = minig;
199 entity join_minigame(entity player, string game_id )
201 if ( !autocvar_sv_minigames || !IS_REAL_CLIENT(player) )
205 for ( minig = minigame_sessions; minig != NULL; minig = minig.list_next )
207 if ( minig.netname == game_id )
208 if ( minigame_addplayer(minig,player) )
215 void part_minigame(entity player )
217 entity minig = player.active_minigame;
219 if ( minig && minig.classname == "minigame" )
220 minigame_rmplayer(minig,player);
223 void end_minigame(entity minigame_session)
225 if ( minigame_session.owner )
226 minigame_session.owner.list_next = minigame_session.list_next;
228 minigame_sessions = minigame_session.list_next;
230 minigame_session.minigame_event(minigame_session,"end");
231 GameLogEcho(strcat(":minigame:end:",minigame_session.netname));
235 while( (e = findentity(e, owner, minigame_session)) )
236 if ( e.minigame_autoclean )
238 LOG_TRACE("SV Auto-cleaned: ",ftos(etof(e)), " (",e.classname,")\n");
243 for ( e = minigame_session.minigame_players; e != NULL; e = p )
246 player_clear_minigame(e.minigame_players);
250 strunzone(minigame_session.netname);
251 remove(minigame_session);
256 while ( minigame_sessions )
258 end_minigame(minigame_sessions);
262 string invite_minigame(entity inviter, entity player)
264 if ( !inviter || !inviter.active_minigame )
265 return "Invalid minigame";
266 if ( !VerifyClientEntity(player, true, false) )
267 return "Invalid player";
268 if ( inviter == player )
269 return "You can't invite yourself";
270 if ( player.active_minigame == inviter.active_minigame )
271 return strcat(player.netname," is already playing");
273 Send_Notification(NOTIF_ONE, player, MSG_INFO, INFO_MINIGAME_INVITE,
274 inviter.active_minigame.netname, inviter.netname );
276 GameLogEcho(strcat(":minigame:invite:",inviter.active_minigame.netname,":",
277 ftos(etof(player)),":",player.netname));
282 entity minigame_find_player(entity client)
284 if ( ! client.active_minigame )
287 for ( e = client.active_minigame.minigame_players; e; e = e.list_next )
288 if ( e.minigame_players == client )
293 bool MinigameImpulse(entity this, int imp)
295 if (!this.active_minigame) return false;
296 entity e = minigame_find_player(this);
297 if ( imp && this.active_minigame && e )
299 return this.active_minigame.minigame_event(this.active_minigame,"impulse",e,imp);
306 void ClientCommand_minigame(entity caller, int request, int argc, string command)
308 if ( !autocvar_sv_minigames )
310 sprint(caller,"Minigames are not enabled!\n");
314 if (request == CMD_REQUEST_COMMAND )
316 string minig_cmd = argv(1);
317 if ( minig_cmd == "create" && argc > 2 )
319 entity minig = start_minigame(caller, argv(2));
321 sprint(caller,"Created minigame session: ",minig.netname,"\n");
323 sprint(caller,"Cannot start minigame session!\n");
326 else if ( minig_cmd == "join" && argc > 2 )
328 entity minig = join_minigame(caller, argv(2));
330 sprint(caller,"Joined: ",minig.netname,"\n");
333 Send_Notification(NOTIF_ONE, caller, MSG_CENTER, CENTER_JOIN_PREVENT_MINIGAME);
334 sprint(caller,"Cannot join given minigame session!\n");
338 else if ( minig_cmd == "list" )
340 FOREACH(Minigames, true, sprint(caller, it.netname, " (", it.message, ") ", "\n"));
343 else if ( minig_cmd == "list-sessions" )
346 for ( e = minigame_sessions; e != NULL; e = e.list_next )
347 sprint(caller,e.netname,"\n");
350 else if ( minig_cmd == "end" || minig_cmd == "part" )
352 if ( caller.active_minigame )
354 part_minigame(caller);
355 sprint(caller,"Left minigame session\n");
358 sprint(caller,"You aren't playing any minigame...\n");
361 else if ( minig_cmd == "invite" && argc > 2 )
363 if ( caller.active_minigame )
365 entity client = GetIndexedEntity(argc, 2);
366 string error = invite_minigame(caller,client);
369 sprint(caller,"You have invited ",client.netname,
370 " to join your game of ", caller.active_minigame.descriptor.message, "\n");
373 sprint(caller,"Could not invite: ", error, ".\n");
376 sprint(caller,"You aren't playing any minigame...\n");
379 else if ( caller.active_minigame )
381 entity e = minigame_find_player(caller);
382 string subcommand = substring(command,argv_end_index(0),-1);
383 int arg_c = tokenize_console(subcommand);
384 if ( caller.active_minigame.minigame_event(caller.active_minigame,"cmd",e,arg_c,subcommand) )
388 else sprint(caller,strcat("Wrong command:^1 ",command,"\n"));
391 sprint(caller, "\nUsage:^3 cmd minigame create <minigame>\n");
392 sprint(caller, " Start a new minigame session\n");
393 sprint(caller, "Usage:^3 cmd minigame join <session>\n");
394 sprint(caller, " Join an exising minigame session\n");
395 sprint(caller, "Usage:^3 cmd minigame list\n");
396 sprint(caller, " List available minigames\n");
397 sprint(caller, "Usage:^3 cmd minigame list-sessions\n");
398 sprint(caller, " List available minigames sessions\n");
399 sprint(caller, "Usage:^3 cmd minigame part|end\n");
400 sprint(caller, " Leave the current minigame\n");
401 sprint(caller, "Usage:^3 cmd minigame invite <player>\n");
402 sprint(caller, " Invite the given player to join you in a minigame\n");