1 #include "minigames.qh"
3 void player_clear_minigame(entity player)
5 player.active_minigame = world;
6 player.minigame_players = world;
7 if ( IS_PLAYER(player) )
8 player.movetype = MOVETYPE_WALK;
10 player.movetype = 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 == world )
23 end_minigame(minigame_session);
26 minigame_session.minigame_event(minigame_session,"part",player);
27 GameLogEcho(strcat(":minigame:part:",minigame_session.netname,":",
28 ftos(num_for_edict(player)),":",player.netname));
29 minigame_session.minigame_players = p.list_next;
31 player_clear_minigame(player);
35 for ( e = p.list_next; e != world; 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(num_for_edict(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, self.Name);
54 #define WriteVector(to,Name) WriteCoord(to,Name##_x); WriteCoord(to,Name##_y); WriteCoord(to,Name##_z)
55 #define WriteVector2D(to,Name) WriteCoord(to,Name##_x); WriteCoord(to,Name##_y)
56 #define MSLE(Name,Fields) \
57 else if ( self.classname == #Name ) { \
58 if ( sf & MINIG_SF_CREATE ) WriteString(MSG_ENTITY,self.owner.netname); \
61 // Send an entity to a client
62 // only use on minigame entities or entities with a minigame owner
63 bool minigame_SendEntity(entity to, int sf)
65 WriteByte(MSG_ENTITY, ENT_CLIENT_MINIGAME);
66 WriteByte(MSG_ENTITY, sf);
68 if ( sf & MINIG_SF_CREATE )
70 WriteShort(MSG_ENTITY,msle_id(self.classname));
71 WriteString(MSG_ENTITY,self.netname);
74 entity minigame_ent = self.owner;
76 if ( self.classname == "minigame" )
80 if ( sf & MINIG_SF_CREATE )
81 WriteString(MSG_ENTITY,self.descriptor.netname);
83 if ( sf & MINIG_SF_UPDATE )
84 WriteLong(MSG_ENTITY,self.minigame_flags);
86 else if ( self.classname == "minigame_player" )
88 if ( sf & MINIG_SF_CREATE )
90 WriteString(MSG_ENTITY,self.owner.netname);
91 WriteLong(MSG_ENTITY,num_for_edict(self.minigame_players));
93 if ( sf & MINIG_SF_UPDATE )
94 WriteByte(MSG_ENTITY,self.team);
96 MINIGAME_SIMPLELINKED_ENTITIES
98 minigame_ent.minigame_event(minigame_ent,"network_send",self,sf);
106 // Force resend all minigame entities
107 void minigame_resend(entity minigame)
109 minigame.SendFlags = MINIG_SF_ALL;
111 while (( e = findentity(e,owner,minigame) ))
113 e.SendFlags = MINIG_SF_ALL;
117 bool minigame_CheckSend()
120 for ( e = self.owner.minigame_players; e != world; e = e.list_next )
121 if ( e.minigame_players == other )
126 int minigame_addplayer(entity minigame_session, entity player)
128 if ( player.active_minigame )
130 if ( player.active_minigame == minigame_session )
132 minigame_rmplayer(player.active_minigame,player);
135 int mgteam = minigame_session.minigame_event(minigame_session,"join",player);
139 entity player_pointer = spawn();
140 player_pointer.classname = "minigame_player";
141 player_pointer.owner = minigame_session;
142 player_pointer.minigame_players = player;
143 player_pointer.team = mgteam;
144 player_pointer.list_next = minigame_session.minigame_players;
145 minigame_session.minigame_players = player_pointer;
146 player.active_minigame = minigame_session;
147 player.minigame_players = player_pointer;
148 player_pointer.customizeentityforclient = minigame_CheckSend;
149 Net_LinkEntity(player_pointer, false, 0, minigame_SendEntity);
151 if ( !IS_OBSERVER(player) && autocvar_sv_minigames_observer )
153 SELFCALL(player, PutObserverInServer());
156 if ( autocvar_sv_minigames_observer == 2 )
157 player.team_forced = -1;
159 minigame_resend(minigame_session);
161 GameLogEcho(strcat(":minigame:join",(mgteam?"":"fail"),":",minigame_session.netname,":",
162 ftos(num_for_edict(player)),":",player.netname));
167 entity start_minigame(entity player, string minigame )
169 if ( !autocvar_sv_minigames || !IS_REAL_CLIENT(player) )
172 entity e = minigame_get_descriptor(minigame);
175 entity minig = spawn();
176 minig.classname = "minigame";
177 minig.netname = strzone(strcat(e.netname,"_",ftos(num_for_edict(minig))));
178 minig.descriptor = e;
179 minig.minigame_event = e.minigame_event;
180 minig.minigame_event(minig,"start");
181 GameLogEcho(strcat(":minigame:start:",minig.netname));
182 if ( ! minigame_addplayer(minig,player) )
184 LOG_TRACE("Minigame ",minig.netname," rejected the first player join!\n");
188 Net_LinkEntity(minig, false, 0, minigame_SendEntity);
190 if ( !minigame_sessions )
191 minigame_sessions = minig;
194 minigame_sessions.owner = minig;
195 minig.list_next = minigame_sessions;
196 minigame_sessions = minig;
204 entity join_minigame(entity player, string game_id )
206 if ( !autocvar_sv_minigames || !IS_REAL_CLIENT(player) )
210 for ( minig = minigame_sessions; minig != world; minig = minig.list_next )
212 if ( minig.netname == game_id )
213 if ( minigame_addplayer(minig,player) )
220 void part_minigame(entity player )
222 entity minig = player.active_minigame;
224 if ( minig && minig.classname == "minigame" )
225 minigame_rmplayer(minig,player);
228 void end_minigame(entity minigame_session)
230 if ( minigame_session.owner )
231 minigame_session.owner.list_next = minigame_session.list_next;
233 minigame_sessions = minigame_session.list_next;
235 minigame_session.minigame_event(minigame_session,"end");
236 GameLogEcho(strcat(":minigame:end:",minigame_session.netname));
240 while( (e = findentity(e, owner, minigame_session)) )
241 if ( e.minigame_autoclean )
243 LOG_TRACE("SV Auto-cleaned: ",ftos(num_for_edict(e)), " (",e.classname,")\n");
248 for ( e = minigame_session.minigame_players; e != world; e = p )
251 player_clear_minigame(e.minigame_players);
255 strunzone(minigame_session.netname);
256 remove(minigame_session);
261 while ( minigame_sessions )
263 end_minigame(minigame_sessions);
267 void initialize_minigames()
269 entity last_minig = world;
271 #define MINIGAME(name,nicename) \
273 minig.classname = "minigame_descriptor"; \
274 minig.netname = #name; \
275 minig.message = nicename; \
276 minig.minigame_event = name##_server_event; \
277 if ( !last_minig ) minigame_descriptors = minig; \
278 else last_minig.list_next = minig; \
286 string invite_minigame(entity inviter, entity player)
288 if ( !inviter || !inviter.active_minigame )
289 return "Invalid minigame";
290 if ( !VerifyClientEntity(player, true, false) )
291 return "Invalid player";
292 if ( inviter == player )
293 return "You can't invite yourself";
294 if ( player.active_minigame == inviter.active_minigame )
295 return strcat(player.netname," is already playing");
297 Send_Notification(NOTIF_ONE, player, MSG_INFO, INFO_MINIGAME_INVITE,
298 inviter.active_minigame.netname, inviter.netname );
300 GameLogEcho(strcat(":minigame:invite:",inviter.active_minigame.netname,":",
301 ftos(num_for_edict(player)),":",player.netname));
306 entity minigame_find_player(entity client)
308 if ( ! client.active_minigame )
311 for ( e = client.active_minigame.minigame_players; e; e = e.list_next )
312 if ( e.minigame_players == client )
317 bool MinigameImpulse(int imp)
319 entity e = minigame_find_player(self);
320 if ( imp && self.active_minigame && e )
322 return self.active_minigame.minigame_event(self.active_minigame,"impulse",e,imp);
329 void ClientCommand_minigame(int request, int argc, string command)
331 if ( !autocvar_sv_minigames )
333 sprint(self,"Minigames are not enabled!\n");
337 if (request == CMD_REQUEST_COMMAND )
339 string minig_cmd = argv(1);
340 if ( minig_cmd == "create" && argc > 2 )
342 entity minig = start_minigame(self, argv(2));
344 sprint(self,"Created minigame session: ",minig.netname,"\n");
346 sprint(self,"Cannot start minigame session!\n");
349 else if ( minig_cmd == "join" && argc > 2 )
351 entity minig = join_minigame(self, argv(2));
353 sprint(self,"Joined: ",minig.netname,"\n");
356 Send_Notification(NOTIF_ONE, self, MSG_CENTER, CENTER_JOIN_PREVENT_MINIGAME);
357 sprint(self,"Cannot join given minigame session!\n");
361 else if ( minig_cmd == "list" )
364 for ( e = minigame_descriptors; e != world; e = e.list_next )
365 sprint(self,e.netname," (",e.message,") ","\n");
368 else if ( minig_cmd == "list-sessions" )
371 for ( e = minigame_sessions; e != world; e = e.list_next )
372 sprint(self,e.netname,"\n");
375 else if ( minig_cmd == "end" || minig_cmd == "part" )
377 if ( self.active_minigame )
380 sprint(self,"Left minigame session\n");
383 sprint(self,"You aren't playing any minigame...\n");
386 else if ( minig_cmd == "invite" && argc > 2 )
388 if ( self.active_minigame )
390 entity client = GetIndexedEntity(argc, 2);
391 string error = invite_minigame(self,client);
394 sprint(self,"You have invited ",client.netname,
395 " to join your game of ", self.active_minigame.descriptor.message, "\n");
398 sprint(self,"Could not invite: ", error, ".\n");
401 sprint(self,"You aren't playing any minigame...\n");
404 else if ( self.active_minigame )
406 entity e = minigame_find_player(self);
407 string subcommand = substring(command,argv_end_index(0),-1);
408 int arg_c = tokenize_console(subcommand);
409 if ( self.active_minigame.minigame_event(self.active_minigame,"cmd",e,arg_c,subcommand) )
413 else sprint(self,strcat("Wrong command:^1 ",command,"\n"));
416 sprint(self, "\nUsage:^3 cmd minigame create <minigame>\n");
417 sprint(self, " Start a new minigame session\n");
418 sprint(self, "Usage:^3 cmd minigame join <session>\n");
419 sprint(self, " Join an exising minigame session\n");
420 sprint(self, "Usage:^3 cmd minigame list\n");
421 sprint(self, " List available minigames\n");
422 sprint(self, "Usage:^3 cmd minigame list-sessions\n");
423 sprint(self, " List available minigames sessions\n");
424 sprint(self, "Usage:^3 cmd minigame part|end\n");
425 sprint(self, " Leave the current minigame\n");
426 sprint(self, "Usage:^3 cmd minigame invite <player>\n");
427 sprint(self, " Invite the given player to join you in a minigame\n");