Advertisement
slc_world

VC:MP TeamupSystem

Oct 31st, 2014
241
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
D 19.34 KB | None | 0 0
  1. // VC:MP TeamupSystem
  2.  
  3. // ------------------------------------------------------------------------------------------------
  4. // Global table used to scope base configurations
  5. _CFG <- {}
  6. // Global table used to scope script commands
  7. _CMD <- {}
  8.  
  9. // ------------------------------------------------------------------------------------------------
  10. // Global enumeration to hold the command syntax
  11. enum CmdSyn
  12. {
  13.     TeamUp = "teamup <player-name>",
  14.     SplitUp = "splitup",
  15.     DenyReq = "denyreq <player-name>",
  16.     DenyAll = "denyall",
  17.     AcceptReq = "acceptreq <player-name>",
  18.     AcceptAny = "acceptany",
  19.     FlushReq = "flushreq",
  20.     PlaySolo = "playsolo",
  21.     Partner = "partner"
  22. }
  23.  
  24. // ------------------------------------------------------------------------------------------------
  25. // Global enumeration to hold the message style and colours
  26. enum MsgTag {
  27.     Dbg = "[#11455D][DEBUG][#F4F3EE]",
  28.     Msg = "[#64A5BB][MESSAGE][#F4F3EE]",
  29.     Scs = "[#698433][SUCCESS][#F4F3EE]",
  30.     Inf = "[#FFD35C][INFO][#F4F3EE]",
  31.     Wrn = "[#FF8202][WARNING][#F4F3EE]",
  32.     Err = "[#EA3E70][ERROR][#F4F3EE]",
  33.     Ftl = "[#C82C3A][FATAL][#F4F3EE]"
  34. }
  35.  
  36. // ------------------------------------------------------------------------------------------------
  37. // Scoped functions used to send formatted messages to players
  38. _Msg <- {
  39.     // --------------------------------------------------------------------------------------------
  40.     function Player(...)
  41.     {
  42.         // Grab the player instance from the first argument
  43.         local i_player = vargv[0];
  44.         // Replace the player instance with the (this) environment
  45.         vargv[0] = this;
  46.         // Forward all the arguments to the format function
  47.         local str = ::format.acall(vargv);
  48.         // Send the generated message to the specified player
  49.         MessagePlayer(str, i_player);
  50.     }
  51. }
  52.  
  53. // ------------------------------------------------------------------------------------------------
  54. _ClientPool <- []
  55.  
  56. // ------------------------------------------------------------------------------------------------
  57. _TeamupPool <- []
  58.  
  59. // ------------------------------------------------------------------------------------------------
  60. // Class responsible for management and identification of player instances
  61. class _Client
  62. {
  63.     // --------------------------------------------------------------------------------------------
  64.     function constructor(i_player)
  65.     {
  66.         // Verify the player instance
  67.         if (typeof i_player != "instance") return null;
  68.         // Store the player instance
  69.         else Instance = i_player
  70.     }
  71.     // --------------------------------------------------------------------------------------------
  72.     function Connect()
  73.     {
  74.         // Ignored....
  75.     }
  76.     // --------------------------------------------------------------------------------------------
  77.     function Disconnect(reason)
  78.     {
  79.         // See if the player had any partner
  80.         if (Partner != null) {
  81.             // Notify the partner about the split-up
  82.             _Msg.Player(Partner, @"%s %s has disconnected and you no longer have a partner.", MsgTag.Inf, Instance.Name);
  83.             // Free the partner from used
  84.             _ClientPool[Partner.ID].Partner = null;
  85.             // Clear any stored instances
  86.             Partner = null;
  87.         }
  88.         // See if there's any requests made by this instance and clear them
  89.         if (_TeamupPool[Instance.ID] != null) {
  90.             // Notify the partner about the result
  91.             _Msg.Player(_TeamupPool[Instance.ID].Target, @"%s %s has disconnected and his team-up request was flushed.", MsgTag.Inf, Instance.Name);
  92.             // Remove the request from the pool/list
  93.             _TeamupPool[Instance.ID] = null;
  94.         }
  95.         // See if there's any requests made to this instance and clear them
  96.         foreach (idx, req in _TeamupPool) {
  97.             // See if this is a valid request
  98.             if (req != null && req.Target.ID == Instance.ID) {
  99.                 // Notify the partner about the rejected request
  100.                 _Msg.Player(req.Invoker, @"%s %s has disconnected and cannot accept team-up request.", MsgTag.Inf, i_player.Name);
  101.                 // Clear the request from the pool/list
  102.                 _TeamupPool[idx] = null;
  103.             }
  104.         }
  105.         // Clear any stored instances
  106.         Instance = null;
  107.     }
  108.     // --------------------------------------------------------------------------------------------
  109.     Instance = null
  110.     // --------------------------------------------------------------------------------------------
  111.     Partner = null
  112.     // --------------------------------------------------------------------------------------------
  113.     PlaySolo = false
  114. }
  115.  
  116. // ------------------------------------------------------------------------------------------------
  117. // Processes all the active team-up requests
  118. function _TeamupProcess()
  119. {
  120.     // Get the current time
  121.     local cur_time = time();
  122.     // Loop through all the queued requests
  123.     foreach (idx, req in _TeamupPool) {
  124.         // See if this is a valid request
  125.         if (req != null && req.Timeout <= cur_time) {
  126.             // Notify the invoker about the expired request
  127.             _Msg.Player(req.Invoker, @"%s Your team-up request to %s has expired.", MsgTag.Inf, req.Target.Name);
  128.             // Clear the request from the pool/list
  129.             _TeamupPool[idx] = null;
  130.         }
  131.     }
  132. }
  133.  
  134. // ------------------------------------------------------------------------------------------------
  135. _CMD.TeamUp <- function(i_player, args)
  136. {
  137.     // See if there isn't already a request in the pool and send a notice to the invoker to flush his previous request
  138.     if (_TeamupPool[i_player.ID] != null) return _Msg.Player(i_player, @"%s Please flush your previous request to:  %s", MsgTag.Scs, _TeamupPool[i_player.ID].Target.Name);
  139.  
  140.     // See if we are dealing with a valid command
  141.     if (typeof args != "string" || args.len() <= 0) return _Msg.Player(i_player, @"%s Syntax: %s", MsgTag.Inf, CmdSyn.TeamUp);
  142.     // Strip the command from unnecessary space characters
  143.     args = strip(args);
  144.    
  145.     // Check one more time if we still have a valid command
  146.     if (typeof args != "string" || args.len() <= 0) return _Msg.Player(i_player, @"%s Syntax: %s", MsgTag.Inf, CmdSyn.TeamUp);
  147.     // Try to find the target instance by name first
  148.     local i_partner = FindPlayer(args);
  149.    
  150.     // See if we found a valid player instance for our partner
  151.     if (typeof i_partner != "instance") return _Msg.Player(i_player, @"%s There's no player on the server identified by: %s", MsgTag.Err, args);
  152.     // See if the invoker tries to team up with him self
  153.     else if (i_player.ID == i_partner.ID) return _Msg.Player(i_player, @"%s You cannot team up with your self.", MsgTag.Wrn);
  154.     // See if the invoker has the option to play solo enabled
  155.     else if (_ClientPool[i_player.ID].PlaySolo) return _Msg.Player(i_player, @"%s You already chose to play solo.", MsgTag.Wrn);
  156.     // See if the partner has the option to play solo enabled
  157.     else if (_ClientPool[i_partner.ID].PlaySolo) return _Msg.Player(i_player, @"%s %s chose to play solo.", MsgTag.Wrn, i_partner.Name);
  158.     // See if the invoker is already in a team
  159.     else if (_ClientPool[i_player.ID].Partner != null) return _Msg.Player(i_player, @"%s You are already teamed-up with: %s", MsgTag.Wrn, _ClientPool[i_player.ID].Partner.Name);
  160.     // See if the requested partner is already in a team
  161.     else if (_ClientPool[i_partner.ID].Partner != null) return _Msg.Player(i_player, @"%s %s is already teamed-up with: %s", MsgTag.Wrn, i_partner.Name, _ClientPool[i_partner.ID].Partner.Name);
  162.    
  163.     // Submit the request to the pool
  164.     _TeamupPool[i_player.ID] = {Invoker = i_player, Target = i_partner, Timeout = (time()+30)};
  165.     // Notify the requested partner
  166.     _Msg.Player(i_partner, @"%s %s would like to team-up with you.", MsgTag.Inf, i_player.Name);
  167.     // Notify the invoker about his request
  168.     _Msg.Player(i_player, @"%s %s successfully received your team-up request.", MsgTag.Scs, i_partner.Name);
  169. }
  170.  
  171. // ------------------------------------------------------------------------------------------------
  172. _CMD.SplitUp <- function(i_player, args)
  173. {
  174.     // See if the invoker is in a team
  175.     if (_ClientPool[i_player.ID].Partner != null) {
  176.         // Inform the invoker about his action
  177.         _Msg.Player(i_player, @"%s You split-up from: %s", MsgTag.Scs, _ClientPool[i_player.ID].Partner.Name);
  178.         // Send a notice to the partner
  179.         _Msg.Player(_ClientPool[i_player.ID].Partner, @"%s %s split-up from you and you no longer have a partner.", MsgTag.Inf, i_player.Name);
  180.         // Remove the link from the partner
  181.         _ClientPool[_ClientPool[i_player.ID].Partner.ID].Partner = null;
  182.         // Remove the link from the invoker
  183.         _ClientPool[i_player.ID].Partner = null;
  184.     // Notify the invoker that he doesn't have a team to split-up
  185.     } else _Msg.Player(i_player, @"%s You don't have a team to split-up.", MsgTag.Wrn);
  186. }
  187.  
  188. // ------------------------------------------------------------------------------------------------
  189. _CMD.DenyReq <- function(i_player, args)
  190. {
  191.     // See if we are dealing with a valid command
  192.     if (typeof args != "string" || args.len() <= 0) return _Msg.Player(i_player, @"%s Syntax: %s", MsgTag.Inf, CmdSyn.DenyReq);
  193.     // Strip the command from unnecessary space characters
  194.     args = strip(args);
  195.    
  196.     // Check one more time if we still have a valid command
  197.     if (typeof args != "string" || args.len() <= 0) return _Msg.Player(i_player, @"%s Syntax: %s", MsgTag.Inf, CmdSyn.DenyReq);
  198.     // Try to find the target instance by name first
  199.     local i_partner = FindPlayer(args);
  200.    
  201.     // See if we found a valid player instance for our partner
  202.     if (typeof i_partner != "instance") return _Msg.Player(i_player, @"%s There's no player on the server identified by: %s", MsgTag.Err, args);
  203.    
  204.     // Notify the partner about the rejected request
  205.     _Msg.Player(i_partner, @"%s %s rejected your team-up request.", MsgTag.Inf, i_player.Name);
  206.     // Notify the invoker about the rejected request
  207.     _Msg.Player(i_player, @"%s You successfully rejected the team-up request from %s", MsgTag.Scs, i_partner.Name);
  208.     // Flush the request from the pool/list
  209.     _TeamupPool[i_partner.ID] = null;
  210. }
  211.  
  212. // ------------------------------------------------------------------------------------------------
  213. _CMD.DenyAll <- function(i_player, args)
  214. {
  215.     // Go through each element in the request pool and clear it if it's addressed to the invoker
  216.     foreach (idx, req in _TeamupPool) {
  217.         // See if this is a valid request
  218.         if (req != null && req.Target.ID == i_player.ID) {
  219.             // Notify the partner about the rejected request
  220.             _Msg.Player(req.Invoker, @"%s %s rejected your team-up request.", MsgTag.Inf, i_player.Name);
  221.             // Notify the invoker about the rejected request
  222.             _Msg.Player(i_player, @"%s You successfully rejected the team-up request from %s", MsgTag.Scs, req.Invoker.Name);
  223.             // Clear the request from the pool/list
  224.             _TeamupPool[idx] = null;
  225.         }
  226.     }
  227. }
  228.  
  229. // ------------------------------------------------------------------------------------------------
  230. _CMD.AcceptReq <- function(i_player, args)
  231. {
  232.     // See if we are dealing with a valid command
  233.     if (typeof args != "string" || args.len() <= 0) return _Msg.Player(i_player, @"%s Syntax: %s", MsgTag.Inf, CmdSyn.AcceptReq);
  234.     // Strip the command from unnecessary space characters
  235.     args = strip(args);
  236.    
  237.     // Check one more time if we still have a valid command
  238.     if (typeof args != "string" || args.len() <= 0) return _Msg.Player(i_player, @"%s Syntax: %s", MsgTag.Inf, CmdSyn.AcceptReq);
  239.     // Try to find the target instance by name first
  240.     local i_partner = FindPlayer(args);
  241.    
  242.     // See if we found a valid player instance for our partner
  243.     if (typeof i_partner != "instance") return _Msg.Player(i_player, @"%s There's no player on the server identified by: %s", MsgTag.Err, args);
  244.    
  245.     // Notify the invoker about the result
  246.     _Msg.Player(i_partner, @"%s %s accepted your team up request.", MsgTag.Inf, i_player.Name);
  247.     // Notify the partner about the result
  248.     _Msg.Player(i_player, @"%s You accepted the team up request from %s", MsgTag.Scs, i_partner.Name);
  249.     // Remove this request from the pool/list
  250.     _TeamupPool[i_partner.ID] = null;
  251.     // Link the players together
  252.     _ClientPool[i_player.ID].Partner = i_partner;
  253.     _ClientPool[i_partner.ID].Partner = i_player;
  254.    
  255.     // A variable to count the rest of the requests
  256.     local req_count = 0;
  257.     // Go through each element in the request pool and clear it if it's addressed to the invoker
  258.     foreach (idx, req in _TeamupPool) {
  259.         // See if this is a valid request
  260.         if (req != null && req.Target.ID == i_player.ID) {
  261.             // Notify the partner about the rejected request
  262.             _Msg.Player(req.Invoker, @"%s %s rejected your team-up request.", MsgTag.Inf, i_player.Name);
  263.             // Increase the request counter
  264.             req_count++;
  265.             // Clear the request from the pool/list
  266.             _TeamupPool[idx] = null;
  267.         }
  268.     }
  269.     // Notify the invoker about the rest of the requests
  270.     _Msg.Player(i_player, @"%s You successfully rejected the rest of the requests (%d).", MsgTag.Inf, req_count);
  271. }
  272.  
  273. // ------------------------------------------------------------------------------------------------
  274. _CMD.AcceptAny <- function(i_player, args)
  275. {
  276.     // An array to hold the indexes of the available requests
  277.     local requests = array(0);
  278.     // Find all the requests made to the invoker
  279.     foreach (idx, req in _TeamupPool) {
  280.         // See if this is a valid request
  281.         if (req != null && req.Target.ID == i_player.ID) {
  282.             // Add the request index to the list
  283.             requests.push(idx);
  284.         }
  285.     }
  286.     // See if we have any requests made to this player
  287.     if (requests.len() <= 0) return _Msg.Player(i_player, @"%s, You don't have any team-up requests.", MsgTag.Inf);
  288.     // See if we have only one request
  289.     else if (requests.len() == 1) return _CMD.AcceptReq(i_player, _TeamupPool[requests[0]].Invoker.Name);
  290.     // Set the seed for the random number generator
  291.     srand(time());
  292.     // Make the seed even more random for small ranges
  293.     srand(time() % ((time() / rand()) % rand()));
  294.     // Get a random index from the list
  295.     local rnum = rand() % requests.len();
  296.     // Accept the request of the partner located at the generated index
  297.     _CMD.AcceptReq(i_player, _TeamupPool[requests[rnum]].Invoker.Name);
  298. }
  299.  
  300. // ------------------------------------------------------------------------------------------------
  301. _CMD.FlushReq <- function(i_player, args)
  302. {
  303.     // See if there's a request in the pool/list
  304.     if (_TeamupPool[i_player.ID] != null) {
  305.         // Inform the invoker about his action
  306.         _Msg.Player(i_player, @"%s You revoked your team-up request to:  %s", MsgTag.Scs, _TeamupPool[i_player.ID].Target.Name);
  307.         // Send a notice to the target
  308.         _Msg.Player(_TeamupPool[i_player.ID].Target, @"%s %s revoked his team-up request.", MsgTag.Inf, i_player.Name);
  309.         // Flush the request
  310.         _TeamupPool[i_player.ID] = null;
  311.     // Notify the invoker that there is no previous request
  312.     } else _Msg.Player(i_player, @"%s You don't have any team-up request.", MsgTag.Wrn);
  313. }
  314.  
  315. // ------------------------------------------------------------------------------------------------
  316. _CMD.PlaySolo <- function(i_player, args)
  317. {
  318.     // See if the invoker isn't in a team already
  319.     if (_ClientPool[i_player.ID].Partner != null) return _Msg.Player(i_player, @"%s You need to split-up from %x", MsgTag.Wrn, _ClientPool[i_player.ID].Partner.Name);
  320.     // See if the invoker has this option enabled or not
  321.     if (_ClientPool[i_player.ID].PlaySolo) {
  322.         // Deactivate the play solo option
  323.         _ClientPool[i_player.ID].PlaySolo = false;
  324.         // Notify the invoker about his action
  325.         _Msg.Player(i_player, @"%s You successfully deactivated the play solo option.", MsgTag.Scs);
  326.     } else {
  327.         // Activate the play solo option
  328.         _ClientPool[i_player.ID].PlaySolo = true;
  329.         // Notify the invoker about his action
  330.         _Msg.Player(i_player, @"%s You successfully activated the play solo option.", MsgTag.Scs);
  331.     }
  332. }
  333.  
  334. // ------------------------------------------------------------------------------------------------
  335. _CMD.Partner <- function(i_player, args)
  336. {
  337.     // See if the invoker has a partner or not
  338.     if (_ClientPool[i_player.ID].Partner != null) {
  339.         // Inform the invoker about his partner
  340.         _Msg.Player(i_player, @"%s Your partner is %s", MsgTag.Inf, _ClientPool[i_player.ID].Partner.Name);
  341.     // Notify the invoker that he doesn't have a partner
  342.     } else _Msg.Player(i_player, @"%s You don't have a partner.", MsgTag.Wrn);
  343. }
  344.  
  345. // ------------------------------------------------------------------------------------------------
  346. function onServerStart()
  347. {
  348.     // Reserve enough space to hold the maximum number of Clients that the server can hold
  349.     _ClientPool = array(GetMaxPlayers());
  350.     _TeamupPool = array(GetMaxPlayers());
  351.     // Attempt to find any previously connected Clients in case of a script reload
  352.     foreach (idx, inst in _ClientPool) {
  353.         // Attempt to find the player by it's unique identifier
  354.         local res = FindPlayer(idx);
  355.         // See if a valid player instance was found at this ID
  356.         if (res != null) {
  357.             // Create a Client instance for this player instance
  358.             inst = _Client(res);
  359.             // Allow the Client instance to initialize
  360.             inst.Connect();
  361.         }
  362.     }
  363.     // Start the teamup request cleaning timer
  364.     NewTimer("_TeamupProcess", 5000, 0);
  365. }
  366.  
  367. // ------------------------------------------------------------------------------------------------
  368. function onServerStop()
  369. {
  370.     // Attempt to de-initialize all connected players from the server
  371.     foreach (inst in _ClientPool) {
  372.         // See if there was any Client instance in this slot
  373.         if (inst != null) {
  374.             // Allow the Client instance to de-initialize
  375.             inst.Disconnect();
  376.             // Clear the slot
  377.             _ClientPool[i_player.ID] = null;
  378.         }
  379.     }
  380.     // Clear all the team-up requests
  381.     foreach (idx, req in _TeamupPool) _TeamupPool[idx] = null;
  382. }
  383.  
  384. // ------------------------------------------------------------------------------------------------
  385. function onPlayerJoin(i_player)
  386. {
  387.     // Create a Client instance for this player instance
  388.     _ClientPool[i_player.ID] = _Client(i_player);
  389.     // Allow the newly created Client instance to initialize
  390.     _ClientPool[i_player.ID].Connect();
  391. }
  392.  
  393. // ------------------------------------------------------------------------------------------------
  394. function onPlayerPart(i_player, reason)
  395. {
  396.     // Allow the Client instance to de-initialize
  397.     _ClientPool[i_player.ID].Disconnect(reason);
  398.     // Clear the slot for other Clients
  399.     _ClientPool[i_player.ID] = null;
  400. }
  401.  
  402. // ------------------------------------------------------------------------------------------------
  403. function onPlayerSpawn(i_player)
  404. {
  405.     // See if the player has a partner
  406.     if (_ClientPool[i_player.ID].Partner != null) {
  407.         // Teleport the player to his partner
  408.         i_player.Pos = _ClientPool[i_player.ID].Partner.Pos;
  409.     }
  410. }
  411.  
  412. // ------------------------------------------------------------------------------------------------
  413. function onPlayerCommand(i_player, cmd, args)
  414. {
  415.     switch (cmd)
  416.     {
  417.         // ----------------------------------------------------------------------------------------
  418.         case "teamup":      _CMD.TeamUp(i_player, args); break;
  419.         case "splitup":     _CMD.SplitUp(i_player, args); break;
  420.         // ----------------------------------------------------------------------------------------
  421.         case "denyreq":     _CMD.DenyReq(i_player, args); break;
  422.         case "denyall":     _CMD.DenyAll(i_player, args); break;
  423.         // ----------------------------------------------------------------------------------------
  424.         case "acceptreq":   _CMD.AcceptReq(i_player, args); break;
  425.         case "acceptany":   _CMD.AcceptAny(i_player, args); break;
  426.         // ----------------------------------------------------------------------------------------
  427.         case "flushreq":    _CMD.FlushReq(i_player, args); break;
  428.         case "playsolo":    _CMD.PlaySolo(i_player, args); break;
  429.         case "partner":     _CMD.Partner(i_player, args); break;
  430.         // ----------------------------------------------------------------------------------------
  431.         default: _Msg.Player(i_player, @"%s Unknown command: %s %s", MsgTag.Err, cmd, typeof args == "string" ? args : "");
  432.     }
  433. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement