Advertisement
Guest User

Untitled

a guest
Jun 29th, 2016
156
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 173.05 KB | None | 0 0
  1. // -------------------------------------- //
  2. // EVIDENCE by domino54 //
  3. // script version: 2.0 @2016-06-29 //
  4. // -------------------------------------- //
  5.  
  6. /**
  7. * INSTALLATION GUIDE
  8. * 1. Rename file to "Chat.Script.txt".
  9. * 2. Place this file in folder: "(user data directory)/Media/Manialinks/Common/Chat/Chat.Script.txt".
  10. * 3. Restart game to apply changes.
  11. */
  12.  
  13. #RequireContext CManiaplanetPlugin
  14.  
  15. #Const ScriptName "Evidence.Script.txt"
  16. #Const ScriptVersion "2016-06-29"
  17. #Const ScriptVersionNb "2.0"
  18.  
  19. #Include "MathLib" as ML
  20. #Include "TextLib" as TL
  21. #Include "Libs/Nadeo/Manialink.Script.txt" as Manialink
  22.  
  23. /*
  24.  
  25. CHANGELOG
  26.  
  27. Additions:
  28. + Evidence Global Chat: text with everyone using Evidence in a single group.
  29. + Dynamic status: option to set dynamic status depending on what you're currently doing.
  30. + Heavy design tweaks.
  31. + Buddy Invitations tab with list of all buddy requests and option to invite players.
  32. + Settings tab with various options of the chat plugin.
  33. + Group Chat can be now secured with password defined in settings tab.
  34. + Some extra Group Chat formatted messages commands.
  35. + Notifications about incoming updates.
  36.  
  37. Tweaks:
  38. ~ Extremely optimized plugin code.
  39. ~ Buttons on the buddies cards are now displayed only when chat is in corresponding mode.
  40. ~ Commands sent to other buddies now won't be shown.
  41. ~ Command used to leave group is now called "quit", instead "leave".
  42. ~ Group Chat will now find names from logins with even less than 4 specified characters.
  43.  
  44. Removed features:
  45. - Server mode and players amount is no longer available to check.
  46. - Server name is no longer visible in Group Chat mode.
  47. */
  48.  
  49. // ---------------------------------- //
  50. // Constants
  51. // ---------------------------------- //
  52. #Const C_ImgBase "file://Media/Manialinks/Common/Chat/"
  53.  
  54. /// Available statuses depending on user presence Id
  55. #Const C_UserPresenceStatus [_("Offline"), _("Available"), _("Away"), _("Busy"), _("Available"), _("Away")]
  56.  
  57. /// Words to avoid in context status
  58. #Const C_ContextAvoidInTitle ["TrackMania ", "ShootMania "]
  59.  
  60. /// Prosences on which context status will be applied
  61. #Const C_ContextStatusPresences [1, 3]
  62.  
  63. /// Available statuses depending on active context
  64. #Const C_ContextStatusText [
  65. ::EContext::MenuManiaPlanet => _("In ManiaPlanet main menu"),
  66. ::EContext::MenuManiaTitleMain => _("In $<%1$> main menu"),
  67. ::EContext::MenuCustom => _("In $<%1$> custom menu"),
  68. ::EContext::MenuSolo => _("In $<%1$> solo menu"),
  69. ::EContext::MenuLocal => _("In $<%1$> multiplayer menu"),
  70. ::EContext::MenuEditors => _("In $<%1$> editors menu"),
  71. ::EContext::MenuProfile => _("In $<%1$> profile menu"),
  72. ::EContext::Solo => _("Playing $<%1$> solo"),
  73. ::EContext::Multi => _("Playing $<%1$> multiplayer"),
  74. ::EContext::EditorTrack => _("Editing a map in $<%1$>"),
  75. ::EContext::EditorPainter => _("Painting a car in $<%1$>"),
  76. ::EContext::EditorMediaTracker => _("Editing a replay in $<%1$>")
  77. ]
  78.  
  79. // ---------------------------------- //
  80. // Group Chat settings
  81. // ---------------------------------- //
  82. #Const C_GroupOfflineRemovalDelay 5000 ///< Delay before removing offline buddies upon chat startup
  83.  
  84. /// Group Chat messages format
  85. #Const C_GroupFormatMessage "$FF0"
  86. #Const C_GroupFormatSuccess "$0F0"
  87. #Const C_GroupFormatInfo "$6BF"
  88. #Const C_GroupFormatPrivate "$F80"
  89. #Const C_GroupFormatError "$F00Error: "
  90.  
  91. /// Required permissions level to perform a command
  92. #Const C_GroupCommandPermissionsLevels [
  93. "kick" => 1, "mute" => 1, "unmute" => 1, "ban" => 1, "unban" => 1, "addop" => 2, "removeop" => 2
  94. ]
  95.  
  96. /// Group Chat formatted messages
  97. #Const C_ChatMessageCommands [
  98. "hi" => "Hello", "bb" => "Bye", "re" => "Returned", "wb" => "Welcome back",
  99. "afk" => "Away from keyboard", "gtg" => "Got to go", "brb" => "Be right back",
  100. "gg" => "Good game", "gga" => "Good game all", "gj" => "Good job",
  101. "n1" => "Nice one", "ns" => "Nice shoot", "nt" => "Nice time", "ty" => "Thank you",
  102. "gl" => "Good luck", "hf" => "Have fun", "glhf" => "Goold luck and have fun",
  103. "wp" => "Well played", "ggwp" => "Good game, well played",
  104. "gr8" => "Great", "w8" => "Wait", "lol" => "Loo0ool", "lool" => "Looo00oool",
  105. "54" => "I <3 Domino", "gu" => "Guerried", "grt" => "Guerritos",
  106. "flo" => "Florenziusted", "nu" => "Nurpsen", "owz" => "Owzom", "wow" => "WOOW"
  107. ]
  108.  
  109. /// Group Chat formatted messages, that can be used with login
  110. #Const C_ChatMessageWithLogin [
  111. "hi", "bb", "wb", "flo", "gg", "gj", "n1", "ns", "nt", "ty", "lol", "lool",
  112. "gl", "hf", "glhf", "wp", "ggwp", "gu", "gr8", "w8", "owz", "wow"
  113. ]
  114.  
  115. // ---------------------------------- //
  116. /** Commands help description
  117. * [required parameter] <optional parameter>
  118. */
  119. #Const C_GroupCommandsHelp [
  120. "help" => "You seem to be really desperate.",
  121. "join" => "/join - Join the Group Chat server.",
  122. "quit" => "/quit - Leave the Group Chat server.",
  123. "list" => "/list <op|mute|ban|nf|logins> - Display list with logins of specified users on the server.",
  124. "me" => "/me [message] - Describe what are you currently doing.",
  125. "kick" => "/kick [login] - Disconnect specified user from the server.",
  126. "mute" => "/mute [login] - Mute specified user. Messages of muted users aren't shown.",
  127. "unmute" => "/unmute [login] - Remove mute penalty from specified user.",
  128. "ban" => "/ban [login] - Ban specified user from the Group Chat.",
  129. "unban" => "/unmute [login] - Remove ban penalty from specified user.",
  130. "addop" => "/addop [login] - Give specified user operator rights.",
  131. "removeop" => "/removeop [login] - Remove operator rights from specified user.",
  132. "noformat" => "/noformat <0|1> - Remove formatting from nicknames to save messages length.",
  133. "pm" => "/pm [login] [message] - Send private message to a specified user.",
  134. "pmr" => "/pmr [message] - Reply to the latest received private message.",
  135. "core" => "/core - Returns name and version of the Group Chat script file.",
  136. "rq" => "/rq - Leave the Group Chat server. With anger.",
  137. "bm" => "/bm - Kick yourself from the Group Chat, if you really want.",
  138. "/chatmsg" => "<login> - Shortcut displaying formatted message in chat."
  139. ]
  140.  
  141. // ---------------------------------- //
  142. // Global Chat settings
  143. // ---------------------------------- //
  144. #Const C_GlobalChatServerURL "http://2.3.49.155/JavaWeb/"
  145. #Const C_GlobalChatServerMethods ["GET_UID", "GET_USER_LIST", "GET_MSG", "REFRESH", "SET_STATUS", "SEND_MSG"]
  146. #Const C_GlobalChatGetUIDTimeout 10000
  147. #Const C_GlobalChatRequestInterval [
  148. "GET_UID" => 2000,
  149. "GET_USER_LIST" => 7500,
  150. "GET_MSG" => 1000,
  151. "REFRESH" => 5000,
  152. "SET_STATUS" => 7500
  153. ]
  154.  
  155. // ---------------------------------- //
  156. // Global variables
  157. // ---------------------------------- //
  158. declare Integer[] G_GlobalChat_ReceivedMessages; ///< Messages Ids received in Global Chat mode
  159. declare Boolean G_GlobalChat_ConnectionError; ///< True, if local user is not present in users list
  160.  
  161. // ---------------------------------- //
  162. // Main
  163. // ---------------------------------- //
  164. ***Main***
  165. ***
  166. // ---------------------------------- //
  167. // Connect to the ManiaPlanet Chat server
  168. BuddiesManager.DesiredConnectionStatus = CBuddiesManager::EDesiredConnectionStatus::Offline;
  169. wait(BuddiesManager.CurrentConnectionStatus == CBuddiesManager::EConnectionStatus::Offline);
  170.  
  171. BuddiesManager.DesiredConnectionStatus = CBuddiesManager::EDesiredConnectionStatus::Online;
  172. wait(BuddiesManager.CurrentConnectionStatus == CBuddiesManager::EConnectionStatus::Online);
  173.  
  174. // ---------------------------------- //
  175. // Layer of the plugin icon
  176. declare IconLayer <=> UILayerCreate();
  177. IconLayer.AttachId = "IconLayer";
  178. IconLayer.ManialinkPage = CreateManialinkPluginIcon();
  179. IconLayer.Type = CUILayer::EUILayerType::ManiaplanetPlugin;
  180. declare IconPage <=> IconLayer.LocalPage;
  181.  
  182. // ---------------------------------- //
  183. // Layer of the Evidence window
  184. declare WindowLayer <=> UILayerCreate();
  185. WindowLayer.AttachId = "WindowLayer";
  186. WindowLayer.ManialinkPage = CreateManialinkWindow();
  187. WindowLayer.Type = CUILayer::EUILayerType::Normal;
  188. declare WindowPage <=> WindowLayer.LocalPage;
  189.  
  190. // ---------------------------------- //
  191. // Layer of the dialog box
  192. declare DialogLayer <=> UILayerCreate();
  193. DialogLayer.AttachId = "DialogBox";
  194. DialogLayer.ManialinkPage = CreateManialinkDialogBox();
  195. DialogLayer.Type = CUILayer::EUILayerType::Normal;
  196. declare DialogPage <=> DialogLayer.LocalPage;
  197.  
  198. // ---------------------------------- //
  199. // Layer of the notices
  200. declare NoticesLayer <=> UILayerCreate();
  201. NoticesLayer.AttachId = "Notices";
  202. NoticesLayer.ManialinkPage = CreateManialinkNotifications();
  203. NoticesLayer.Type = CUILayer::EUILayerType::Normal;
  204. declare NoticesPage <=> NoticesLayer.LocalPage;
  205.  
  206. // ---------------------------------- //
  207. // Persistent settings
  208. declare persistent Text[] Persistent_Evidence_BuddiesInGroup;
  209. declare persistent Text[] Persistent_Evidence_MutedGroupBuddies;
  210.  
  211. // ---------------------------------- //
  212. // Manialink script communication
  213. declare NewReceivedMessages for WindowPage = Text[][]; ///< New messages to proceed
  214. declare ChatWidgetIsOpen for WindowPage = False; ///< Current chat state
  215. declare CurrentWidgetMode for WindowPage = ""; ///< Active widget mode
  216. declare SelectedConversation for WindowPage = ""; ///< Login of selected buddy for private conversation
  217. declare LegacyMailsAmount for WindowPage = 0; ///< Amount of messages in classic mailbox
  218. declare CurrentPluginPresenceId for WindowPage = 4; ///< Current presence Id of the user
  219. declare CurrentPluginStatusText for WindowPage = ""; ///< Currently displayed status of the user
  220. declare ManialinkTargetPresence for WindowPage = 4; ///< Requested user presence Id
  221. declare ManialinkCustomStatus for WindowPage = ""; ///< Custom status specified by user
  222. declare TotalNbUnreadMessages for WindowPage = 0; ///< Total amount of unread messages
  223. declare FlashTaskbar for WindowPage = False; ///< Force game to blink taskbar icon
  224. declare UseDynamicStatus for WindowPage = False; ///< User context status setting
  225. declare NoticeOnConnection for WindowPage = False; ///< Send notice on new connection
  226. declare UsersThatSeenMessage for WindowPage = Text[]; ///< Users that just seen message
  227.  
  228. declare PluginNbUsersOnline for IconPage = 0; ///< Amount of buddies online
  229. declare PluginNbUnreadMessages for IconPage = 0; ///< Amount of unread messages from buddies and group
  230. declare PluginIsChatWindowOpen for IconPage = False; ///< Current chat visibility status
  231. declare PluginTriggerOpenChat for IconPage = False; ///< Trigger chat visibility
  232.  
  233. declare PrevManialinkTargetPresence = 4;
  234. declare PrevManialinkCustomStatus = "";
  235. declare PrevUseDynamicStatus = False;
  236. declare PrevNbBuddiesInGroup = -1;
  237.  
  238. // ---------------------------------- //
  239. // Plugin buddies data
  240. declare Text[] BuddiesList_Online for WindowPage; ///< Buddies currently being connected
  241. declare Text[] BuddiesList_Offline for WindowPage; ///< Buddies currently being offline
  242. declare Text[] BuddiesList_RequestFrom for WindowPage; ///< Incoming buddies invitations
  243. declare Text[] BuddiesList_RequestTo for WindowPage; ///< Sent buddies invitations
  244. declare Text[] BuddiesList_OnServer for WindowPage; ///< Players on current server
  245. declare Text[] BuddiesList_InGroup for WindowPage; ///< Buddies in the group
  246. declare Text[] BuddiesList_GlobalList for WindowPage; ///< Buddies available on the global chat
  247. declare Text[] BuddiesList_MutedUsers for WindowPage; ///< Buddies muted from the group
  248. declare Text[] BuddiesList_Evidence for WindowPage; ///< Buddies using Evidence chat
  249.  
  250. declare Text[Text] BuddiesName for WindowPage; ///< Names of the buddies
  251. declare Integer[Text] BuddiesPresenceId for WindowPage; ///< Presence Ids of the buddies
  252. declare Text[Text] BuddiesStatus for WindowPage; ///< Statuses of the buddies
  253. declare Text[Text] BuddiesServerLogin for WindowPage; ///< Login of the servers buddies are on
  254. declare Boolean[Text] BuddiesIsMuted for WindowPage; ///< True if buddy is muted in Group Chat
  255. declare Text[Text] BuddiesJoinLink for WindowPage; ///< Links to join buddies servers
  256.  
  257. declare Text[Text] ServersName for WindowPage; ///< Names of the buddies servers
  258.  
  259. /// Update variables
  260. declare PrevNbBuddiesOffline = 0;
  261. declare PrevNbBuddiesRequestFrom = 0;
  262. declare PrevNbBuddiesRequestTo = 0;
  263. declare PrevNbBuddiesOnServer = 0;
  264. declare PrevNbBuddiesMuted = 0;
  265.  
  266. // ---------------------------------- //
  267. // Dialog box layer data
  268. declare DialogVisible for DialogPage = False; ///< Visibility of the dialog box
  269. declare DialogBuddyLogin for DialogPage = ""; ///< Login of the buddy to remove
  270. declare DialogBuddyName for DialogPage = ""; ///< Name of the buddy to remove
  271.  
  272. // ---------------------------------- //
  273. // Notifications
  274. declare Text[][] NewNotifications for NoticesPage; ///< New notifications to display
  275. declare Boolean ToolbarActive for NoticesPage; ///< ManiaPlanet toolbar visibility
  276.  
  277. // ---------------------------------- //
  278. // Variables
  279. declare StartTime = Now;
  280. declare SET_STATUS = True;
  281. declare Text ContextAutoStatus;
  282.  
  283. /// Update variables
  284. declare PrevUserServerLogin = "";
  285. declare PrevUserServerName = "";
  286. declare PrevOutgoingBuddyNames = Text[Text];
  287. declare ::EContext PrevActiveContext;
  288. ***
  289.  
  290. // ---------------------------------- //
  291. // Yield
  292. // ---------------------------------- //
  293. ***Yield***
  294. ***
  295. // ---------------------------------- //
  296. // Buddies manager events management
  297. foreach (Event in BuddiesManager.PendingEvents) {
  298. // ---------------------------------- //
  299. // User received a new message
  300. if (Event.Type == CBuddiesEvent::EType::Message && Event.MessageBody != "") {
  301. // ---------------------------------- //
  302. // Normal message
  303. if (Event.MessageType != "data") {
  304. declare EventIsCommand = (TL::SubString(Event.MessageBody, 0, 1) == "/");
  305. // ---------------------------------- //
  306. // New message
  307. if (!EventIsCommand) {
  308. // ---------------------------------- //
  309. // Display and notify user about new message
  310. if (!Persistent_Evidence_BuddiesInGroup.exists(Event.Sender.Login))
  311. NewReceivedMessages.add([Event.Sender.Login, Event.Sender.Login, Event.MessageBody]);
  312.  
  313. // ---------------------------------- //
  314. // Send message to all other buddies in the group
  315. else if (!Persistent_Evidence_MutedGroupBuddies.exists(Event.Sender.Login))
  316. SendMessageToGroup(Event.Sender.Login, Event.MessageBody);
  317.  
  318. // ---------------------------------- //
  319. // Buddy is muted in the group
  320. else BuddiesManager.SendMessage(Event.Sender, "", C_GroupFormatError^"You're muted in this group!");
  321. }
  322. // ---------------------------------- //
  323. // New command
  324. else if (TL::Length(Event.MessageBody) > 1) PerformChatCommand(Event.Sender.Login, Event.MessageBody);
  325.  
  326. // ---------------------------------- //
  327. // Add Evidence user
  328. if (Event.MessageType == "Evidence" && !BuddiesList_Evidence.exists(Event.Sender.Login))
  329. BuddiesList_Evidence.add(Event.Sender.Login);
  330. }
  331. // ---------------------------------- //
  332. // Custom data protocol
  333. else {
  334. // ---------------------------------- //
  335. // Buddy confirmed reading the message
  336. if (Event.MessageBody == "seenmessage") {
  337. if (!UsersThatSeenMessage.exists(Event.Sender.Login)) UsersThatSeenMessage.add(Event.Sender.Login);
  338. }
  339. }
  340. }
  341. // ---------------------------------- //
  342. // Buddy changed his presence
  343. else if (Event.Type == CBuddiesEvent::EType::PresenceChange) {
  344. BuddiesPresenceId[Event.Buddy.Login] = GetPresenceId(Event.Buddy.PresenceShow);
  345.  
  346. // Update name
  347. BuddiesName[Event.Buddy.Login] = Event.Buddy.Name;
  348.  
  349. // Update status
  350. declare BuddyStatus = Event.Buddy.PresenceStatus;
  351. if (BuddyStatus == "") BuddyStatus = C_UserPresenceStatus[GetPresenceId(Event.Buddy.PresenceShow)];
  352. BuddiesStatus[Event.Buddy.Login] = BuddyStatus;
  353.  
  354. if (
  355. (BuddiesPresenceId[Event.Buddy.Login] == 4 || BuddiesPresenceId[Event.Buddy.Login] == 5) &&
  356. !BuddiesList_Evidence.exists(Event.Buddy.Login)
  357. )
  358. BuddiesList_Evidence.add(Event.Buddy.Login);
  359.  
  360. // Update buddy server login
  361. BuddiesServerLogin[Event.Buddy.Login] = Event.Buddy.CurrentServerLogin;
  362.  
  363. // Update buddy join link
  364. BuddiesJoinLink[Event.Buddy.Login] = "";
  365. if (Event.Buddy.CurrentServerJoinLink != "")
  366. BuddiesJoinLink[Event.Buddy.Login] = TL::Replace(Event.Buddy.CurrentServerJoinLink, "maniaplanet://", "");
  367.  
  368. // Update server information
  369. if (Event.Buddy.CurrentServerLogin != "")
  370. ServersName[Event.Buddy.CurrentServerLogin] = Event.Buddy.CurrentServerName;
  371.  
  372. // Connection notification
  373. if (NoticeOnConnection && !Event.PreviousIsOnline && Event.Buddy.IsOnline && Now > StartTime + C_GroupOfflineRemovalDelay)
  374. NewNotifications.add([_("New connection"), TL::Compose(_("%1 $zis now connected."), Event.Buddy.Name), "Icons64x64_1|Buddy"]);
  375. }
  376. // ---------------------------------- //
  377. // Result of the add buddy request
  378. else if (Event.Type == CBuddiesEvent::EType::AddBuddyResult) {
  379.  
  380. }
  381. // ---------------------------------- //
  382. // Result of the remove buddy request
  383. else if (Event.Type == CBuddiesEvent::EType::RemoveBuddyResult) {
  384.  
  385. }
  386. }
  387.  
  388. // ---------------------------------- //
  389. // Manage events
  390. foreach (Event in PendingEvents) {
  391. // ---------------------------------- //
  392. // Manialink layer custom event
  393. if (Event.Type == CManiaplanetPluginEvent::EType::LayerCustomEvent) {
  394. // ---------------------------------- //
  395. // Send message to selected buddies
  396. if (Event.CustomEventType == "SendMessage" && Event.CustomEventData.count >= 2) {
  397. declare ConversationLogin = Event.CustomEventData[0];
  398. declare MessageBody = Event.CustomEventData[1];
  399.  
  400. switch (ConversationLogin) {
  401. // ---------------------------------- //
  402. // Send message to the group
  403. case "*group*" : {
  404. declare EventIsCommand = (TL::SubString(MessageBody, 0, 1) == "/");
  405. if (EventIsCommand) PerformChatCommand(LocalUser.Login, MessageBody);
  406. else SendMessageToGroup(LocalUser.Login, MessageBody);
  407. }
  408. // ---------------------------------- //
  409. // Send message to global chat
  410. case "*global*" : {
  411. if (Persistent_Evidence_GlobalChatUID > 0) {
  412. // Destroy ongoing request and start new
  413. if (GlobalChat_Requests["SEND_MSG"] != Null) {
  414. Http.Destroy(GlobalChat_Requests["SEND_MSG"]);
  415. GlobalChat_Requests["SEND_MSG"] = Null;
  416. }
  417.  
  418. // Start new request
  419. if (GlobalChat_Requests["SEND_MSG"] == Null) {
  420. GlobalChat_Requests["SEND_MSG"] = Http.CreateGet(FormatURL(
  421. C_GlobalChatServerURL,
  422. ["act" => "SEND_MSG",
  423. "uid" => TL::ToText(Persistent_Evidence_GlobalChatUID),
  424. "login" => LocalUser.Login, "body" => MessageBody]
  425. ), False);
  426. }
  427. }
  428. }
  429. // ---------------------------------- //
  430. // Send message to selected buddy
  431. default : SendMessage(ConversationLogin, "Evidence", MessageBody);
  432. }
  433. }
  434. // ---------------------------------- //
  435. // Tell the receipent user has seen their message
  436. else if (Event.CustomEventType == "SeenMessage" && Event.CustomEventData.count >= 1) {
  437. if (!BuddiesList_Evidence.exists(Event.CustomEventData[0])) continue;
  438. SendMessage(Event.CustomEventData[0], "data", "seenmessage");
  439. }
  440. // ---------------------------------- //
  441. // Copy message content to clipboard
  442. else if (Event.CustomEventType == "SetClipboard") {
  443. declare ClipboardContent = Event.CustomEventData[0];
  444. if (ClipboardContent != "") ClipboardSet(ClipboardContent);
  445. }
  446. // ---------------------------------- //
  447. // Send buddy request to a player
  448. else if (Event.CustomEventType == "AddBuddy") {
  449. BuddiesManager.AddBuddy(Event.CustomEventData[0]);
  450. }
  451. // ---------------------------------- //
  452. // Accept buddy request
  453. else if (Event.CustomEventType == "BuddyAccept") {
  454. declare Login = Event.CustomEventData[0];
  455. if (Login != "") {
  456. declare Buddy = BuddiesManager.GetBuddyFromLogin(Login);
  457. if (Buddy != Null) BuddiesManager.AcceptBuddy(Buddy);
  458. }
  459. }
  460. // ---------------------------------- //
  461. // Deny / cancel buddy request
  462. else if (Event.CustomEventType == "BuddyDeny") {
  463. declare Login = Event.CustomEventData[0];
  464. if (Login != "") {
  465. declare Buddy = BuddiesManager.GetBuddyFromLogin(Login);
  466. if (Buddy != Null) BuddiesManager.RemoveBuddy(Buddy);
  467. }
  468. }
  469. // ---------------------------------- //
  470. // Remove buddy
  471. else if (Event.CustomEventType == "RemoveBuddy") {
  472. DialogVisible = True;
  473. DialogBuddyLogin = Event.CustomEventData[0];
  474. if (BuddiesName.existskey(DialogBuddyLogin))
  475. DialogBuddyName = BuddiesName[DialogBuddyLogin];
  476. }
  477. // ---------------------------------- //
  478. // Confirm buddy removal
  479. else if (Event.CustomEventType == "BuddyRemoved") {
  480. if (Event.CustomEventData.existskey(0) && Event.CustomEventData[0] != "") {
  481. declare Login = Event.CustomEventData[0];
  482. declare Buddy = BuddiesManager.GetBuddyFromLogin(Login);
  483. if (Buddy != Null) BuddiesManager.RemoveBuddy(Buddy);
  484. }
  485. }
  486. // ---------------------------------- //
  487. // Show message notification
  488. else if (Event.CustomEventType == "ShowMessageNotice") {
  489. declare Login = Event.CustomEventData[0];
  490. declare Message = Event.CustomEventData[1];
  491. NewNotifications.add([GetNameFromLogin(Login), Message, "BgRaceScore2|Speaking"]);
  492. }
  493. }
  494. }
  495.  
  496. // ---------------------------------- //
  497. // Update buddies amount
  498. // ---------------------------------- //
  499.  
  500. // ---------------------------------- //
  501. // Online buddies amount change
  502. if (PluginNbUsersOnline != BuddiesManager.OnlineBuddies.count) {
  503. PluginNbUsersOnline = BuddiesManager.OnlineBuddies.count;
  504. BuddiesList_Online.clear();
  505. foreach (Buddy in BuddiesManager.OnlineBuddies) {
  506. BuddiesList_Online.add(Buddy.Login);
  507. BuddiesName[Buddy.Login] = Buddy.Name;
  508. }
  509. BuddiesList_Online = BuddiesList_Online.sort();
  510. }
  511.  
  512. // ---------------------------------- //
  513. // Offline buddies amount change
  514. if (PrevNbBuddiesOffline != BuddiesManager.OfflineBuddies.count) {
  515. PrevNbBuddiesOffline = BuddiesManager.OfflineBuddies.count;
  516. BuddiesList_Offline.clear();
  517. foreach (Buddy in BuddiesManager.OfflineBuddies) {
  518. BuddiesList_Offline.add(Buddy.Login);
  519. BuddiesName[Buddy.Login] = Buddy.Name;
  520. }
  521. BuddiesList_Offline = BuddiesList_Offline.sort();
  522. }
  523.  
  524. // ---------------------------------- //
  525. // Incoming buddy requests amount change
  526. if (PrevNbBuddiesRequestFrom != BuddiesManager.IncomingBuddyRequests.count) {
  527. PrevNbBuddiesRequestFrom = BuddiesManager.IncomingBuddyRequests.count;
  528. BuddiesList_RequestFrom.clear();
  529. foreach (Buddy in BuddiesManager.IncomingBuddyRequests) {
  530. BuddiesList_RequestFrom.add(Buddy.Login);
  531. BuddiesName[Buddy.Login] = Buddy.Name;
  532. }
  533. BuddiesList_RequestFrom = BuddiesList_RequestFrom.sort();
  534. }
  535.  
  536. // ---------------------------------- //
  537. // Outgoing buddy requests amount change
  538. if (PrevNbBuddiesRequestTo != BuddiesManager.OutgoingBuddyRequests.count) {
  539. PrevNbBuddiesRequestTo = BuddiesManager.OutgoingBuddyRequests.count;
  540. BuddiesList_RequestTo.clear();
  541. foreach (Buddy in BuddiesManager.OutgoingBuddyRequests) {
  542. BuddiesList_RequestTo.add(Buddy.Login);
  543. BuddiesName[Buddy.Login] = Buddy.Name;
  544. }
  545. BuddiesList_RequestTo = BuddiesList_RequestTo.sort();
  546. }
  547.  
  548.  
  549. // ---------------------------------- //
  550. // Current server players amount change
  551. if (PrevNbBuddiesOnServer != CurrentServerPlayers.count) {
  552. PrevNbBuddiesOnServer = CurrentServerPlayers.count;
  553. BuddiesList_OnServer.clear();
  554. foreach (Player in CurrentServerPlayers) {
  555. BuddiesList_OnServer.add(Player.Login);
  556. BuddiesName[Player.Login] = Player.Name;
  557. }
  558. BuddiesList_OnServer = BuddiesList_OnServer.sort();
  559. }
  560.  
  561. // ---------------------------------- //
  562. // Group buddies amount change
  563. if (PrevNbBuddiesInGroup != Persistent_Evidence_BuddiesInGroup.count) {
  564. PrevNbBuddiesInGroup = Persistent_Evidence_BuddiesInGroup.count;
  565. BuddiesList_InGroup.clear();
  566. foreach (Login in Persistent_Evidence_BuddiesInGroup) BuddiesList_InGroup.add(Login);
  567. BuddiesList_InGroup = BuddiesList_InGroup.sort();
  568. }
  569.  
  570. // ---------------------------------- //
  571. // Muted buddies amount change
  572. if (PrevNbBuddiesMuted != Persistent_Evidence_MutedGroupBuddies.count) {
  573. PrevNbBuddiesMuted = Persistent_Evidence_MutedGroupBuddies.count;
  574. BuddiesList_MutedUsers.clear();
  575. foreach (Login in Persistent_Evidence_MutedGroupBuddies) BuddiesList_MutedUsers.add(Login);
  576. BuddiesList_MutedUsers = BuddiesList_MutedUsers.sort();
  577. }
  578.  
  579. // ---------------------------------- //
  580. // Remove offline buddies from group
  581. if (Now > StartTime + C_GroupOfflineRemovalDelay) {
  582. foreach (Buddy in BuddiesManager.OfflineBuddies) {
  583. if (Persistent_Evidence_BuddiesInGroup.exists(Buddy.Login))
  584. PerformChatCommand(Buddy.Login, "/quit");
  585. }
  586. }
  587.  
  588. // ---------------------------------- //
  589. // Check if name of invited buddy changed
  590. foreach (Buddy in BuddiesManager.OutgoingBuddyRequests) {
  591. if (!PrevOutgoingBuddyNames.existskey(Buddy.Login) || PrevOutgoingBuddyNames[Buddy.Login] != Buddy.Name) {
  592. PrevOutgoingBuddyNames[Buddy.Login] = Buddy.Name;
  593. BuddiesName[Buddy.Login] = Buddy.Name;
  594. }
  595. }
  596.  
  597. // ---------------------------------- //
  598. // User changed his presence
  599. if (PrevManialinkTargetPresence != ManialinkTargetPresence) {
  600. PrevManialinkTargetPresence = ManialinkTargetPresence;
  601. SET_STATUS = True;
  602. }
  603.  
  604. // ---------------------------------- //
  605. // User changed his custom status
  606. if (PrevManialinkCustomStatus != ManialinkCustomStatus) {
  607. PrevManialinkCustomStatus = ManialinkCustomStatus;
  608. SET_STATUS = True;
  609. }
  610.  
  611. // ---------------------------------- //
  612. // User changed his server
  613. if (PrevUserServerLogin != CurrentServerLogin) {
  614. PrevUserServerLogin = CurrentServerLogin;
  615. SET_STATUS = True;
  616. }
  617.  
  618. // ---------------------------------- //
  619. // Server the user is playing on changed name
  620. if (PrevUserServerName != CurrentServerName) {
  621. PrevUserServerName = CurrentServerName;
  622. SET_STATUS = True;
  623. }
  624.  
  625. // ---------------------------------- //
  626. // Dynamic status usage change
  627. if (PrevUseDynamicStatus != UseDynamicStatus) {
  628. PrevUseDynamicStatus = UseDynamicStatus;
  629. SET_STATUS = True;
  630. }
  631.  
  632. // ---------------------------------- //
  633. // Status depending on active context
  634. if (UseDynamicStatus && PrevActiveContext != ActiveContext) {
  635. PrevActiveContext = ActiveContext;
  636.  
  637. // Get status for current context
  638. if (C_ContextStatusText.existskey(ActiveContext)) {
  639. ContextAutoStatus = C_ContextStatusText[ActiveContext];
  640.  
  641. // Compose current title pack name
  642. if (LoadedTitle != Null && TL::Find("%1", ContextAutoStatus, False, False)) {
  643. declare TitlePackName = LoadedTitle.Name;
  644. foreach (Word in C_ContextAvoidInTitle)
  645. if (TL::Find(Word, TitlePackName, False, False))
  646. TitlePackName = TL::Replace(TitlePackName, Word, "");
  647. ContextAutoStatus = TL::Compose(ContextAutoStatus, TitlePackName);
  648. }
  649. }
  650. // There is no available status
  651. else ContextAutoStatus = "";
  652.  
  653. // Force update status
  654. if (UseDynamicStatus && C_ContextStatusPresences.exists(CurrentPluginPresenceId))
  655. SET_STATUS = True;
  656. }
  657.  
  658. // ---------------------------------- //
  659. // Update user status and presence
  660. if (SET_STATUS) {
  661. SET_STATUS = False;
  662.  
  663. // Get presence
  664. CurrentPluginPresenceId = ManialinkTargetPresence;
  665.  
  666. // Get status
  667. declare NewStatusText = _("Available");
  668. if (ManialinkCustomStatus != "") NewStatusText = ManialinkCustomStatus;
  669. else if (UseDynamicStatus && ContextAutoStatus != "" && C_ContextStatusPresences.exists(CurrentPluginPresenceId))
  670. NewStatusText = ContextAutoStatus;
  671. else if (C_UserPresenceStatus.existskey(CurrentPluginPresenceId))
  672. NewStatusText = C_UserPresenceStatus[CurrentPluginPresenceId];
  673.  
  674. // Send new presence and status to buddies
  675. BuddiesManager.ChangePresence(GetPresenceFromId(CurrentPluginPresenceId), NewStatusText);
  676.  
  677. // Send new status to manialink
  678. if (CurrentServerName != "") CurrentPluginStatusText = CurrentServerName;
  679. else if (CurrentServerLogin != "") CurrentPluginStatusText = CurrentServerLogin;
  680. else CurrentPluginStatusText = NewStatusText;
  681. }
  682.  
  683. // ---------------------------------- //
  684. // User changed chat visibility through plugin icon
  685. if (PluginTriggerOpenChat) {
  686. PluginTriggerOpenChat = False;
  687. ChatWidgetIsOpen = !ChatWidgetIsOpen;
  688. }
  689.  
  690. // ---------------------------------- //
  691. // Other
  692. ToolBarForceShow = ChatWidgetIsOpen;
  693. PluginIsChatWindowOpen = ChatWidgetIsOpen;
  694. LegacyMailsAmount = Messenger_MessagesCount;
  695. PluginNbUnreadMessages = TotalNbUnreadMessages;
  696. ToolbarActive = ToolBarIsActive;
  697.  
  698. if (FlashTaskbar) {
  699. FlashTaskbar = False;
  700. FlashWindow();
  701. }
  702. ***
  703.  
  704. // ---------------------------------- //
  705. // Global Chat start
  706. // ---------------------------------- //
  707. ***GlobalChatStart***
  708. ***
  709. // ---------------------------------- //
  710. // Persistent settings
  711. declare persistent Integer Persistent_Evidence_GlobalChatUID = -1;
  712. Persistent_Evidence_GlobalChatUID = -1;
  713.  
  714. // ---------------------------------- //
  715. // Manialink communication
  716. declare GlobalChat_ConnectionStatus for WindowPage = 0;
  717. declare EnableGlobalChat for WindowPage = False;
  718.  
  719. // ---------------------------------- //
  720. // Variables
  721. declare CHttpRequest[Text] GlobalChat_Requests;
  722. declare Integer[Text] GlobalChat_RequestStartTime;
  723. declare Integer[Text] GlobalChat_NextRequestTime;
  724.  
  725. /// Init requests
  726. foreach (Method in C_GlobalChatServerMethods) {
  727. GlobalChat_Requests[Method] = Null;
  728. GlobalChat_RequestStartTime[Method] = 0;
  729. GlobalChat_NextRequestTime[Method] = 0;
  730. }
  731. ***
  732.  
  733. // ---------------------------------- //
  734. // Global Chat yield
  735. // ---------------------------------- //
  736. ***GlobalChatYield***
  737. ***
  738. // ---------------------------------- //
  739. // Global Chat is turned off
  740. if (!EnableGlobalChat) {
  741. if (GlobalChat_ConnectionStatus != 0) {
  742. GlobalChat_ConnectionStatus = 0;
  743. Persistent_Evidence_GlobalChatUID = -1;
  744. declare XMLDocument = Xml.Create("<users/>");
  745. LoadUsersData(XMLDocument);
  746. Xml.Destroy(XMLDocument);
  747. }
  748. }
  749. // ---------------------------------- //
  750. // Get new UID from server
  751. else if (Persistent_Evidence_GlobalChatUID <= 0) {
  752. GlobalChat_ConnectionStatus = 3;
  753.  
  754. // Start new request
  755. if (GlobalChat_Requests["GET_UID"] == Null) {
  756. // Prevent spamming the server
  757. if (Now >= GlobalChat_NextRequestTime["GET_UID"]) {
  758. GlobalChat_Requests["GET_UID"] = Http.CreateGet(FormatURL(C_GlobalChatServerURL, [
  759. "act" => "GET_UID",
  760. "login" => LocalUser.Login
  761. ]), False);
  762. GlobalChat_RequestStartTime["GET_UID"] = Now;
  763. GlobalChat_NextRequestTime["GET_UID"] = Now + C_GlobalChatRequestInterval["GET_UID"];
  764. }
  765. }
  766. // Set new UID
  767. else if (GlobalChat_Requests["GET_UID"].IsCompleted) {
  768. Persistent_Evidence_GlobalChatUID = TL::ToInteger(GlobalChat_Requests["GET_UID"].Result);
  769. Http.Destroy(GlobalChat_Requests["GET_UID"]);
  770. GlobalChat_Requests["GET_UID"] = Null;
  771. }
  772. // Destroy timed out request
  773. else if (Now >= GlobalChat_RequestStartTime["GET_UID"] + C_GlobalChatGetUIDTimeout) {
  774. Http.Destroy(GlobalChat_Requests["GET_UID"]);
  775. GlobalChat_Requests["GET_UID"] = Null;
  776. }
  777. }
  778. // ---------------------------------- //
  779. // Perform all important requests
  780. else {
  781. GlobalChat_ConnectionStatus = 1;
  782.  
  783. // ---------------------------------- //
  784. // Trigger chat error
  785. if (G_GlobalChat_ConnectionError) {
  786. G_GlobalChat_ConnectionError = False;
  787. Persistent_Evidence_GlobalChatUID = -1;
  788. }
  789.  
  790. // ---------------------------------- //
  791. // Update connection time
  792. if (Now > GlobalChat_NextRequestTime["REFRESH"]) {
  793. // Destroy ongoing request and start new
  794. if (GlobalChat_Requests["REFRESH"] != Null) {
  795. Http.Destroy(GlobalChat_Requests["REFRESH"]);
  796. GlobalChat_Requests["REFRESH"] = Null;
  797. }
  798.  
  799. // Start new request
  800. if (GlobalChat_Requests["REFRESH"] == Null) {
  801. GlobalChat_Requests["REFRESH"] = Http.CreateGet(FormatURL(C_GlobalChatServerURL, [
  802. "act" => "REFRESH",
  803. "uid" => TL::ToText(Persistent_Evidence_GlobalChatUID),
  804. "login" => LocalUser.Login
  805. ]), False);
  806. GlobalChat_NextRequestTime["REFRESH"] = Now + C_GlobalChatRequestInterval["REFRESH"];
  807. }
  808. }
  809.  
  810. // ---------------------------------- //
  811. // Update local user status
  812. if (Now > GlobalChat_NextRequestTime["SET_STATUS"]) {
  813. // Destroy ongoing request and start new
  814. if (GlobalChat_Requests["SET_STATUS"] != Null) {
  815. Http.Destroy(GlobalChat_Requests["SET_STATUS"]);
  816. GlobalChat_Requests["SET_STATUS"] = Null;
  817. }
  818.  
  819. // Start new request
  820. if (GlobalChat_Requests["SET_STATUS"] == Null) {
  821. GlobalChat_Requests["SET_STATUS"] = Http.CreateGet(FormatURL(C_GlobalChatServerURL, [
  822. "act" => "SET_STATUS",
  823. "uid" => TL::ToText(Persistent_Evidence_GlobalChatUID),
  824. "login" => LocalUser.Login, "name" => LocalUser.Name,
  825. "presence" => TL::ToText(CurrentPluginPresenceId),
  826. "status" => CurrentPluginStatusText
  827. ]), False);
  828. GlobalChat_NextRequestTime["SET_STATUS"] = Now + C_GlobalChatRequestInterval["SET_STATUS"];
  829. }
  830. }
  831.  
  832. // ---------------------------------- //
  833. // Start users list request
  834. if (Now > GlobalChat_NextRequestTime["GET_USER_LIST"]) {
  835. // Destroy ongoing request and start new
  836. if (GlobalChat_Requests["GET_USER_LIST"] != Null) {
  837. Http.Destroy(GlobalChat_Requests["GET_USER_LIST"]);
  838. GlobalChat_Requests["GET_USER_LIST"] = Null;
  839. }
  840.  
  841. // Start new request
  842. if (GlobalChat_Requests["GET_USER_LIST"] == Null) {
  843. GlobalChat_Requests["GET_USER_LIST"] = Http.CreateGet(FormatURL(C_GlobalChatServerURL, ["act" => "GET_USER_LIST"]), False);
  844. GlobalChat_NextRequestTime["GET_USER_LIST"] = Now + C_GlobalChatRequestInterval["GET_USER_LIST"];
  845. }
  846. }
  847.  
  848. // ---------------------------------- //
  849. // Update users list from request result
  850. if (GlobalChat_Requests["GET_USER_LIST"] != Null && GlobalChat_Requests["GET_USER_LIST"].IsCompleted) {
  851. // Get result and destroy request
  852. declare RequestResult = GlobalChat_Requests["GET_USER_LIST"].Result;
  853. Http.Destroy(GlobalChat_Requests["GET_USER_LIST"]);
  854. GlobalChat_Requests["GET_USER_LIST"] = Null;
  855.  
  856. // Load users data
  857. if (RequestResult != "") {
  858. declare XMLDocument = Xml.Create(RequestResult);
  859. LoadUsersData(XMLDocument);
  860. Xml.Destroy(XMLDocument);
  861. }
  862. }
  863.  
  864. // ---------------------------------- //
  865. // Start messages list request
  866. if (Now > GlobalChat_NextRequestTime["GET_MSG"]) {
  867. // Destroy ongoing request and start new
  868. if (GlobalChat_Requests["GET_MSG"] != Null) {
  869. Http.Destroy(GlobalChat_Requests["GET_MSG"]);
  870. GlobalChat_Requests["GET_MSG"] = Null;
  871. }
  872.  
  873. // Start new request
  874. if (GlobalChat_Requests["GET_MSG"] == Null) {
  875. GlobalChat_Requests["GET_MSG"] = Http.CreateGet(FormatURL(C_GlobalChatServerURL, ["act" => "GET_MSG"]), False);
  876. GlobalChat_NextRequestTime["GET_MSG"] = Now + C_GlobalChatRequestInterval["GET_MSG"];
  877. }
  878. }
  879.  
  880. // ---------------------------------- //
  881. // Update messages list from request result
  882. if (GlobalChat_Requests["GET_MSG"] != Null && GlobalChat_Requests["GET_MSG"].IsCompleted) {
  883. // Get result and destroy request
  884. declare RequestResult = GlobalChat_Requests["GET_MSG"].Result;
  885. Http.Destroy(GlobalChat_Requests["GET_MSG"]);
  886. GlobalChat_Requests["GET_MSG"] = Null;
  887.  
  888. // Load messages data
  889. if (RequestResult != "") {
  890. declare XMLDocument = Xml.Create(RequestResult);
  891. LoadMessages(XMLDocument);
  892. Xml.Destroy(XMLDocument);
  893. }
  894. }
  895. }
  896. ***
  897.  
  898. // ---------------------------------- //
  899. // Functions
  900. // ---------------------------------- //
  901.  
  902. // ---------------------------------- //
  903. /** Get interface layer from attach Id
  904. *
  905. * @param _LayerId Text Id of the layer
  906. *
  907. * @return First layer with matching Id
  908. */
  909. CUILayer GetLayerFromId(Text _LayerId) {
  910. if (_LayerId == "") return Null;
  911. foreach (Layer in UILayers) if (Layer.AttachId == _LayerId) return Layer;
  912. return Null;
  913. }
  914.  
  915. // ---------------------------------- //
  916. /** Send message to a player
  917. *
  918. * @param _ReceipentLogin Login of the player to send message to
  919. * @param _MessageType Type of the message
  920. * @param _MessageBody Message text contents
  921. */
  922. Void SendMessage(Text _ReceipentLogin, Text _MessageType, Text _MessageBody) {
  923. if (_MessageBody == "") return;
  924.  
  925. declare LoginsToAvoid = ["", LocalUser.Login, "*group*", "*global*"];
  926. if (LoginsToAvoid.exists(_ReceipentLogin)) return;
  927.  
  928. declare Receipent = BuddiesManager.GetBuddyFromLogin(_ReceipentLogin);
  929. if (Receipent == Null) return;
  930. BuddiesManager.SendMessage(Receipent, _MessageType, _MessageBody);
  931. }
  932.  
  933. // ---------------------------------- //
  934. /** Get presence ID from presence enumerator
  935. *
  936. * @param _PresenceShow Buddy presence
  937. *
  938. * @return Presence ID
  939. */
  940. Integer GetPresenceId(CBuddy::EPresenceShow _PresenceShow) {
  941. switch (_PresenceShow) {
  942. case CBuddy::EPresenceShow::Available : return 1;
  943. case CBuddy::EPresenceShow::Away : return 2;
  944. case CBuddy::EPresenceShow::DoNotDisturb : return 3;
  945. case CBuddy::EPresenceShow::WantToChat : return 4;
  946. case CBuddy::EPresenceShow::ExtendedAway : return 5;
  947. }
  948. return 0;
  949. }
  950.  
  951. // ---------------------------------- //
  952. /** Get presence enumerator from its Id
  953. *
  954. * @param _PresenceId Id of the presence to get
  955. *
  956. * @return Presence enumerator value
  957. */
  958. CBuddiesManager::EPresenceShow GetPresenceFromId(Integer _PresenceId) {
  959. switch (_PresenceId) {
  960. case 2 : return CBuddiesManager::EPresenceShow::Away;
  961. case 3 : return CBuddiesManager::EPresenceShow::DoNotDisturb;
  962. case 4 : return CBuddiesManager::EPresenceShow::WantToChat;
  963. case 5 : return CBuddiesManager::EPresenceShow::ExtendedAway;
  964. }
  965. return CBuddiesManager::EPresenceShow::Available;
  966. }
  967.  
  968. // ---------------------------------- //
  969. /** Get permissions level required to perform specified command
  970. *
  971. * @param _Command Command to check permissions
  972. *
  973. * @return Required permissions level
  974. */
  975. Integer GetCommandPermissionsLevel(Text _Command) {
  976. if (C_GroupCommandPermissionsLevels.existskey(_Command))
  977. return C_GroupCommandPermissionsLevels[_Command];
  978. return 0;
  979. }
  980.  
  981. // ---------------------------------- //
  982. /** Get permissions level of specific user
  983. *
  984. * @param _Command Command to check permissions
  985. *
  986. * @return Required permissions level
  987. */
  988. Integer GetUserPermissionsLevel(Text _UserLogin) {
  989. // User is host
  990. if (_UserLogin == LocalUser.Login) return 2;
  991.  
  992. // User is operator
  993. declare persistent Text[] Persistent_Evidence_GroupOperators;
  994. if (Persistent_Evidence_GroupOperators.exists(_UserLogin)) return 1;
  995.  
  996. // Standard user
  997. return 0;
  998. }
  999.  
  1000. // ---------------------------------- //
  1001. /** Get name of the permissions level
  1002. *
  1003. * @param _PermissionsLevel Level to get name
  1004. *
  1005. * @return Name of the permissions level
  1006. */
  1007. Text GetPermissionsLevelName(Integer _PermissionsLevel) {
  1008. switch (_PermissionsLevel) {
  1009. case 2 : return "Host";
  1010. case 1 : return "Operator";
  1011. }
  1012. return "User";
  1013. }
  1014.  
  1015. // ---------------------------------- //
  1016. /** Get user name from login
  1017. *
  1018. * @param _UserLogin Find name of user with this login
  1019. *
  1020. * @return Name of the found player or initial login
  1021. */
  1022. Text GetNameFromLogin(Text _UserLogin) {
  1023. if (_UserLogin == "") return "";
  1024. if (_UserLogin == LocalUser.Login) return LocalUser.Name;
  1025.  
  1026. // Find with matchfinding
  1027. declare MatchingBuddiesName = Text[];
  1028. if (TL::Find(_UserLogin, LocalUser.Login, False, False)) MatchingBuddiesName.add(LocalUser.Name);
  1029.  
  1030. foreach (Buddy in BuddiesManager.Buddies) {
  1031. if (Buddy.Login == _UserLogin) return Buddy.Name;
  1032. if (TL::Find(_UserLogin, Buddy.Login, False, False)) MatchingBuddiesName.add(Buddy.Name);
  1033. }
  1034.  
  1035. foreach (Buddy in BuddiesManager.IncomingBuddyRequests) {
  1036. if (Buddy.Login == _UserLogin) return Buddy.Name;
  1037. if (TL::Find(_UserLogin, Buddy.Login, False, False)) MatchingBuddiesName.add(Buddy.Name);
  1038. }
  1039.  
  1040. foreach (Buddy in BuddiesManager.OutgoingBuddyRequests) {
  1041. if (Buddy.Login == _UserLogin) return Buddy.Name;
  1042. if (TL::Find(_UserLogin, Buddy.Login, False, False)) MatchingBuddiesName.add(Buddy.Name);
  1043. }
  1044.  
  1045. if (MatchingBuddiesName.count == 1) return MatchingBuddiesName[0];
  1046.  
  1047. return _UserLogin;
  1048. }
  1049.  
  1050. // ---------------------------------- //
  1051. /** Remove format from nicknames
  1052. *
  1053. * @param _Message Message to remove names format
  1054. *
  1055. * @return Message without format in nicknames
  1056. */
  1057. Text RemoveNamesFormat(Text _Message) {
  1058. if (_Message == "") return "";
  1059. declare OutputMessage = _Message;
  1060.  
  1061. declare Text[] Nicknames;
  1062. foreach (Buddy in BuddiesManager.Buddies) Nicknames.add(Buddy.Name);
  1063. foreach (Buddy in BuddiesManager.IncomingBuddyRequests) Nicknames.add(Buddy.Name);
  1064. foreach (Buddy in BuddiesManager.OutgoingBuddyRequests) Nicknames.add(Buddy.Name);
  1065.  
  1066. foreach (Name in Nicknames)
  1067. if (TL::Find(Name, OutputMessage, False, False))
  1068. OutputMessage = TL::Replace(OutputMessage, Name, TL::StripFormatting(Name));
  1069.  
  1070. return OutputMessage;
  1071. }
  1072.  
  1073. // ---------------------------------- //
  1074. /** Send message to everyone in the group
  1075. *
  1076. * @param _SenderLogin Message sender login
  1077. * @param _Message Message contents
  1078. */
  1079. Void SendMessageToGroup(Text _SenderLogin, Text _Message) {
  1080. if (_Message == "") return;
  1081. declare FormattedMessage = _Message;
  1082. if (_SenderLogin != "") FormattedMessage = C_GroupFormatMessage^"[$<"^GetNameFromLogin(_SenderLogin)^"$>] "^_Message;
  1083.  
  1084. // ---------------------------------- //
  1085. // Persistent settings
  1086. declare persistent Text[] Persistent_Evidence_BuddiesInGroup;
  1087. declare persistent Text[] Persistent_Evidence_DisabledNoformat;
  1088.  
  1089. // ---------------------------------- //
  1090. // Send message to buddies
  1091. foreach (Login in Persistent_Evidence_BuddiesInGroup) {
  1092. if (Login == _SenderLogin) continue;
  1093.  
  1094. // Remove nicknames format from message
  1095. declare Text MessageForBuddy;
  1096. if (!Persistent_Evidence_DisabledNoformat.exists(Login))
  1097. MessageForBuddy = RemoveNamesFormat(FormattedMessage);
  1098. else
  1099. MessageForBuddy = FormattedMessage;
  1100.  
  1101. SendMessage(Login, "", MessageForBuddy);
  1102. }
  1103.  
  1104. // ---------------------------------- //
  1105. // Display message on host's screen
  1106. declare WindowLayer = GetLayerFromId("WindowLayer");
  1107. declare WindowPage <=> WindowLayer.LocalPage;
  1108. declare Text[][] NewReceivedMessages for WindowPage;
  1109.  
  1110. NewReceivedMessages.add(["*group*", _SenderLogin, _Message]);
  1111. }
  1112.  
  1113. // ---------------------------------- //
  1114. /** Process command sent to the Group Chat server
  1115. *
  1116. * @param _CommandPerformer User that sent command
  1117. * @param _MessageBody Message contents
  1118. */
  1119. Void PerformChatCommand(Text _CommandPerformer, Text _MessageBody) {
  1120. if (_CommandPerformer == "" || _MessageBody == "") return;
  1121. declare SplitCommand = TL::Split(" ", TL::SubString(_MessageBody, 1, TL::Length(_MessageBody) - 1));
  1122. if (SplitCommand.count <= 0) return;
  1123.  
  1124. declare CommandType = SplitCommand[0];
  1125. declare Buddy = BuddiesManager.GetBuddyFromLogin(_CommandPerformer);
  1126. declare UserLevelName = GetPermissionsLevelName(GetUserPermissionsLevel(_CommandPerformer));
  1127. declare Text ExceptionMessage;
  1128.  
  1129. // ---------------------------------- //
  1130. // Get command sender name
  1131. declare Text UserName;
  1132. if (_CommandPerformer == LocalUser.Login) UserName = LocalUser.Name;
  1133. else if (Buddy != Null) UserName = Buddy.Name;
  1134.  
  1135. // ---------------------------------- //
  1136. // Persistent settings
  1137. declare persistent Text[] Persistent_Evidence_BuddiesInGroup;
  1138. declare persistent Text[] Persistent_Evidence_GroupOperators;
  1139. declare persistent Text[] Persistent_Evidence_GroupBannedUsers;
  1140. declare persistent Text[] Persistent_Evidence_MutedGroupBuddies;
  1141. declare persistent Text[] Persistent_Evidence_DisabledNoformat;
  1142. declare persistent Text[Text] Persistent_Evidence_LastPMLogins;
  1143.  
  1144. // ---------------------------------- //
  1145. // Get manialink layer
  1146. declare WindowLayer = GetLayerFromId("WindowLayer");
  1147. declare WindowPage <=> WindowLayer.LocalPage;
  1148.  
  1149. // ---------------------------------- //
  1150. // Share variables with manialink
  1151. declare Text[][] NewReceivedMessages for WindowPage;
  1152. declare Text GroupChatPassword for WindowPage;
  1153.  
  1154. // ---------------------------------- //
  1155. // Overall: join command
  1156. if (CommandType == "join") {
  1157. declare Text RequestedPassword;
  1158. foreach (I => Word in SplitCommand) if (I > 0) {
  1159. if (I > 1) RequestedPassword ^= " ";
  1160. RequestedPassword ^= Word;
  1161. }
  1162.  
  1163. // Host tries to connect to itself
  1164. if (_CommandPerformer == LocalUser.Login)
  1165. NewReceivedMessages.add(["*group*", "", C_GroupFormatError^"You're the host!"]);
  1166.  
  1167. // User is already connected
  1168. else if (Persistent_Evidence_BuddiesInGroup.exists(_CommandPerformer))
  1169. BuddiesManager.SendMessage(Buddy, "", C_GroupFormatError^"You're already connected!");
  1170.  
  1171. // User is banned
  1172. else if (Persistent_Evidence_GroupBannedUsers.exists(_CommandPerformer))
  1173. BuddiesManager.SendMessage(Buddy, "", C_GroupFormatError^"You're banned in this group!");
  1174.  
  1175. // Add user to the group
  1176. else if (GroupChatPassword == "" || RequestedPassword == GroupChatPassword) {
  1177. Persistent_Evidence_BuddiesInGroup.add(_CommandPerformer);
  1178. SendMessageToGroup("", C_GroupFormatSuccess^UserLevelName^" $<"^UserName^"$> joined the group");
  1179. PerformChatCommand(_CommandPerformer, "/list");
  1180. }
  1181.  
  1182. // User joins without password
  1183. else if (RequestedPassword == "")
  1184. BuddiesManager.SendMessage(Buddy, "", C_GroupFormatError^"You must enter a password to connect: /join <password>");
  1185.  
  1186. // User sent wrong password
  1187. else BuddiesManager.SendMessage(Buddy, "", C_GroupFormatError^"Incorrect password!");
  1188. return;
  1189. }
  1190.  
  1191. // ---------------------------------- //
  1192. // Ignore all commands if user is not in the group
  1193. else if (_CommandPerformer != LocalUser.Login && !Persistent_Evidence_BuddiesInGroup.exists(_CommandPerformer)) return;
  1194.  
  1195. // ---------------------------------- //
  1196. // Check user permissions
  1197. if (GetUserPermissionsLevel(_CommandPerformer) < GetCommandPermissionsLevel(CommandType))
  1198. ExceptionMessage = "You don't have enough permissions!";
  1199.  
  1200. // ---------------------------------- //
  1201. // Perform apecific command
  1202. switch (CommandType) {
  1203. // ---------------------------------- //
  1204. // Leave the group
  1205. case "quit" : {
  1206. if (_CommandPerformer != LocalUser.Login) {
  1207. SendMessageToGroup("", C_GroupFormatSuccess^UserLevelName^" $<"^UserName^"$> has left the group");
  1208. declare Removed = Persistent_Evidence_BuddiesInGroup.remove(_CommandPerformer);
  1209. return;
  1210. }
  1211. // Host tries to leave
  1212. else ExceptionMessage = "You're the host!";
  1213. }
  1214. // ---------------------------------- //
  1215. // Commands help
  1216. case "help" : {
  1217. declare Text ComposedMessage;
  1218. declare Text CommandToShowHelp;
  1219. if (SplitCommand.existskey(1)) CommandToShowHelp = SplitCommand[1];
  1220.  
  1221. // Show help for specified command
  1222. if (C_GroupCommandsHelp.existskey(CommandToShowHelp))
  1223. ComposedMessage = C_GroupCommandsHelp[CommandToShowHelp];
  1224.  
  1225. // Show help for the formatted message command
  1226. else if (C_ChatMessageCommands.existskey(CommandToShowHelp))
  1227. ComposedMessage = "/"^CommandToShowHelp^" "^C_GroupCommandsHelp["/chatmsg"];
  1228.  
  1229. // Show list of all available commands
  1230. else {
  1231. ComposedMessage = "Available commands: ";
  1232. declare Text[] AllCommands;
  1233.  
  1234. foreach (Command => Help in C_GroupCommandsHelp) if (Command != "/chatmsg") AllCommands.add(Command);
  1235. foreach (Command => Message in C_ChatMessageCommands) AllCommands.add(Command);
  1236. AllCommands = AllCommands.sort();
  1237.  
  1238. foreach (I => Command in AllCommands) {
  1239. if (I > 0) ComposedMessage ^= ", ";
  1240. ComposedMessage ^= Command;
  1241. }
  1242. ComposedMessage ^= ".";
  1243. }
  1244.  
  1245. // Send message to buddy
  1246. if (_CommandPerformer == LocalUser.Login) NewReceivedMessages.add(["*group*", "", C_GroupFormatInfo^ComposedMessage]);
  1247. else BuddiesManager.SendMessage(Buddy, "", C_GroupFormatInfo^ComposedMessage);
  1248. return;
  1249. }
  1250. // ---------------------------------- //
  1251. // Me
  1252. case "me" : {
  1253. // User is muted
  1254. if (Persistent_Evidence_MutedGroupBuddies.exists(_CommandPerformer))
  1255. ExceptionMessage = "You're muted in this group!";
  1256.  
  1257. // Send message
  1258. else if (SplitCommand.existskey(1)) {
  1259. declare Text CommandText;
  1260. foreach (I => Word in SplitCommand) if (I > 0) CommandText ^= Word^" ";
  1261. SendMessageToGroup("", C_GroupFormatInfo^"$<"^UserName^"$> $i"^CommandText);
  1262. return;
  1263. }
  1264.  
  1265. // Missing parameters
  1266. else ExceptionMessage = "Usage: /me [message]";
  1267. }
  1268. // ---------------------------------- //
  1269. // Create list
  1270. case "list" : {
  1271. declare OutputMessage = C_GroupFormatInfo;
  1272. declare Text ListType;
  1273. if (SplitCommand.existskey(1)) ListType = SplitCommand[1];
  1274.  
  1275. switch (ListType) {
  1276. // ---------------------------------- //
  1277. // Banned users list
  1278. case "ban" : {
  1279. OutputMessage ^= "Banned users ("^Persistent_Evidence_GroupBannedUsers.count^"): ";
  1280. foreach (I => Login in Persistent_Evidence_GroupBannedUsers) {
  1281. if (I > 0) OutputMessage ^= ", ";
  1282. OutputMessage ^= Login;
  1283. }
  1284. }
  1285. // ---------------------------------- //
  1286. // Muted users list
  1287. case "muted" : {
  1288. OutputMessage ^= "Muted users ("^Persistent_Evidence_MutedGroupBuddies.count^"): ";
  1289. foreach (I => Login in Persistent_Evidence_MutedGroupBuddies) {
  1290. if (I > 0) OutputMessage ^= ", ";
  1291. OutputMessage ^= Login;
  1292. }
  1293. }
  1294. // ---------------------------------- //
  1295. // Operators list
  1296. case "op" : {
  1297. OutputMessage ^= "Group operators ("^1 + Persistent_Evidence_GroupOperators.count^"): "^LocalUser.Login;
  1298. foreach (I => Login in Persistent_Evidence_GroupOperators) OutputMessage ^= ", "^Login;
  1299. }
  1300. // ---------------------------------- //
  1301. // Operators list
  1302. case "nf" : {
  1303. OutputMessage ^= "Users that disabled \"noformat\" option ("^Persistent_Evidence_DisabledNoformat.count^"): ";
  1304. foreach (I => Login in Persistent_Evidence_DisabledNoformat) {
  1305. if (I > 0) OutputMessage ^= ", ";
  1306. OutputMessage ^= Login;
  1307. }
  1308. }
  1309. // ---------------------------------- //
  1310. // List of all available logins to format name
  1311. case "logins" : {
  1312. declare Text[] AvailableLogins;
  1313. foreach (Buddy in BuddiesManager.Buddies) AvailableLogins.add(Buddy.Login);
  1314. foreach (Buddy in BuddiesManager.IncomingBuddyRequests) AvailableLogins.add(Buddy.Login);
  1315. foreach (Buddy in BuddiesManager.OutgoingBuddyRequests) AvailableLogins.add(Buddy.Login);
  1316. AvailableLogins = AvailableLogins.sort();
  1317.  
  1318. OutputMessage ^= "Available logins ("^1 + AvailableLogins.count^"): "^LocalUser.Login;
  1319. foreach (I => Login in AvailableLogins) OutputMessage ^= ", "^Login;
  1320. }
  1321. // ---------------------------------- //
  1322. // Connected users list
  1323. default : {
  1324. OutputMessage ^= "Users online ("^1 + Persistent_Evidence_BuddiesInGroup.count^"): "^LocalUser.Login;
  1325. foreach (Login in Persistent_Evidence_BuddiesInGroup) OutputMessage ^= ", "^Login;
  1326. }
  1327. }
  1328.  
  1329. // Display list on user screen
  1330. if (_CommandPerformer == LocalUser.Login) NewReceivedMessages.add(["*group*", "", OutputMessage]);
  1331. else BuddiesManager.SendMessage(Buddy, "", OutputMessage);
  1332. return;
  1333. }
  1334. // ---------------------------------- //
  1335. // Kick user
  1336. case "kick" : {
  1337. declare Text ExceptionMessage;
  1338. if (SplitCommand.existskey(1) && SplitCommand[1] != "") {
  1339. declare LoginToMute = SplitCommand[1];
  1340.  
  1341. // User tried to kick host
  1342. if (LoginToMute == LocalUser.Login) ExceptionMessage = "Requested user is the host!";
  1343.  
  1344. // User is not connected
  1345. else if (!Persistent_Evidence_BuddiesInGroup.exists(LoginToMute))
  1346. ExceptionMessage = "User not found!";
  1347.  
  1348. // Operator tries to kick another operator
  1349. else if (GetUserPermissionsLevel(_CommandPerformer) <= 1 && GetUserPermissionsLevel(LoginToMute) >= 1)
  1350. ExceptionMessage = "You can't kick other operators!";
  1351.  
  1352. // Kick specified user
  1353. else {
  1354. SendMessageToGroup("", C_GroupFormatSuccess^UserLevelName^" $<"^UserName^"$> kicked $<"^GetNameFromLogin(LoginToMute)^"$>!");
  1355. PerformChatCommand(LoginToMute, "/quit");
  1356. return;
  1357. }
  1358. }
  1359. // Login not specified
  1360. else ExceptionMessage = "Usage: /kick [login]";
  1361. }
  1362. // ---------------------------------- //
  1363. // Ban user
  1364. case "ban" : {
  1365. if (SplitCommand.existskey(1) && SplitCommand[1] != "") {
  1366. declare LoginToBan = SplitCommand[1];
  1367.  
  1368. // User tried to ban host
  1369. if (LoginToBan == LocalUser.Login) ExceptionMessage = "Requested user is the host!";
  1370.  
  1371. // User is not connected
  1372. else if (!Persistent_Evidence_BuddiesInGroup.exists(LoginToBan))
  1373. ExceptionMessage = "User not found!";
  1374.  
  1375. // User is already banned
  1376. else if (Persistent_Evidence_GroupBannedUsers.exists(LoginToBan))
  1377. ExceptionMessage = "Requested user is already banned!";
  1378.  
  1379. // Operator tries to ban another operator
  1380. else if (GetUserPermissionsLevel(_CommandPerformer) <= 1 && GetUserPermissionsLevel(LoginToBan) >= 1)
  1381. ExceptionMessage = "You can't ban other operators!";
  1382.  
  1383. // Ban specified user
  1384. else {
  1385. Persistent_Evidence_GroupBannedUsers.add(LoginToBan);
  1386. SendMessageToGroup("", C_GroupFormatSuccess^UserLevelName^" $<"^UserName^"$> banned $<"^GetNameFromLogin(LoginToBan)^"$>!");
  1387. PerformChatCommand(LoginToBan, "/quit");
  1388. return;
  1389. }
  1390. }
  1391. // Login not specified
  1392. else ExceptionMessage = "Usage: /ban [login]";
  1393. }
  1394. // ---------------------------------- //
  1395. // Unban user
  1396. case "unban" : {
  1397. if (SplitCommand.existskey(1) && SplitCommand[1] != "") {
  1398. declare LoginToUnban = SplitCommand[1];
  1399.  
  1400. // User tried to ban host
  1401. if (LoginToUnban == LocalUser.Login) ExceptionMessage = "Requested user is the host!";
  1402.  
  1403. // User is not banned
  1404. else if (!Persistent_Evidence_GroupBannedUsers.exists(LoginToUnban))
  1405. ExceptionMessage = "Requested user is not banned!";
  1406.  
  1407. // Operator tries to unban another operator
  1408. else if (GetUserPermissionsLevel(_CommandPerformer) <= 1 && GetUserPermissionsLevel(LoginToUnban) >= 1)
  1409. ExceptionMessage = "You can't unban other operators!";
  1410.  
  1411. // Unban specified user
  1412. else {
  1413. declare Removed = Persistent_Evidence_GroupBannedUsers.remove(LoginToUnban);
  1414. SendMessageToGroup("", C_GroupFormatSuccess^UserLevelName^" $<"^UserName^"$> unbanned $<"^GetNameFromLogin(LoginToUnban)^"$>!");
  1415. return;
  1416. }
  1417. }
  1418. // Login not specified
  1419. else ExceptionMessage = "Usage: /unban [login]";
  1420. }
  1421. // ---------------------------------- //
  1422. // Mute user
  1423. case "mute" : {
  1424. if (SplitCommand.existskey(1) && SplitCommand[1] != "") {
  1425. declare LoginToMute = SplitCommand[1];
  1426.  
  1427. // User tried to mute host
  1428. if (LoginToMute == LocalUser.Login) ExceptionMessage = "Requested user is the host!";
  1429.  
  1430. // User is not connected
  1431. else if (!Persistent_Evidence_BuddiesInGroup.exists(LoginToMute))
  1432. ExceptionMessage = "User not found!";
  1433.  
  1434. // User is already muted
  1435. else if (Persistent_Evidence_MutedGroupBuddies.exists(LoginToMute))
  1436. ExceptionMessage = "Requested user is already muted!";
  1437.  
  1438. // Operator tries to mute another operator
  1439. else if (GetUserPermissionsLevel(_CommandPerformer) <= 1 && GetUserPermissionsLevel(LoginToMute) >= 1)
  1440. ExceptionMessage = "You can't mute other operators!";
  1441.  
  1442. // Mute specified user
  1443. else {
  1444. Persistent_Evidence_MutedGroupBuddies.add(LoginToMute);
  1445. SendMessageToGroup("", C_GroupFormatSuccess^UserLevelName^" $<"^UserName^"$> muted $<"^GetNameFromLogin(LoginToMute)^"$>!");
  1446. return;
  1447. }
  1448. }
  1449. // Login not specified
  1450. else ExceptionMessage = "Usage: /mute [login]";
  1451. }
  1452. // ---------------------------------- //
  1453. // Unmute user
  1454. case "unmute" : {
  1455. if (SplitCommand.existskey(1) && SplitCommand[1] != "") {
  1456. declare LoginToUnmute = SplitCommand[1];
  1457.  
  1458. // User tried to mute host
  1459. if (LoginToUnmute == LocalUser.Login) ExceptionMessage = "Requested user is the host!";
  1460.  
  1461. // User is not muted
  1462. else if (!Persistent_Evidence_MutedGroupBuddies.exists(LoginToUnmute))
  1463. ExceptionMessage = "Requested user is not muted!";
  1464.  
  1465. // Operator tries to unmute another operator
  1466. else if (GetUserPermissionsLevel(_CommandPerformer) <= 1 && GetUserPermissionsLevel(LoginToUnmute) >= 1)
  1467. ExceptionMessage = "You can't unmute other operators!";
  1468.  
  1469. // Unmute specified user
  1470. else {
  1471. declare Removed = Persistent_Evidence_MutedGroupBuddies.remove(LoginToUnmute);
  1472. SendMessageToGroup("", C_GroupFormatSuccess^UserLevelName^" $<"^UserName^"$> unmuted $<"^GetNameFromLogin(LoginToUnmute)^"$>!");
  1473. return;
  1474. }
  1475. }
  1476. // Login not specified
  1477. else ExceptionMessage = "Usage: /unmute [login]";
  1478. }
  1479. // ---------------------------------- //
  1480. // Give operator rights
  1481. case "addop" : {
  1482. if (SplitCommand.existskey(1) && SplitCommand[1] != "") {
  1483. declare LoginToSetOp = SplitCommand[1];
  1484.  
  1485. // User tried to give host operator rights
  1486. if (LoginToSetOp == LocalUser.Login) ExceptionMessage = "Requested user is the host!";
  1487.  
  1488. // User is not connected
  1489. else if (!Persistent_Evidence_BuddiesInGroup.exists(LoginToSetOp))
  1490. ExceptionMessage = "User not found!";
  1491.  
  1492. // User already is operator
  1493. else if (GetUserPermissionsLevel(LoginToSetOp) >= 1)
  1494. ExceptionMessage = "Requested user already has operator rights!";
  1495.  
  1496. // Give operator rights
  1497. else {
  1498. Persistent_Evidence_GroupOperators.add(LoginToSetOp);
  1499. SendMessageToGroup("", C_GroupFormatSuccess^UserLevelName^" $<"^UserName^"$> gave $<"^GetNameFromLogin(LoginToSetOp)^"$> operator rights!");
  1500. return;
  1501. }
  1502. }
  1503. // Login not specified
  1504. else ExceptionMessage = "Usage: /addop [login]";
  1505. }
  1506. // ---------------------------------- //
  1507. // Unmute
  1508. case "removeop" : {
  1509. if (SplitCommand.existskey(1) && SplitCommand[1] != "") {
  1510. declare LoginToRemoveOp = SplitCommand[1];
  1511.  
  1512. // User tried to remove operator rights from host
  1513. if (LoginToRemoveOp == LocalUser.Login) ExceptionMessage = "Requested user is the host!";
  1514.  
  1515. // User is not operator
  1516. else if (GetUserPermissionsLevel(LoginToRemoveOp) < 1)
  1517. ExceptionMessage = "Requested user is not operator!";
  1518.  
  1519. // Remove operator rights
  1520. else {
  1521. declare Removed = Persistent_Evidence_GroupOperators.remove(LoginToRemoveOp);
  1522. SendMessageToGroup("", C_GroupFormatSuccess^UserLevelName^" $<"^UserName^"$> took operator rights from $<"^GetNameFromLogin(LoginToRemoveOp)^"$>!");
  1523. return;
  1524. }
  1525. }
  1526. // Login not specified
  1527. else ExceptionMessage = "Usage: /removeop [login]";
  1528. }
  1529. // ---------------------------------- //
  1530. // Send private message
  1531. case "pm" : {
  1532. if (SplitCommand.existskey(2)) {
  1533. declare MessageRecipient = SplitCommand[1];
  1534.  
  1535. // Sender is muted
  1536. if (Persistent_Evidence_MutedGroupBuddies.exists(_CommandPerformer))
  1537. ExceptionMessage = "You're muted in this group!";
  1538.  
  1539. // User is sending message to himself
  1540. else if (MessageRecipient == _CommandPerformer)
  1541. ExceptionMessage = "You can't send private messages to yourself!";
  1542.  
  1543. // User not found
  1544. else if (!Persistent_Evidence_BuddiesInGroup.exists(MessageRecipient) && MessageRecipient != LocalUser.Login)
  1545. ExceptionMessage = "User not found!";
  1546.  
  1547. // Send message
  1548. else {
  1549. declare Text ComposedMessage;
  1550. foreach (I => Word in SplitCommand) if (I >= 2) ComposedMessage ^= " "^Word;
  1551.  
  1552. // Sender message
  1553. declare SenderMessageText = C_GroupFormatPrivate^"[To $<"^GetNameFromLogin(MessageRecipient)^"$>]"^ComposedMessage;
  1554. if (_CommandPerformer != LocalUser.Login) BuddiesManager.SendMessage(Buddy, "", SenderMessageText);
  1555. else NewReceivedMessages.add(["*group*", LocalUser.Login, SenderMessageText]);
  1556.  
  1557. // Receipent message
  1558. declare RecipientMessageText = C_GroupFormatPrivate^"[From $<"^UserName^"$>]"^ComposedMessage;
  1559. if (MessageRecipient == LocalUser.Login) NewReceivedMessages.add(["*group*", _CommandPerformer, RecipientMessageText]);
  1560. else BuddiesManager.SendMessage(BuddiesManager.GetBuddyFromLogin(MessageRecipient), "", RecipientMessageText);
  1561.  
  1562. // Save latest message sender
  1563. Persistent_Evidence_LastPMLogins[_CommandPerformer] = MessageRecipient;
  1564. Persistent_Evidence_LastPMLogins[MessageRecipient] = _CommandPerformer;
  1565. return;
  1566. }
  1567. }
  1568.  
  1569. // Message not specified
  1570. else if (SplitCommand.existskey(1))
  1571. ExceptionMessage = "Usage: /pm "^SplitCommand[1]^" [message]";
  1572.  
  1573. // Login not specified
  1574. else ExceptionMessage = "Usage: /pm [login] [message]";
  1575. }
  1576. // ---------------------------------- //
  1577. // Reply to latest private message
  1578. case "pmr" : {
  1579. if (SplitCommand.existskey(1)) {
  1580. // Sender is muted
  1581. if (Persistent_Evidence_MutedGroupBuddies.exists(_CommandPerformer))
  1582. ExceptionMessage = "You're muted in this group!";
  1583.  
  1584. // User hasn't contacted anyone yet
  1585. if (!Persistent_Evidence_LastPMLogins.existskey(_CommandPerformer))
  1586. ExceptionMessage = "You haven't started any private conversation yet!";
  1587.  
  1588. // Send message
  1589. else {
  1590. declare Text ComposedMessage;
  1591. foreach (I => Word in SplitCommand) if (I >= 1) ComposedMessage ^= " "^Word;
  1592. declare Recipient = Persistent_Evidence_LastPMLogins[_CommandPerformer];
  1593. PerformChatCommand(_CommandPerformer, "/pm "^Recipient^ComposedMessage);
  1594. return;
  1595. }
  1596. }
  1597.  
  1598. // Message not specified
  1599. else ExceptionMessage = "Usage: /pmr [message]";
  1600. }
  1601. // ---------------------------------- //
  1602. // Set noformat option
  1603. case "noformat" : {
  1604. declare PrevNoformatSetting = !Persistent_Evidence_DisabledNoformat.exists(_CommandPerformer);
  1605. declare Text InformationMessage;
  1606.  
  1607. if (SplitCommand.existskey(1)) {
  1608. declare NewSettingValue = SplitCommand[1] == "1";
  1609.  
  1610. // Invalid value
  1611. if (SplitCommand[1] != "0" && SplitCommand[1] != "1")
  1612. ExceptionMessage = "Only accepted boolean values are \"0\" and \"1\"!";
  1613.  
  1614. // New setting is the same
  1615. else if (NewSettingValue == PrevNoformatSetting)
  1616. ExceptionMessage = "Option \"noformat\" is already set to \""^NewSettingValue^"\"!";
  1617.  
  1618. // Change setting
  1619. else {
  1620. InformationMessage = C_GroupFormatInfo^"Option \"noformat\" has been set to \""^NewSettingValue^"\"!";
  1621. if (!PrevNoformatSetting) {
  1622. declare Removed = Persistent_Evidence_DisabledNoformat.remove(_CommandPerformer);
  1623. } else
  1624. Persistent_Evidence_DisabledNoformat.add(_CommandPerformer);
  1625. }
  1626. }
  1627.  
  1628. // Setting not specified
  1629. else InformationMessage = C_GroupFormatInfo^"Option \"noformat\" is set to \""^PrevNoformatSetting^"\".";
  1630.  
  1631. if (InformationMessage != "") {
  1632. if (_CommandPerformer != LocalUser.Login) BuddiesManager.SendMessage(Buddy, "", InformationMessage);
  1633. else NewReceivedMessages.add(["*group*", "", InformationMessage]);
  1634. return;
  1635. }
  1636. }
  1637. // ---------------------------------- //
  1638. // Show script information
  1639. case "core" : {
  1640. declare ComposedMessage = ScriptName^" v"^ScriptVersionNb^" @"^ScriptVersion;
  1641. if (_CommandPerformer != LocalUser.Login) BuddiesManager.SendMessage(Buddy, "", C_GroupFormatInfo^ComposedMessage);
  1642. else NewReceivedMessages.add(["*group*", "", C_GroupFormatInfo^ComposedMessage]);
  1643. return;
  1644. }
  1645. // ---------------------------------- //
  1646. // Ragequit
  1647. case "rq" : {
  1648. if (_CommandPerformer != LocalUser.Login) {
  1649. SendMessageToGroup("", "$F00$<"^UserName^"$> $isaid !@#$$% and ragequit.");
  1650. PerformChatCommand(_CommandPerformer, "/quit");
  1651. return;
  1652. }
  1653. // Host tries to leave
  1654. else ExceptionMessage = "You're the host!";
  1655. }
  1656. // ---------------------------------- //
  1657. // Bootme
  1658. case "bm" : {
  1659. if (_CommandPerformer != LocalUser.Login) {
  1660. SendMessageToGroup("", C_GroupFormatInfo^"$<"^UserName^"$> $ichooses to boot back to the real world!");
  1661. PerformChatCommand(_CommandPerformer, "/quit");
  1662. return;
  1663. }
  1664. // Host tries to leave
  1665. else ExceptionMessage = "You're the host!";
  1666. }
  1667. }
  1668.  
  1669. // ---------------------------------- //
  1670. // Formatted chat messages
  1671. if (C_ChatMessageCommands.existskey(CommandType)) {
  1672. if (!Persistent_Evidence_MutedGroupBuddies.exists(_CommandPerformer)) {
  1673. declare ComposedMessage = "$i"^C_ChatMessageCommands[CommandType];
  1674.  
  1675. // Attach additional username
  1676. if (SplitCommand.existskey(1) && SplitCommand[1] != "" && C_ChatMessageWithLogin.exists(CommandType))
  1677. ComposedMessage ^= " $i$<"^GetNameFromLogin(SplitCommand[1])^"$>$i";
  1678.  
  1679. ComposedMessage ^= "!";
  1680. SendMessageToGroup(_CommandPerformer, ComposedMessage);
  1681. return;
  1682. }
  1683.  
  1684. // User is muted
  1685. else ExceptionMessage = "You're muted in this group!";
  1686. }
  1687.  
  1688. // ---------------------------------- //
  1689. // Command unknown
  1690. if (ExceptionMessage == "") ExceptionMessage = "Command unknown";
  1691.  
  1692. // ---------------------------------- //
  1693. // Show exception message
  1694. if (_CommandPerformer != LocalUser.Login) BuddiesManager.SendMessage(Buddy, "", C_GroupFormatError^ExceptionMessage);
  1695. else NewReceivedMessages.add(["*group*", "", C_GroupFormatError^ExceptionMessage]);
  1696. }
  1697.  
  1698. // ---------------------------------- //
  1699. /** Format URL from given base and query
  1700. *
  1701. * @param _URL Base of the URL
  1702. * @param _Query Elements of the query
  1703. *
  1704. * @return Complete URL
  1705. */
  1706. Text FormatURL(Text _URL, Text[Text] _Query) {
  1707. if (_URL == "" || !Http.IsValidUrl(_URL)) return "";
  1708. declare Text QueryText;
  1709. declare I = 0;
  1710.  
  1711. foreach (Name => Value in _Query) {
  1712. if (I == 0) QueryText ^= "?";
  1713. else QueryText ^= "&";
  1714. QueryText ^= TL::URLEncode(Name)^"="^TL::URLEncode(Value);
  1715. I += 1;
  1716. }
  1717.  
  1718. return _URL^QueryText;
  1719. }
  1720.  
  1721. // ---------------------------------- //
  1722. /** Load users list and data from request XML result
  1723. *
  1724. * @param _Document XML document with users data
  1725. */
  1726. Void LoadUsersData(CXmlDocument _Document) {
  1727. if (_Document == Null || _Document.Root == Null || _Document.Root.Name != "users") return;
  1728.  
  1729. // ---------------------------------- //
  1730. // Get manialink layer
  1731. declare WindowLayer = GetLayerFromId("WindowLayer");
  1732. if (WindowLayer == Null) return;
  1733.  
  1734. declare WindowPage <=> WindowLayer.LocalPage;
  1735. if (WindowPage == Null) return;
  1736.  
  1737. // ---------------------------------- //
  1738. // Share variables with manialink
  1739. declare Text[] BuddiesList_GlobalList for WindowPage;
  1740. declare Text[Text] GlobalChat_BuddiesName for WindowPage;
  1741. declare Integer[Text] GlobalChat_BuddiesPresenceId for WindowPage;
  1742. declare Text[Text] GlobalChat_BuddiesStatus for WindowPage;
  1743.  
  1744. // Clear previous data
  1745. BuddiesList_GlobalList.clear();
  1746.  
  1747. declare LocalUserExists = False;
  1748.  
  1749. // ---------------------------------- //
  1750. // Read nodes data
  1751. foreach (Node in _Document.Root.Children) {
  1752. if (Node.Name == "user") {
  1753. // Get user Login
  1754. declare UserLogin = Node.GetAttributeText("login", "");
  1755. if (UserLogin != "" && UserLogin != LocalUser.Login) {
  1756. BuddiesList_GlobalList.add(UserLogin);
  1757.  
  1758. // Get user name
  1759. declare UserName = Node.GetAttributeText("name", "");
  1760. if (UserName != "") GlobalChat_BuddiesName[UserLogin] = UserName;
  1761.  
  1762. // Get user presence id
  1763. declare UserPresenceId = Node.GetAttributeInteger("presenceid", 0);
  1764. if (UserPresenceId < 1 || UserPresenceId > 5) UserPresenceId = 1;
  1765. GlobalChat_BuddiesPresenceId[UserLogin] = UserPresenceId;
  1766.  
  1767. // Get user status
  1768. declare UserStatus = Node.GetAttributeText("status", "");
  1769. if (UserStatus == "") UserStatus = C_UserPresenceStatus[UserPresenceId];
  1770. GlobalChat_BuddiesStatus[UserLogin] = UserStatus;
  1771. }
  1772.  
  1773. if (UserLogin == LocalUser.Login) LocalUserExists = True;
  1774. }
  1775. }
  1776.  
  1777. // Trigegr connection error
  1778. if (!LocalUserExists) G_GlobalChat_ConnectionError = True;
  1779. }
  1780.  
  1781. // ---------------------------------- //
  1782. /** Load messages data from request XML result
  1783. *
  1784. * @param _Document XML document with messages data
  1785. */
  1786. Void LoadMessages(CXmlDocument _Document) {
  1787. if (_Document == Null || _Document.Root == Null || _Document.Root.Name != "messages") return;
  1788.  
  1789. // ---------------------------------- //
  1790. // Get manialink layer
  1791. declare WindowLayer = GetLayerFromId("WindowLayer");
  1792. if (WindowLayer == Null) return;
  1793.  
  1794. declare WindowPage <=> WindowLayer.LocalPage;
  1795. if (WindowPage == Null) return;
  1796.  
  1797. // ---------------------------------- //
  1798. // Share variables with manialink
  1799. declare Text[][] NewReceivedMessages for WindowPage;
  1800.  
  1801. // ---------------------------------- //
  1802. // Read nodes data
  1803. foreach (Node in _Document.Root.Children) {
  1804. if (Node.Name == "msg") {
  1805. // Get user Login
  1806. declare UserLogin = Node.GetAttributeText("author", "");
  1807.  
  1808. // Get message timestamp
  1809. declare Timestamp = Node.GetAttributeInteger("timestamp", 0);
  1810.  
  1811. // Get umessage body
  1812. declare MessageBody = Node.GetAttributeText("body", "");
  1813.  
  1814. if (UserLogin != "" && Timestamp > 0 && MessageBody != "") {
  1815. if (!G_GlobalChat_ReceivedMessages.exists(Timestamp)) {
  1816. G_GlobalChat_ReceivedMessages.add(Timestamp);
  1817. NewReceivedMessages.add(["*global*", UserLogin, MessageBody]);
  1818. }
  1819. }
  1820. }
  1821. }
  1822. }
  1823.  
  1824. // ---------------------------------- //
  1825. /** Create widget manialink
  1826. *
  1827. * @return The manialink
  1828. */
  1829. Text CreateManialinkPluginIcon() {
  1830. return """
  1831. <manialink version="2" name="Evidence:PluginIcon">
  1832. <!-- Plugin icon frame -->
  1833. <frame id="Frame_EvidencPluginIcon" posn="-8 90 1">
  1834. <quad sizen="9.5 6" halign="right" bgcolor="0AF" opacity="0" id="Quad_PluginIconBgCard" ScriptEvents="1"/>
  1835. <quad posn="-7 .25 1" sizen="6 6" colorize="FFF" image="http://i.imgur.com/zWESBiR.png"/>
  1836. <label posn="-7.5 -3 1" halign="right" valign="center2" textsize="2" textemboss="1" textcolor="FFF" id="Label_PluginIconUsers"/>
  1837.  
  1838. <!-- Plugin icon notifications amount -->
  1839. <frame id="Frame_PluginIconNotice" posn="-2 -1.5 2" hidden="1">
  1840. <quad sizen="2.5 2.5" halign="center" valign="center" image="file://Media/Manialinks/Common/disc.dds" colorize="B00"/>
  1841. <label posn="0 0 1" halign="center" valign="center2" style="TextValueSmallSm" scale=".45" textcolor="FFF" id="Label_PluginIconNotice"/>
  1842. </frame>
  1843. </frame>
  1844. <script><!--
  1845. /**
  1846. * EVIDENCE by domino54
  1847. * Plugin icon manialink
  1848. */
  1849.  
  1850. #Include "TextLib" as TL
  1851.  
  1852. // ---------------------------------- //
  1853. // Start manialink
  1854. // ---------------------------------- //
  1855. ***StartManialink***
  1856. ***
  1857. // ---------------------------------- //
  1858. // Load interface elements
  1859. declare Quad_PluginIconBgCard <=> (Page.GetFirstChild("Quad_PluginIconBgCard") as CMlQuad);
  1860. declare Label_PluginIconUsers <=> (Page.GetFirstChild("Label_PluginIconUsers") as CMlLabel);
  1861. declare Frame_PluginIconNotice <=> (Page.GetFirstChild("Frame_PluginIconNotice") as CMlFrame);
  1862. declare Label_PluginIconNotice <=> (Page.GetFirstChild("Label_PluginIconNotice") as CMlLabel);
  1863.  
  1864. // ---------------------------------- //
  1865. // Plugin script communication
  1866. declare PluginNbUsersOnline for Page = 0; ///< Amount of buddies online
  1867. declare PluginNbUnreadMessages for Page = 0; ///< Amount of unread messages from buddies and group
  1868. declare PluginIsChatWindowOpen for Page = False; ///< Current chat visibility status
  1869. declare PluginTriggerOpenChat for Page = False; ///< Trigger chat visibility
  1870.  
  1871. /// Update variables
  1872. declare PrevNbBuddiesOnline = -1;
  1873. ***
  1874.  
  1875. // ---------------------------------- //
  1876. // Yield
  1877. // ---------------------------------- //
  1878. ***Yield***
  1879. ***
  1880. // ---------------------------------- //
  1881. // Events management
  1882. foreach (Event in PendingEvents) {
  1883. // ---------------------------------- //
  1884. // Mouse click
  1885. if (Event.Type == CMlEvent::Type::MouseClick) {
  1886. if (Event.ControlId == "Quad_PluginIconBgCard") {
  1887. PluginTriggerOpenChat = True;
  1888. Audio.PlaySoundEvent(CAudioManager::ELibSound::Valid, 1, 0.);
  1889. }
  1890. }
  1891. // ---------------------------------- //
  1892. // Mouse over
  1893. if (Event.Type == CMlEvent::Type::MouseOver) {
  1894. if (Event.ControlId == "Quad_PluginIconBgCard") Quad_PluginIconBgCard.Opacity = .5;
  1895. }
  1896. // ---------------------------------- //
  1897. // Mouse out
  1898. if (Event.Type == CMlEvent::Type::MouseOut) {
  1899. if (Event.ControlId == "Quad_PluginIconBgCard") Quad_PluginIconBgCard.Opacity = 0.;
  1900. }
  1901. }
  1902.  
  1903. // ---------------------------------- //
  1904. // Show amount of connected buddies
  1905. if (PrevNbBuddiesOnline != PluginNbUsersOnline) {
  1906. PrevNbBuddiesOnline = PluginNbUsersOnline;
  1907. Label_PluginIconUsers.SetText(TL::ToText(PluginNbUsersOnline));
  1908. Quad_PluginIconBgCard.Size.X = 9.5 + Label_PluginIconUsers.ComputeWidth(Label_PluginIconUsers.Value);
  1909. }
  1910.  
  1911. // ---------------------------------- //
  1912. // Show amount of unread messages
  1913. Frame_PluginIconNotice.Visible = (!PluginIsChatWindowOpen && PluginNbUnreadMessages > 0);
  1914. if (Frame_PluginIconNotice.Visible) {
  1915. Label_PluginIconNotice.Value = TL::ToText(PluginNbUnreadMessages);
  1916. }
  1917. ***
  1918.  
  1919. // ---------------------------------- //
  1920. // Main
  1921. // ---------------------------------- //
  1922. main() {
  1923. +++StartManialink+++
  1924. while (True) {
  1925. +++Yield+++
  1926. yield;
  1927. }
  1928. }
  1929. --></script>
  1930. </manialink>""";
  1931. }
  1932.  
  1933. // ---------------------------------- //
  1934. /** Create dialog box manialink
  1935. *
  1936. * @return The manialink
  1937. */
  1938. Text CreateManialinkDialogBox() {
  1939. return """
  1940. <manialink version="2" name="Evidence:DialogBox" background="0">
  1941. <frame id="Frame_DialogBox" posn="0 0 70" hidden="1">
  1942. <quad posn="0 0 -1" sizen="320 180" halign="center" valign="center" style="Bgs1" substyle="BgDialogBlur" ScriptEvents="1"/>
  1943. <quad posn="0 17 1" sizen="126.5 8" halign="center" style="Bgs1InRace" substyle="BgGlow2"/>
  1944. <quad sizen="120 25" halign="center" valign="center" style="Bgs1InRace" substyle="BgWindow2"/>
  1945. <quad posn="0 -12 1" sizen="120 2" halign="center" style="Bgs1InRace" substyle="BgMetalBar"/>
  1946.  
  1947. <label posn="0 6.25" sizen="100 4" halign="center" valign="center2" textsize="2" textcolor="FFF" autonewline="1" id="Label_DialogMessage"/>
  1948. <label posn="-32 -4 1" style="CardButtonMedium" valign="center" halign="center" text="Remove" translate="1" id="Label_ButtonRemove" ScriptEvents="1"/>
  1949. <label posn="32 -4 1" style="CardButtonMedium" valign="center" halign="center" text="Cancel" translate="1" id="Label_ButtonCancel" ScriptEvents="1"/>
  1950. </frame>
  1951.  
  1952. <script><!--
  1953. /**
  1954. * EVIDENCE by domino54
  1955. * Buddy removal dialog box
  1956. */
  1957.  
  1958. #Include "TextLib" as TL
  1959.  
  1960. // ---------------------------------- //
  1961. // Main
  1962. // ---------------------------------- //
  1963. ***Main***
  1964. ***
  1965. // ---------------------------------- //
  1966. // Load interface elements
  1967. declare Frame_DialogBox <=> (Page.GetFirstChild("Frame_DialogBox") as CMlFrame);
  1968. declare Label_DialogMessage <=> (Page.GetFirstChild("Label_DialogMessage") as CMlLabel);
  1969.  
  1970. // ---------------------------------- //
  1971. // Script communication
  1972. declare DialogVisible for Page = False; ///< Visibility of the dialog box
  1973. declare DialogBuddyLogin for Page = ""; ///< Login of the buddy to remove
  1974. declare DialogBuddyName for Page = ""; ///< Name of the buddy to remove
  1975.  
  1976. /// Update variables
  1977. declare PrevDialogVisible = False;
  1978. ***
  1979.  
  1980. // ---------------------------------- //
  1981. // Yield
  1982. // ---------------------------------- //
  1983. ***Yield***
  1984. ***
  1985. // ---------------------------------- //
  1986. // Events management
  1987. foreach (Event in PendingEvents) {
  1988. // ---------------------------------- //
  1989. // Click on the interface element
  1990. if (Event.Type == CMlEvent::Type::MouseClick) {
  1991. // ---------------------------------- //
  1992. // Button remove
  1993. if (Event.ControlId == "Label_ButtonRemove") {
  1994. SendCustomEvent("BuddyRemoved", [DialogBuddyLogin]);
  1995. DialogVisible = False;
  1996. }
  1997. // ---------------------------------- //
  1998. // Button cancel
  1999. if (Event.ControlId == "Label_ButtonCancel") DialogVisible = False;
  2000. }
  2001. // ---------------------------------- //
  2002. // Menu navigation
  2003. if (Event.Type == CMlEvent::Type::MenuNavigation) {
  2004. // ---------------------------------- //
  2005. // Escape key
  2006. if (Event.MenuNavAction == CMlEvent::EMenuNavAction::Cancel) DialogVisible = False;
  2007. }
  2008. }
  2009.  
  2010. // ---------------------------------- //
  2011. // Update visibility
  2012. if (PrevDialogVisible != DialogVisible) {
  2013. PrevDialogVisible = DialogVisible;
  2014. EnableMenuNavigation(DialogVisible, True, Null, 10);
  2015.  
  2016. // ---------------------------------- //
  2017. // Set visibility
  2018. Frame_DialogBox.Visible = DialogVisible;
  2019.  
  2020. // ---------------------------------- //
  2021. // Play sound
  2022. declare TargetSound = CAudioManager::ELibSound::HideDialog;
  2023. if (DialogVisible) TargetSound = CAudioManager::ELibSound::ShowDialog;
  2024. Audio.PlaySoundEvent(TargetSound, 0, 0.);
  2025.  
  2026. // ---------------------------------- //
  2027. // Set buddy name
  2028. if (DialogVisible) Label_DialogMessage.SetText(TL::Compose(_("Are you sure you want to remove $<%1$> from your buddy list?"), DialogBuddyName));
  2029. }
  2030. ***
  2031.  
  2032. // ---------------------------------- //
  2033. // Main
  2034. // ---------------------------------- //
  2035. main() {
  2036. +++Main+++
  2037. while (True) {
  2038. yield;
  2039. +++Yield+++
  2040. }
  2041. }
  2042. --></script>
  2043. </manialink>""";
  2044. }
  2045.  
  2046. // ---------------------------------- //
  2047. /** Create window manialink
  2048. *
  2049. * @return The manialink
  2050. */
  2051. Text CreateManialinkWindow() {
  2052. return """
  2053. <?xml version="1.0" encoding="utf-8" standalone="yes"?>
  2054. <manialink version="2" name="Evidence:ChatWindow" background="0">
  2055. <stylesheet>
  2056. <style id="Quad_BuddySlotBtnJoin" image="{{{C_ImgBase}}}buddy-join.dds" imagefocus="{{{C_ImgBase}}}buddy-join-on.dds"/>
  2057. <style id="Quad_BuddySlotBtnAdd" image="{{{C_ImgBase}}}buddy-buddy-accept.dds" imagefocus="{{{C_ImgBase}}}buddy-buddy-accept-focus.dds"/>
  2058. <style id="Quad_BuddySlotBtnDeny" image="{{{C_ImgBase}}}buddy-buddy-deny.dds" imagefocus="{{{C_ImgBase}}}buddy-buddy-deny-focus.dds"/>
  2059. <style id="Quad_BuddySlotBtnPlus" image="{{{C_ImgBase}}}buddy-buddy-add.dds" imagefocus="{{{C_ImgBase}}}buddy-buddy-add-focus.dds"/>
  2060. <style id="Quad_BuddySlotBtnKick" image="{{{C_ImgBase}}}buddy-delete-off.dds" imagefocus="{{{C_ImgBase}}}buddy-delete-focus.dds"/>
  2061. <style id="Quad_BuddySlotBtnSearch" image="{{{C_ImgBase}}}buddy-search-go-off.dds" imagefocus="{{{C_ImgBase}}}buddy-search-go-focus.dds"/>
  2062.  
  2063. <style id="Quad_MessageSlotBtnCopy" image="{{{C_ImgBase}}}buddy-copy-serverlink.dds" imagefocus="{{{C_ImgBase}}}buddy-copy-serverlink-on.dds"/>
  2064. <style id="Quad_InvitePlayerButton" image="{{{C_ImgBase}}}buddy-buddy-add.dds" imagefocus="{{{C_ImgBase}}}buddy-buddy-add-focus.dds"/>
  2065. <style id="Quad_SearchModeClose" image="{{{C_ImgBase}}}buddy-search-clear-off.dds" imagefocus="{{{C_ImgBase}}}buddy-search-clear-focus.dds"/>
  2066.  
  2067. <style id="Label_MessengerBuddyName" style="TextValueSmallSm" textsize="2" textemboss="1" textcolor="FFF"/>
  2068. <style id="Quad_MessengerBuddyRemove" image="{{{C_ImgBase}}}buddy-delete-off.dds" imagefocus="{{{C_ImgBase}}}buddy-delete-focus.dds"/>
  2069. <style id="Quad_MessengerBuddyJoin" image="{{{C_ImgBase}}}buddy-join.dds" imagefocus="{{{C_ImgBase}}}buddy-join-on.dds"/>
  2070.  
  2071. <style class="Check" sizen="4 4" valign="center" style="Icons64x64_1" substyle="Check"/>
  2072. </stylesheet>
  2073.  
  2074. <!-- Model of the mode change buttons -->
  2075. <framemodel id="FrameModel_ModeButton">
  2076. <quad sizen="6 6" halign="center" valign="center" colorize="FFF" class="ModeButton focus-2 valid-0" id="Quad_ModeButtonIcon" ScriptEvents="1"/>
  2077. <frame id="Frame_ModeButtonNotice" posn="1.5 1.5 1" hidden="1">
  2078. <quad sizen="2.5 2.5" halign="center" valign="center" image="file://Media/Manialinks/Common/disc.dds" colorize="B00"/>
  2079. <label posn="0 0 1" halign="center" valign="center2" style="TextValueSmallSm" scale=".45" textcolor="FFF" id="Label_ModeButtonNotice"/>
  2080. </frame>
  2081. </framemodel>
  2082.  
  2083. <!-- Model of the buddies list slots -->
  2084. <framemodel id="FrameModel_BuddySlot">
  2085. <quad posn="0 -.25" sizen="44 7.5" bgcolor="000" opacity=".125" class="valid-1" id="Quad_BuddySlotBgCard" ScriptEvents="1"/>
  2086. <quad posn="0 -.25 .1" sizen="44 7.5" bgcolor="0AF" opacity="0" id="Quad_BuddySlotBlink"/>
  2087. <label posn="43.5 -7.5 .2" halign="right" valign="bottom" scale=".5" textemboss="0" textcolor="0AF" id="Label_BuddySlotNbNotice"/>
  2088.  
  2089. <!-- Presence lights -->
  2090. <quad posn="0 -.25 1" sizen="1 7.5" opacity=".6" id="Quad_BuddySlotPresence"/>
  2091. <quad posn="-2.3 2 .9" sizen="5.5 12" style="Bgs1InRace" substyle="BgButtonGlow" id="Quad_BuddySlotGlow" hidden="1"/>
  2092.  
  2093. <!-- Name and status -->
  2094. <label posn="2 -2.5 1" sizen="33.5 3" valign="center2" textsize="1" textcolor="FFF" id="Label_BuddySlotName"/>
  2095. <label posn="2 -5.75 1" sizen="48.5 3" scale=".75" valign="center2" textsize="1" textcolor="FFF" maxline="1" id="Label_BuddySlotStatus"/>
  2096. <label posn="43.5 -.5 1" halign="right" scale=".5" textcolor="0AF" text="E" id="Label_EvidenceUser" hidden="1"/>
  2097.  
  2098. <!-- Control buttons -->
  2099. <quad posn="41.5 -4 1" sizen="3.5 3.5" halign="center" valign="center" class="focus-1 valid-1" id="Quad_BuddySlotBtnJoin" ScriptEvents="1" hidden="1"/>
  2100. <quad posn="38.0 -4 1" sizen="3.5 3.5" halign="center" valign="center" class="focus-1 valid-1" id="Quad_BuddySlotBtnAdd" ScriptEvents="1" hidden="1"/>
  2101. <quad posn="41.5 -4 1" sizen="3.5 3.5" halign="center" valign="center" class="focus-1 valid-1" id="Quad_BuddySlotBtnDeny" ScriptEvents="1" hidden="1"/>
  2102. <quad posn="41.5 -4 1" sizen="3.5 3.5" halign="center" valign="center" class="focus-1 valid-1" id="Quad_BuddySlotBtnPlus" ScriptEvents="1" hidden="1"/>
  2103. <quad posn="41.5 -4 1" sizen="3.5 3.5" halign="center" valign="center" class="focus-1 valid-1" id="Quad_BuddySlotBtnKick" ScriptEvents="1" hidden="1"/>
  2104. <quad posn="38.0 -4 1" sizen="3.5 3.5" halign="center" valign="center" class="focus-1 valid-1" id="Quad_BuddySlotBtnMute" ScriptEvents="1" hidden="1"/>
  2105.  
  2106. <!-- Search mode buttons -->
  2107. <quad posn="41.5 -4 1" sizen="3.5 3.5" halign="center" valign="center" class="focus-1 valid-1" id="Quad_BuddySlotBtnSearch" ScriptEvents="1" hidden="1"/>
  2108. </framemodel>
  2109.  
  2110. <!-- Model of the the messages items -->
  2111. <framemodel id="FrameModel_MessageSlot">
  2112. <quad posn="0 -.25" sizen="124 7.5" bgcolor="000" opacity=".25" id="Quad_MessageSlotBgCard"/>
  2113. <quad posn="1 -2.5 1" sizen="2.25 2.25" valign="center" class="focus1 valid1" id="Quad_MessageSlotBtnCopy" ScriptEvents="1"/>
  2114.  
  2115. <label posn="4 -2.5 1" sizen="80 4" valign="center2" scale=".9" textsize="1" textcolor="FFF" text="Buddy name" id="Label_MessageSlotName"/>
  2116. <label posn="123 -2.5 1" halign="right" valign="center2" scale=".9" textsize="1" textcolor="FFF" opacity=".375" id="Label_MessageSlotTime"/>
  2117. <label posn="1 -4.25 1" sizen="122" textsize="1" textemboss="1" textcolor="FFF" autonewline="1" text="Message body" id="Label_MessageSlotBody"/>
  2118.  
  2119. <quad posn="1 -4.5 1" sizen="40 40" id="Quad_MessageSlotImage" keepratio="fit" hidden="1"/>
  2120. </framemodel>
  2121.  
  2122. <!-- Frame preventing going off screen while using VR devices -->
  2123. <frame clip="1" clipsizen="320 180">
  2124.  
  2125. <!-- Plugin window itself -->
  2126. <frame id="Frame_EvidencePlugin" posn="0 204">
  2127. <!-- Buddies list window -->
  2128. <frame id="Frame_BuddiesList" posn="-24">
  2129. <!-- Background images -->
  2130. <quad sizen="48.5 106" image="file://Media/Manialinks/Common/background2.png" ScriptEvents="1"/>
  2131. <quad posn="0 0 -1" sizen="48 104" style="Bgs1" substyle="BgDialogBlur" opacity="0"/>
  2132. <quad posn="-3 3 1" sizen="54 7.5" style="Bgs1InRace" substyle="BgGlow2"/>
  2133. <quad posn="0 -104.5 1" sizen="48 1" style="Bgs1InRace" substyle="BgMetalBar"/>
  2134.  
  2135. <!-- Mode buttons -->
  2136. <frame id="Frame_ModeButtons" posn="4.5 -7.75 1">
  2137. <frameinstance posn="0" modelid="FrameModel_ModeButton" id="Frame_ModeButtonBuddies"/>
  2138. <frameinstance posn="6" modelid="FrameModel_ModeButton" id="Frame_ModeButtonGroup"/>
  2139. <frameinstance posn="12" modelid="FrameModel_ModeButton" id="Frame_ModeButtonRequests"/>
  2140. <!-- <frameinstance posn="18" modelid="FrameModel_ModeButton" id="Frame_ModeButtonGlobal"/> -->
  2141. <frameinstance posn="33" modelid="FrameModel_ModeButton" id="Frame_ModeButtonMailbox"/>
  2142. <frameinstance posn="39" modelid="FrameModel_ModeButton" id="Frame_ModeButtonSettings"/>
  2143. </frame>
  2144.  
  2145. <!-- User own Slot -->
  2146. <frameinstance posn="2 -10.75 1" modelid="FrameModel_BuddySlot" id="Frame_LocalUserSlot"/>
  2147.  
  2148. <!-- Buddies Slots -->
  2149. <frame id="Frame_BuddiesSlots" posn="2 -18.75 1">
  2150. <frameinstance posn="0 0" modelid="FrameModel_BuddySlot" id="Frame_BuddySlot#0"/>
  2151. <frameinstance posn="0 -8" modelid="FrameModel_BuddySlot" id="Frame_BuddySlot#1"/>
  2152. <frameinstance posn="0 -16" modelid="FrameModel_BuddySlot" id="Frame_BuddySlot#2"/>
  2153. <frameinstance posn="0 -24" modelid="FrameModel_BuddySlot" id="Frame_BuddySlot#3"/>
  2154. <frameinstance posn="0 -32" modelid="FrameModel_BuddySlot" id="Frame_BuddySlot#4"/>
  2155. <frameinstance posn="0 -40" modelid="FrameModel_BuddySlot" id="Frame_BuddySlot#5"/>
  2156. <frameinstance posn="0 -48" modelid="FrameModel_BuddySlot" id="Frame_BuddySlot#6"/>
  2157. <frameinstance posn="0 -56" modelid="FrameModel_BuddySlot" id="Frame_BuddySlot#7"/>
  2158. <frameinstance posn="0 -64" modelid="FrameModel_BuddySlot" id="Frame_BuddySlot#8"/>
  2159. <frameinstance posn="0 -72" modelid="FrameModel_BuddySlot" id="Frame_BuddySlot#9"/>
  2160. </frame>
  2161.  
  2162. <!-- Buddy inviting -->
  2163. <frame posn="2 -10.75 1" id="Frame_BuddyInviteCard" hidden="1">
  2164. <quad posn="0 -.25" sizen="44 7.5" bgcolor="000" opacity=".125"/>
  2165. <label posn="1 -2.25 1" sizen="48.5 3" scale=".75" valign="center2" textsize="1" textcolor="FFF" text="Add player to buddies list:"/>
  2166. <entry posn="1 -5.5 1" sizen="38 3.5" valign="center2" textsize="1" textcolor="FFF" id="Entry_InvitePlayerInput" ScriptEvents="1"/>
  2167. <quad posn="41.5 -4 1" sizen="3.5 3.5" halign="center" valign="center" class="focus-1 valid-1" id="Quad_InvitePlayerButton" ScriptEvents="1" hidden="1"/>
  2168. </frame>
  2169.  
  2170. <!-- Buddy searching -->
  2171. <frame posn="2 -10.75 1" id="Frame_SearchModeCard" hidden="1">
  2172. <quad posn="0 -.25" sizen="44 7.5" bgcolor="000" opacity=".125"/>
  2173. <label posn="1 -2.25 1" sizen="48.5 3" scale=".75" valign="center2" textsize="1" textcolor="FFF" text="Search for a player:"/>
  2174. <entry posn="1 -5.5 1" sizen="38 3.5" valign="center2" textsize="1" textcolor="FFF" id="Entry_SearchModeInput" ScriptEvents="1"/>
  2175. <quad posn="41.5 -4 1" sizen="3.5 3.5" halign="center" valign="center" class="focus-1 valid-1" id="Quad_SearchModeClose" ScriptEvents="1"/>
  2176. </frame>
  2177.  
  2178. <!-- Page switch -->
  2179. <frame id="Frame_PageSwitch" posn="24 -101.5 1">
  2180. <quad posn="-8 0 1" sizen="5 5" halign="center" valign="center" style="Icons64x64_1" substyle="ArrowPrev" id="Quad_PrevBuddiesPage" ScriptEvents="1"/>
  2181. <label halign="center" valign="center2" style="TextValueSmallSm" textsize="1" id="Label_PageSwitchCounter"/>
  2182. <quad posn="8 0 1" sizen="5 5" halign="center" valign="center" style="Icons64x64_1" substyle="ArrowNext" id="Quad_NextBuddiesPage" ScriptEvents="1"/>
  2183. <quad posn="-8" sizen="5 5" halign="center" valign="center" style="Icons64x64_1" substyle="ArrowDisabled"/>
  2184. <quad posn="8" sizen="5 5" halign="center" valign="center" style="Icons64x64_1" substyle="ArrowDisabled"/>
  2185. </frame>
  2186.  
  2187. <!-- Settings tab -->
  2188. <frame id="Frame_SettingsMenu" posn="2 -14 1" hidden="1">
  2189. <label posn="0 0" valign="center2" style="TextButtonNav" textsize="1" textcolor="FFF" text="Settings" translate="1"/>
  2190.  
  2191. <label posn="0 -5" valign="center2" textsize="1" textcolor="FFF" text="Status with current activity"/>
  2192. <quad posn="40.5 -5" class="Check" id="Quad_CheckUseDynamicStatus" ScriptEvents="1"/>
  2193.  
  2194. <label posn="0 -10" valign="center2" textsize="1" textcolor="FFF" text="Automatically format links"/>
  2195. <quad posn="40.5 -10" class="Check" id="Quad_CheckUseLinksPhrasing" ScriptEvents="1"/>
  2196.  
  2197. <label posn="0 -15" valign="center2" textsize="1" textcolor="FFF" text="Group password"/>
  2198. <entry posn="44 -15" sizen="16 3.5" halign="right" valign="center2" textsize="1" textemboss="1" textcolor="FFF" textformat="newpassword" id="Entry_GroupChatPassword" ScriptEvents="1"/>
  2199.  
  2200. <label posn="0 -20" valign="center2" textsize="1" textcolor="FFF" text="Enable Global Chat"/>
  2201. <quad posn="40.5 -20" class="Check" id="Quad_CheckEnableGlobalChat" ScriptEvents="1"/>
  2202.  
  2203. <label posn="0 -25" valign="center2" textsize="1" textcolor="FFF" text="Notice on new message"/>
  2204. <quad posn="40.5 -25" class="Check" id="Quad_CheckNoticeOnNewMessage" ScriptEvents="1"/>
  2205.  
  2206. <label posn="0 -30" valign="center2" textsize="1" textcolor="FFF" text="Notice on new connection"/>
  2207. <quad posn="40.5 -30" class="Check" id="Quad_CheckNoticeOnConnection" ScriptEvents="1"/>
  2208. </frame>
  2209.  
  2210. <label
  2211. posn="24 -75.5 1" halign="center" style="CardButtonMediumL" text="Download update" id="Label_ButtonUpdate" hidden="1"
  2212. url="https://raw.githubusercontent.com/domino54/title-packs/master/Plugins/Evidence.Script.txt"
  2213. />
  2214.  
  2215. <textedit posn="2 -84.5 1" sizen="44 18" textsize="1" textcolor="FFF" id="TextEdit_PasteBin"/>
  2216. </frame>
  2217.  
  2218. <!-- Messaging window -->
  2219. <frame id="Frame_MessengerWindow" posn="164">
  2220. <!-- Background images -->
  2221. <quad posn="-.25" sizen="137 106" image="file://Media/Manialinks/Common/background3.png" ScriptEvents="1"/>
  2222. <quad posn="0 0 -1" sizen="137 104" style="Bgs1" substyle="BgDialogBlur" opacity="0"/>
  2223. <quad posn="-3 3 1" sizen="142 7.5" style="Bgs1InRace" substyle="BgGlow2"/>
  2224. <quad posn="0 -104.5 1" sizen="136 1" style="Bgs1InRace" substyle="BgMetalBar"/>
  2225.  
  2226. <!-- User information -->
  2227. <frame id="Frame_MessengerBuddyInfo" posn="2 .25 1">
  2228. <label posn="0 -4.5 1" sizen="60 4" valign="center2" id="Label_MessengerBuddyName"/>
  2229. <quad posn="-.9 -8.5 1" sizen="4.5 4.5" valign="center" style="Icons64x64_1" substyle="ClipPause" id="Quad_MessengerBuddyPresence" ScriptEvents="1"/>
  2230. <label posn="4 -8.5 1" sizen="60 3" valign="center2" textsize="1" textemboss="1" textcolor="FC0" maxline="1" id="Label_MessengerBuddyStatus"/>
  2231. <entry posn="4 -8.5 1" sizen="60 3.5" valign="center2" textsize="1" textemboss="1" textcolor="FC0" maxline="1" id="Entry_MessengerStatusInput" ScriptEvents="1" hidden="1"/>
  2232. </frame>
  2233.  
  2234. <!-- User actions -->
  2235. <frame id="Frame_MessengerBuddyActions" posn="134.5 -6.1 1">
  2236. <!-- Server name and join button -->
  2237. <quad posn="-6 0 1" sizen="6 6" valign="center" class="focus-1 valid-1" id="Quad_MessengerBuddyJoin" ScriptEvents="1" hidden="1"/>
  2238. <quad posn="-6" sizen="6 6" valign="center" image="{{{C_ImgBase}}}buddy-join-off.dds"/>
  2239. <label posn="-6.5 1.75" sizen="60 3" halign="right" valign="center2" textsize="1" textcolor="FFF" textemboss="1" id="Label_MessengerBuddyServer"/>
  2240.  
  2241. <!-- Action buttons -->
  2242. <quad posn="-15 -1.75" sizen="4 4" valign="center" class="focus-1 valid-1" id="Quad_MessengerBuddyRemove" ScriptEvents="1"/>
  2243. <quad posn="-10.5 -1.75" sizen="4 4" valign="center" style="Icons64x64_1" substyle="Outbox" id="Quad_MessengerBuddyMail" ScriptEvents="1"/>
  2244.  
  2245. <!-- Buddy login -->
  2246. <label posn="-15.5 -1.75" sizen="30 3" halign="right" valign="center2" textsize="1" textemboss="1" textcolor="AAA" id="Label_MessengerBuddyLogin"/>
  2247. </frame>
  2248.  
  2249. <!-- Messages models -->
  2250. <frame id="Frame_MessagesSlots" posn="2 -98.75 1" clip="1" clipposn="66 42.75" clipsizen="132 87.5">
  2251. <frameinstance modelid="FrameModel_MessageSlot" id="Frame_MessageSlot#0" hidden="1"/>
  2252. <frameinstance modelid="FrameModel_MessageSlot" id="Frame_MessageSlot#1" hidden="1"/>
  2253. <frameinstance modelid="FrameModel_MessageSlot" id="Frame_MessageSlot#2" hidden="1"/>
  2254. <frameinstance modelid="FrameModel_MessageSlot" id="Frame_MessageSlot#3" hidden="1"/>
  2255. <frameinstance modelid="FrameModel_MessageSlot" id="Frame_MessageSlot#4" hidden="1"/>
  2256. <frameinstance modelid="FrameModel_MessageSlot" id="Frame_MessageSlot#5" hidden="1"/>
  2257. <frameinstance modelid="FrameModel_MessageSlot" id="Frame_MessageSlot#6" hidden="1"/>
  2258. <frameinstance modelid="FrameModel_MessageSlot" id="Frame_MessageSlot#7" hidden="1"/>
  2259. <frameinstance modelid="FrameModel_MessageSlot" id="Frame_MessageSlot#8" hidden="1"/>
  2260. <frameinstance modelid="FrameModel_MessageSlot" id="Frame_MessageSlot#9" hidden="1"/>
  2261. <frameinstance modelid="FrameModel_MessageSlot" id="Frame_MessageSlot#10" hidden="1"/>
  2262. <quad posn="6 2.25" sizen="3.5 3.5" halign="center" valign="center" style="Icons64x64_1" substyle="Check" styleselected="1" id="Quad_SeenMessage" hidden="1"/>
  2263. </frame>
  2264.  
  2265. <frame id="Frame_BottomControls" posn="0 -101.5 1">
  2266. <!-- Message entry -->
  2267. <entry posn="2" sizen="122 4" valign="center2" textsize="1" textcolor="FFF" id="Entry_MessageSubmit" ScriptEvents="1"/>
  2268.  
  2269. <!-- Control buttons -->
  2270. <quad posn="125 0 1" sizen="5 5" valign="center" style="Icons64x64_1" substyle="ArrowUp" id="Quad_MessagesScrollUp" ScriptEvents="1" hidden="1"/>
  2271. <quad posn="130 0 1" sizen="5 5" valign="center" style="Icons64x64_1" substyle="ArrowDown" id="Quad_MessagesScrollDown" ScriptEvents="1" hidden="1"/>
  2272. <quad posn="125" sizen="5 5" valign="center" style="Icons64x64_1" substyle="ArrowDisabled"/>
  2273. <quad posn="130" sizen="5 5" valign="center" style="Icons64x64_1" substyle="ArrowDisabled"/>
  2274. </frame>
  2275. </frame>
  2276. </frame>
  2277. </frame>
  2278. <script><!--
  2279. /**
  2280. * EVIDENCE by domino54
  2281. * Interface manialink
  2282. */
  2283.  
  2284. #Include "MathLib" as ML
  2285. #Include "TextLib" as TL
  2286.  
  2287. #Const C_WidgetAnimDuration 200. ///< Duration of the show/hide animations
  2288. #Const C_EvidenceFramePosY 84. ///< Position of the Evidence window when visible
  2289. #Const C_EvidenceFramePosHide 120. ///< Position offset when Evidence window is hidden
  2290. #Const C_MessengerFramePosX 24. ///< Position of the Messenger window when visible
  2291. #Const C_MessengerFramePosHide 140. ///< Position offset when Messenger window is hidden
  2292. #Const C_MaxMessagesInHistory 32 ///< Maximum amount of messages stored per conversation
  2293.  
  2294. /// Update checker
  2295. #Const C_UpdateCheckInterval 1800000
  2296. #Const C_UpdateCheckAddress "https://raw.githubusercontent.com/domino54/title-packs/master/evidence-version.txt"
  2297.  
  2298. /// Available modes in the Evidence widget (with exception of Mailbox)
  2299. #Const C_ChatWidgetModes ["Buddies", "Group", "Requests", /* "Global", */ "Mailbox", "Settings"]
  2300.  
  2301. /// Default statuses for users presences
  2302. #Const C_UserPresenceStatus [_("Offline"), _("Available"), _("Away"), _("Busy"), _("Available"), _("Away")]
  2303.  
  2304. /// Global Chat connection status
  2305. #Const C_GlobalChatConnectionStatus [0 => _("Offline"), 1 => _("Connected"), 3 => _("|Broadcasting|Connecting...")]
  2306.  
  2307. /// Colors of the users presences
  2308. #Const C_UserPresenceColors [
  2309. <.2, .4, .5>, ///< Offline
  2310. <.3, 1., .3>, ///< Available
  2311. <1., 1., 0.>, ///< Away
  2312. <1., .3, .3>, ///< Busy
  2313. <.3, 1., .3>, ///< Available Evidence (former Wanna talk!)
  2314. <1., 1., 0.> ///< Away Evidence (former Snooze)
  2315. ]
  2316.  
  2317. /// Opacity of the mode buttons
  2318. #Const C_ModeButtonsOpacity [
  2319. False => [ ///< Disabled
  2320. False => .25, ///< Off
  2321. True => .625 ///< Focus
  2322. ],
  2323. True => [ ///< Selected
  2324. False => .875, ///< Off
  2325. True => 1. ///< Focus
  2326. ]
  2327. ]
  2328.  
  2329. /// Colors of the buddies cards
  2330. #Const C_BuddySlotBgColors [
  2331. False => [ ///< Disabled
  2332. False => <0., 0., 0.>, ///< Off
  2333. True => <.3, .3, .3> ///< Focus
  2334. ],
  2335. True => [ ///< Selected
  2336. False => <.6, .6, .6>, ///< Off
  2337. True => <.9, .9, .9> ///< Focus
  2338. ]
  2339. ]
  2340.  
  2341. /// Mute button images
  2342. #Const C_SlotMuteButtonImages [
  2343. False => [ ///< Not muted
  2344. False => "{{{C_ImgBase}}}buddy-ally-on.dds",
  2345. True => "{{{C_ImgBase}}}buddy-ally-on-focus.dds"
  2346. ],
  2347. True => [ ///< Muted
  2348. False => "{{{C_ImgBase}}}buddy-ally-off.dds",
  2349. True => "{{{C_ImgBase}}}buddy-ally-focus.dds"
  2350. ]
  2351. ]
  2352.  
  2353. /// URLs of the mode buttons images
  2354. #Const C_ModeButtonsImagesURLs [
  2355. "Buddies" => "http://i.imgur.com/zWESBiR.png",
  2356. "Group" => "http://i.imgur.com/qFKByDl.png",
  2357. "Requests" => "http://i.imgur.com/TIAbhB7.png",
  2358. "Global" => "http://i.imgur.com/MXfIHAs.png",
  2359. "Mailbox" => "http://i.imgur.com/ULIzuFa.png",
  2360. "Settings" => "http://i.imgur.com/6ydip4k.png"
  2361. ]
  2362.  
  2363. // ---------------------------------- //
  2364. // Main
  2365. // ---------------------------------- //
  2366. ***Main***
  2367. ***
  2368. // ---------------------------------- //
  2369. // Load interface elements
  2370. declare Frame_EvidencePlugin <=> (Page.GetFirstChild("Frame_EvidencePlugin") as CMlFrame);
  2371. declare Frame_MessengerWindow <=> (Page.GetFirstChild("Frame_MessengerWindow") as CMlFrame);
  2372.  
  2373. /// Local user Slot
  2374. declare Frame_LocalUserSlot <=> (Page.GetFirstChild("Frame_LocalUserSlot") as CMlFrame);
  2375. declare Quad_LocalUserBgCard <=> (Frame_LocalUserSlot.GetFirstChild("Quad_BuddySlotBgCard") as CMlQuad);
  2376. declare Label_LocalUserBgName <=> (Frame_LocalUserSlot.GetFirstChild("Label_BuddySlotName") as CMlLabel);
  2377. declare Label_LocalUserStatus <=> (Frame_LocalUserSlot.GetFirstChild("Label_BuddySlotStatus") as CMlLabel);
  2378. declare Quad_LocalUserPresence <=> (Frame_LocalUserSlot.GetFirstChild("Quad_BuddySlotPresence") as CMlQuad);
  2379. declare Quad_LocalUserGlow <=> (Frame_LocalUserSlot.GetFirstChild("Quad_BuddySlotGlow") as CMlQuad);
  2380. declare Quad_LocalUserSearch <=> (Frame_LocalUserSlot.GetFirstChild("Quad_BuddySlotBtnSearch") as CMlQuad);
  2381.  
  2382. /// Player inviting
  2383. declare Frame_BuddyInviteCard <=> (Page.GetFirstChild("Frame_BuddyInviteCard") as CMlFrame);
  2384. declare Entry_InvitePlayerInput <=> (Page.GetFirstChild("Entry_InvitePlayerInput") as CMlEntry);
  2385. declare Quad_InvitePlayerButton <=> (Page.GetFirstChild("Quad_InvitePlayerButton") as CMlQuad);
  2386.  
  2387. /// Player search
  2388. declare Frame_SearchModeCard <=> (Page.GetFirstChild("Frame_SearchModeCard") as CMlFrame);
  2389. declare Entry_SearchModeInput <=> (Page.GetFirstChild("Entry_SearchModeInput") as CMlEntry);
  2390.  
  2391. /// Buddies list page switch
  2392. declare Frame_PageSwitch <=> (Page.GetFirstChild("Frame_PageSwitch") as CMlFrame);
  2393. declare Quad_PrevBuddiesPage <=> (Page.GetFirstChild("Quad_PrevBuddiesPage") as CMlQuad);
  2394. declare Quad_NextBuddiesPage <=> (Page.GetFirstChild("Quad_NextBuddiesPage") as CMlQuad);
  2395. declare Label_PageSwitchCounter <=> (Page.GetFirstChild("Label_PageSwitchCounter") as CMlLabel);
  2396.  
  2397. /// Messenger scrolling
  2398. declare Quad_MessagesScrollUp <=> (Page.GetFirstChild("Quad_MessagesScrollUp") as CMlQuad);
  2399. declare Quad_MessagesScrollDown <=> (Page.GetFirstChild("Quad_MessagesScrollDown") as CMlQuad);
  2400.  
  2401. /// Messanger buddy information
  2402. declare Label_MessengerBuddyName <=> (Page.GetFirstChild("Label_MessengerBuddyName") as CMlLabel);
  2403. declare Quad_MessengerBuddyPresence <=> (Page.GetFirstChild("Quad_MessengerBuddyPresence") as CMlQuad);
  2404. declare Label_MessengerBuddyStatus <=> (Page.GetFirstChild("Label_MessengerBuddyStatus") as CMlLabel);
  2405. declare Entry_MessengerStatusInput <=> (Page.GetFirstChild("Entry_MessengerStatusInput") as CMlEntry);
  2406.  
  2407. /// Messenger buddy actions
  2408. declare Frame_MessengerBuddyActions <=> (Page.GetFirstChild("Frame_MessengerBuddyActions") as CMlFrame);
  2409. declare Label_MessengerBuddyLogin <=> (Page.GetFirstChild("Label_MessengerBuddyLogin") as CMlLabel);
  2410. declare Label_MessengerBuddyServer <=> (Page.GetFirstChild("Label_MessengerBuddyServer") as CMlLabel);
  2411. declare Quad_MessengerBuddyJoin <=> (Page.GetFirstChild("Quad_MessengerBuddyJoin") as CMlQuad);
  2412. declare Quad_MessengerBuddyMail <=> (Page.GetFirstChild("Quad_MessengerBuddyMail") as CMlQuad);
  2413. declare Quad_MessengerBuddyRemove <=> (Page.GetFirstChild("Quad_MessengerBuddyRemove") as CMlQuad);
  2414. declare Quad_SeenMessage <=> (Page.GetFirstChild("Quad_SeenMessage") as CMlQuad);
  2415.  
  2416. /// Settings tab
  2417. declare Frame_SettingsMenu <=> (Page.GetFirstChild("Frame_SettingsMenu") as CMlFrame);
  2418. declare Quad_CheckUseDynamicStatus <=> (Page.GetFirstChild("Quad_CheckUseDynamicStatus") as CMlQuad);
  2419. declare Quad_CheckUseLinksPhrasing <=> (Page.GetFirstChild("Quad_CheckUseLinksPhrasing") as CMlQuad);
  2420. declare Quad_CheckEnableGroupChat <=> (Page.GetFirstChild("Quad_CheckEnableGroupChat") as CMlQuad);
  2421. declare Entry_GroupChatPassword <=> (Page.GetFirstChild("Entry_GroupChatPassword") as CMlEntry);
  2422. declare Quad_CheckEnableGlobalChat <=> (Page.GetFirstChild("Quad_CheckEnableGlobalChat") as CMlQuad);
  2423. declare Quad_CheckNoticeOnNewMessage <=> (Page.GetFirstChild("Quad_CheckNoticeOnNewMessage") as CMlQuad);
  2424. declare Quad_CheckNoticeOnConnection <=> (Page.GetFirstChild("Quad_CheckNoticeOnConnection") as CMlQuad);
  2425. declare Label_ButtonUpdate <=> (Page.GetFirstChild("Label_ButtonUpdate") as CMlLabel);
  2426. declare TextEdit_PasteBin <=> (Page.GetFirstChild("TextEdit_PasteBin") as CMlTextEdit);
  2427.  
  2428. /// Mode buttons
  2429. declare CMlFrame[Text] Frame_ModeButtons;
  2430. foreach (Mode in C_ChatWidgetModes) {
  2431. Frame_ModeButtons[Mode] <=> (Page.GetFirstChild("Frame_ModeButton"^Mode) as CMlFrame);
  2432. declare Quad_ModeButtonIcon <=> (Frame_ModeButtons[Mode].GetFirstChild("Quad_ModeButtonIcon") as CMlQuad);
  2433. Quad_ModeButtonIcon.ImageUrl = C_ModeButtonsImagesURLs[Mode];
  2434. Quad_ModeButtonIcon.DataAttributeSet("mode", Mode);
  2435. }
  2436.  
  2437. /// Buddies list slots
  2438. declare CMlFrame[] Frame_BuddiesSlots;
  2439. for (I, 0, 9) Frame_BuddiesSlots.add((Page.GetFirstChild("Frame_BuddySlot#"^I) as CMlFrame));
  2440.  
  2441. /// Messages slots
  2442. declare CMlFrame[] Frame_MessagesSlots;
  2443. for (I, 0, 10) Frame_MessagesSlots.add((Page.GetFirstChild("Frame_MessageSlot#"^I) as CMlFrame));
  2444.  
  2445. // ---------------------------------- //
  2446. // Persistent settings
  2447. declare persistent Text[][Text] Persistent_Evidence_ChatHistoryBody for Page;
  2448. declare persistent Text[][Text] Persistent_Evidence_ChatHistorySender for Page;
  2449. declare persistent Text[][Text] Persistent_Evidence_ChatHistoryDate for Page;
  2450. declare persistent Integer[Text] Persistent_Evidence_NbUnreadMessages for Page;
  2451. declare persistent Integer Persistent_Evidence_UserTargetPresenceId for Page = 4;
  2452. declare persistent Text Persistent_Evidence_UserCustomStatus for Page;
  2453. declare persistent Text Persistent_Evidence_PasteBin for Page;
  2454. declare persistent Text[] Persistent_Evidence_UsersSeenMessages for Page;
  2455.  
  2456. declare persistent Boolean Persistent_Evidence_UseDynamicStatus for Page = True;
  2457. declare persistent Boolean Persistent_Evidence_UseLinksPhrasing for Page = True;
  2458. declare persistent Text Persistent_Evidence_GroupChatPassword for Page;
  2459. declare persistent Boolean Persistent_Evidence_EnableGlobalChat for Page = True;
  2460. declare persistent Boolean Persistent_Evidence_NoticeOnNewMessage for Page = True;
  2461. declare persistent Boolean Persistent_Evidence_NoticeOnConnection for Page = True;
  2462.  
  2463. if (Persistent_Evidence_UserTargetPresenceId < 3) Persistent_Evidence_UserTargetPresenceId = 4;
  2464.  
  2465. // ---------------------------------- //
  2466. // Plugin script communication
  2467. declare NewReceivedMessages for Page = Text[][]; ///< New messages to proceed
  2468. declare ChatWidgetIsOpen for Page = False; ///< Current chat state
  2469. declare MessengerIsOpen for Page = False; ///< Current messenger state
  2470. declare CurrentWidgetMode for Page = ""; ///< Active widget mode
  2471. declare SelectedConversation for Page = ""; ///< Login of selected buddy for private conversation
  2472. declare LegacyMailsAmount for Page = 0; ///< Amount of messages in classic mailbox
  2473. declare CurrentPluginPresenceId for Page = 4; ///< Current presence Id of the user
  2474. declare CurrentPluginStatusText for Page = ""; ///< Currently displayed status of the user
  2475. declare ManialinkTargetPresence for Page = 4; ///< Requested user presence Id
  2476. declare ManialinkCustomStatus for Page = ""; ///< Custom status specified by user
  2477. declare TotalNbUnreadMessages for Page = 0; ///< Total amount of unread messages
  2478. declare FlashTaskbar for Page = False; ///< Force game to blink taskbar icon
  2479. declare UsersThatSeenMessage for Page = Text[]; ///< Users that just seen message
  2480.  
  2481. /// Settings
  2482. declare UseDynamicStatus for Page = False; ///< User context status setting
  2483. declare UseLinksPhrasing for Page = False; ///< User automatic link formatting setting
  2484. declare GroupChatPassword for Page = ""; ///< Group Chat password
  2485. declare EnableGlobalChat for Page = False; ///< Global Chat usage setting
  2486. declare NoticeOnNewMessage for Page = False; ///< Display notices on new messages
  2487. declare NoticeOnConnection for Page = False; ///< Display notice on buddy connection
  2488.  
  2489. declare GlobalChat_ConnectionStatus for Page = 0;
  2490.  
  2491. /// Update variables
  2492. declare PrevChatWidgetIsOpen = False;
  2493. declare PrevMessengerIsOpen = False;
  2494. declare PrevWidgetMode = "!";
  2495. declare PrevSelectedConversation = "!";
  2496. declare PrevLegacyMailsAmount = -1;
  2497. declare PrevPluginPresenceId = 0;
  2498. declare PrevEntryStatusValue = "!";
  2499. declare PrevGlobalChatConnectionStatus = -1;
  2500.  
  2501. // ---------------------------------- //
  2502. // Plugin buddies data
  2503. declare Text[] BuddiesList_Online for Page; ///< Buddies currently being connected
  2504. declare Text[] BuddiesList_Offline for Page; ///< Buddies currently being offline
  2505. declare Text[] BuddiesList_RequestFrom for Page; ///< Incoming buddies invitations
  2506. declare Text[] BuddiesList_RequestTo for Page; ///< Sent buddies invitations
  2507. declare Text[] BuddiesList_OnServer for Page; ///< Players on current server
  2508. declare Text[] BuddiesList_InGroup for Page; ///< Buddies in the group
  2509. declare Text[] BuddiesList_GlobalList for Page; ///< Buddies available on the global chat
  2510. declare Text[] BuddiesList_MutedUsers for Page; ///< Buddies muted
  2511. declare Text[] BuddiesList_SearchList for Page; ///< List of buddies found in search
  2512. declare Text[] BuddiesList_Evidence for Page; ///< Buddies using Evidence chat
  2513.  
  2514. declare Text[] BuddiesList_ListOnTop for Page; ///< Buddies to be listed on top
  2515. declare Text[] BuddiesList_SortedList for Page; ///< Sorted list of all buddies (online and offline)
  2516. declare Text[] BuddiesList_RequestList for Page; ///< Sorted list of all requests
  2517.  
  2518. declare Text[Text] BuddiesName for Page; ///< Names of the buddies
  2519. declare Integer[Text] BuddiesPresenceId for Page; ///< Presence Ids of the buddies
  2520. declare Text[Text] BuddiesStatus for Page; ///< Statuses of the buddies
  2521. declare Text[Text] BuddiesServerLogin for Page; ///< Login of the servers buddies are on
  2522. declare Boolean[Text] BuddiesIsMuted for Page; ///< True if buddy is muted in Group Chat
  2523. declare Text[Text] BuddiesJoinLink for Page; ///< Links to join buddies servers
  2524.  
  2525. /// Global chat data
  2526. declare Integer[Text] GlobalChat_BuddiesPresenceId for Page;
  2527. declare Text[Text] GlobalChat_BuddiesName for Page;
  2528. declare Text[Text] GlobalChat_BuddiesStatus for Page;
  2529.  
  2530. declare Text[Text] ServersName for Page; ///< Names of the buddies servers
  2531.  
  2532. /// Update variables
  2533. declare PrevBuddiesOnline = -1;
  2534. declare PrevBuddiesOffline = -1;
  2535. declare PrevBuddiesRequestFrom = -1;
  2536. declare PrevBuddiesRequestTo = -1;
  2537. declare PrevBuddiesOnServer = -1;
  2538. declare PrevBuddiesInGroup = -1;
  2539. declare PrevBuddiesGlobalList = -1;
  2540. declare PrevBuddiesMutedUsers = -1;
  2541.  
  2542. declare Text[Text] PrevBuddiesName;
  2543. declare Integer[Text] PrevBuddiesPresenceId;
  2544. declare Text[Text] PrevBuddiesStatus;
  2545. declare Text[Text] PrevBuddiesServerLogin;
  2546. declare Text[Text] PrevGlobalBuddiesName;
  2547. declare Integer[Text] PrevGlobalBuddiesPresenceId;
  2548.  
  2549. // ---------------------------------- //
  2550. // Variables
  2551. declare SortBuddiesList = True; ///< Forces manialink to sort Buddies tab
  2552. declare SortRequestsList = True; ///< Forces manialink to sort Requests tab
  2553. declare UpdateBuddiesList = True; ///< Forces manialink to build buddies list
  2554. declare HighlightModeButton = ""; ///< ID of the mode button to highlight
  2555. declare UpdateModeButtons = True; ///< Update opacity of the mode buttons
  2556. declare HighlightBuddySlot = NullId; ///< ID of the buddy slot to highlight
  2557. declare UpdateSlotsBgSlots = True; ///< Update backgrounds of the buddies slots
  2558. declare UpdateMessagesSlots = 2; ///< Amount of pending messages slots updates
  2559. declare UpdateMessengerInfo = True; ///< Update name and status of the conversation
  2560. declare MessagesOffset = Integer[Text]; ///< Messages scrolling option
  2561. declare NextUpdateCheckout = 0; ///< Time of the next update check
  2562. declare PluginIsOutdated = False;
  2563. declare UpdateCheckRequest = CHttpRequest;
  2564. declare PrevEntrySearchValue = "";
  2565. declare GameIsInFocus = False;
  2566.  
  2567. declare PrevGameIsInFocus = False;
  2568.  
  2569. /// Current and total page number on tabs
  2570. declare Integer[Text] CurrentPage;
  2571. declare Integer[Text] PagesCount;
  2572. foreach (Mode in C_ChatWidgetModes) {
  2573. CurrentPage[Mode] = 1;
  2574. PagesCount[Mode] = 1;
  2575. }
  2576. CurrentPage["Search"] = 1;
  2577. PagesCount["Search"] = 1;
  2578.  
  2579. /// Unread messages amount
  2580. declare UnreadMessagesGroups = ["Buddies", "Group", "Global"];
  2581. declare Integer[Text] NbUnreadMessages;
  2582. declare Integer[Text] PrevNbUnreadMessages;
  2583. foreach (Group in UnreadMessagesGroups) {
  2584. NbUnreadMessages[Group] = 0;
  2585. PrevNbUnreadMessages[Group] = 0;
  2586. }
  2587.  
  2588. // ---------------------------------- //
  2589. // Initialize variables
  2590. ManialinkTargetPresence = Persistent_Evidence_UserTargetPresenceId;
  2591. Entry_MessengerStatusInput.Value = Persistent_Evidence_UserCustomStatus;
  2592. Entry_GroupChatPassword.Value = Persistent_Evidence_GroupChatPassword;
  2593. TextEdit_PasteBin.Value = Persistent_Evidence_PasteBin;
  2594. Quad_LocalUserBgCard.DataAttributeSet("login", LocalUser.Login);
  2595. CurrentWidgetMode = "Buddies";
  2596.  
  2597. // ---------------------------------- //
  2598. // Convert deprecated history onto new one
  2599. declare persistent Text[][][Text] Persistent_Evidence_ChatHistory for Page;
  2600. if (Persistent_Evidence_ChatHistory.count > 0) {
  2601. foreach (ConversationLogin => Messages in Persistent_Evidence_ChatHistory) {
  2602. if (!Persistent_Evidence_ChatHistorySender.existskey(ConversationLogin))
  2603. Persistent_Evidence_ChatHistorySender[ConversationLogin] = Text[];
  2604.  
  2605. if (!Persistent_Evidence_ChatHistoryBody.existskey(ConversationLogin))
  2606. Persistent_Evidence_ChatHistoryBody[ConversationLogin] = Text[];
  2607.  
  2608. if (!Persistent_Evidence_ChatHistoryDate.existskey(ConversationLogin))
  2609. Persistent_Evidence_ChatHistoryDate[ConversationLogin] = Text[];
  2610.  
  2611. foreach (MessageData in Messages) {
  2612. Persistent_Evidence_ChatHistorySender[ConversationLogin].add(MessageData[0]);
  2613. Persistent_Evidence_ChatHistoryBody[ConversationLogin].add(MessageData[1]);
  2614. Persistent_Evidence_ChatHistoryDate[ConversationLogin].add(MessageData[2]);
  2615. }
  2616. }
  2617. Persistent_Evidence_ChatHistory.clear();
  2618. }
  2619. ***
  2620.  
  2621. // ---------------------------------- //
  2622. // Yield
  2623. // ---------------------------------- //
  2624. ***Yield***
  2625. ***
  2626. // ---------------------------------- //
  2627. // Manage events
  2628. foreach (Event in PendingEvents) {
  2629. // ---------------------------------- //
  2630. // Keyboard button press
  2631. if (Event.Type == CMlEvent::Type::KeyPress) {
  2632. // ---------------------------------- //
  2633. // Change Evidence visibility
  2634. if (Event.KeyName == "F7") ChatWidgetIsOpen = !ChatWidgetIsOpen;
  2635. }
  2636. // ---------------------------------- //
  2637. // Mouse click
  2638. else if (Event.Type == CMlEvent::Type::MouseClick) {
  2639. // ---------------------------------- //
  2640. // Change current widget mode
  2641. if (Event.ControlId == "Quad_ModeButtonIcon") {
  2642. declare NewMode = Event.Control.DataAttributeGet("mode");
  2643. if (NewMode == "Mailbox") OpenLink("#mailto=", ::LinkType::ManialinkBrowser);
  2644. else CurrentWidgetMode = NewMode;
  2645. }
  2646. // ---------------------------------- //
  2647. // Change current widget mode
  2648. else if (Event.ControlId == "Quad_BuddySlotBgCard") {
  2649. // Go to the Group mode
  2650. if (Event.Control == Quad_LocalUserBgCard) CurrentWidgetMode = "Group";
  2651.  
  2652. // ---------------------------------- //
  2653. // Select buddy
  2654. else if (CurrentWidgetMode != "Global") {
  2655. // ---------------------------------- //
  2656. // Open buddy conversation
  2657. declare BuddyLogin = Event.Control.DataAttributeGet("login");
  2658. if (SelectedConversation != BuddyLogin) {
  2659. SelectedConversation = BuddyLogin;
  2660. if (CurrentWidgetMode == "Group") CurrentWidgetMode = "Buddies";
  2661. UpdateMessagesSlots = 2;
  2662.  
  2663. // ---------------------------------- //
  2664. // Close search mode
  2665. if (Frame_SearchModeCard.Visible) {
  2666. Frame_SearchModeCard.Hide();
  2667. Entry_SearchModeInput.Value = "";
  2668. }
  2669. }
  2670. // ---------------------------------- //
  2671. // Hide messenger
  2672. else SelectedConversation = "";
  2673. }
  2674.  
  2675. UpdateSlotsBgSlots = True;
  2676. }
  2677. // ---------------------------------- //
  2678. // Buddies list previous page button
  2679. else if (Event.ControlId == "Quad_PrevBuddiesPage") {
  2680. declare Mode = CurrentWidgetMode;
  2681. if (Frame_SearchModeCard.Visible) Mode = "Search";
  2682.  
  2683. if (CurrentPage[Mode] > 1) CurrentPage[Mode] -= 1;
  2684. UpdateBuddiesList = True;
  2685. }
  2686. // ---------------------------------- //
  2687. // Buddies list next page button
  2688. else if (Event.ControlId == "Quad_NextBuddiesPage") {
  2689. declare Mode = CurrentWidgetMode;
  2690. if (Frame_SearchModeCard.Visible) Mode = "Search";
  2691.  
  2692. if (CurrentPage[Mode] < PagesCount[Mode]) CurrentPage[Mode] += 1;
  2693. UpdateBuddiesList = True;
  2694. }
  2695. // ---------------------------------- //
  2696. // Scroll messages up
  2697. else if (Event.ControlId == "Quad_MessagesScrollUp") {
  2698. declare Text BuddyLogin;
  2699. switch (CurrentWidgetMode) {
  2700. case "Group" : BuddyLogin = "*group*";
  2701. case "Global" : BuddyLogin = "*global*";
  2702. default : BuddyLogin = SelectedConversation;
  2703. }
  2704. if (!MessagesOffset.existskey(BuddyLogin)) MessagesOffset[BuddyLogin] = 0;
  2705. MessagesOffset[BuddyLogin] += 1;
  2706. UpdateMessagesSlots = 2;
  2707. }
  2708. // ---------------------------------- //
  2709. // Scroll messages down
  2710. else if (Event.ControlId == "Quad_MessagesScrollDown") {
  2711. declare Text BuddyLogin;
  2712. switch (CurrentWidgetMode) {
  2713. case "Group" : BuddyLogin = "*group*";
  2714. case "Global" : BuddyLogin = "*global*";
  2715. default : BuddyLogin = SelectedConversation;
  2716. }
  2717. if (!MessagesOffset.existskey(BuddyLogin)) MessagesOffset[BuddyLogin] = 0;
  2718. MessagesOffset[BuddyLogin] -= 1;
  2719. UpdateMessagesSlots = 2;
  2720. }
  2721. // ---------------------------------- //
  2722. // Send buddy invitation
  2723. else if (Event.ControlId == "Quad_InvitePlayerButton") {
  2724. SendCustomEvent("AddBuddy", [Entry_InvitePlayerInput.Value]);
  2725. Entry_InvitePlayerInput.Value = "";
  2726. }
  2727. // ---------------------------------- //
  2728. // Accept buddy request
  2729. else if (Event.ControlId == "Quad_BuddySlotBtnAdd") {
  2730. declare Login = Event.Control.DataAttributeGet("login");
  2731. if (Login != "") SendCustomEvent("BuddyAccept", [Login]);
  2732. }
  2733. // ---------------------------------- //
  2734. // Deny / cancel buddy request
  2735. else if (Event.ControlId == "Quad_BuddySlotBtnDeny") {
  2736. declare Login = Event.Control.DataAttributeGet("login");
  2737. if (Login != "") SendCustomEvent("BuddyDeny", [Login]);
  2738. }
  2739. // ---------------------------------- //
  2740. // Add buddy from server
  2741. else if (Event.ControlId == "Quad_BuddySlotBtnPlus") {
  2742. declare Login = Event.Control.DataAttributeGet("login");
  2743. if (Login != "") SendCustomEvent("AddBuddy", [Login]);
  2744. }
  2745. // ---------------------------------- //
  2746. // Enter the search mode
  2747. else if (Event.ControlId == "Quad_BuddySlotBtnSearch") {
  2748. Frame_SearchModeCard.Show();
  2749. Entry_SearchModeInput.StartEdition();
  2750. PrevWidgetMode = "";
  2751. }
  2752. // ---------------------------------- //
  2753. // Leave search mode
  2754. else if (Event.ControlId == "Quad_SearchModeClose") {
  2755. Frame_SearchModeCard.Hide();
  2756. Entry_SearchModeInput.Value = "";
  2757. PrevWidgetMode = "";
  2758. }
  2759. // ---------------------------------- //
  2760. // Cycle through available presences
  2761. else if (Event.ControlId == "Quad_MessengerBuddyPresence") {
  2762. if (CurrentWidgetMode == "Group") {
  2763. ManialinkTargetPresence += 1;
  2764. if (ManialinkTargetPresence > 5) ManialinkTargetPresence = 3;
  2765. Persistent_Evidence_UserTargetPresenceId = ManialinkTargetPresence;
  2766. }
  2767. }
  2768. // ---------------------------------- //
  2769. // Send mail to specified buddy
  2770. else if (Event.ControlId == "Quad_MessengerBuddyMail") {
  2771. declare BuddyLogin = Event.Control.DataAttributeGet("login");
  2772. if (BuddyLogin != "") OpenLink("#mailto="^BuddyLogin, ::LinkType::ManialinkBrowser);
  2773. }
  2774. // ---------------------------------- //
  2775. // Remove buddy
  2776. else if (Event.ControlId == "Quad_MessengerBuddyRemove") {
  2777. declare Login = Event.Control.DataAttributeGet("login");
  2778. if (Login != "") SendCustomEvent("RemoveBuddy", [Login]);
  2779. SelectedConversation = "";
  2780. }
  2781. // ---------------------------------- //
  2782. // Copy message content buttons
  2783. else if (Event.ControlId == "Quad_MessageSlotBtnCopy") {
  2784. declare ClipboardContents = TL::StripFormatting(Event.Control.DataAttributeGet("clipboard"));
  2785. if (ClipboardContents != "") SendCustomEvent("SetClipboard", [ClipboardContents]);
  2786. }
  2787.  
  2788. // ---------------------------------- //
  2789. // Open manialink
  2790. if (Event.Control.DataAttributeExists("manialink")) {
  2791. declare ManialinkCode = Event.Control.DataAttributeGet("manialink");
  2792. if (ManialinkCode != "") {
  2793. OpenLink(ManialinkCode, ::LinkType::ManialinkBrowser);
  2794. ChatWidgetIsOpen = False;
  2795. }
  2796. }
  2797.  
  2798. // ---------------------------------- //
  2799. // Send command
  2800. if (Event.Control.DataAttributeExists("command")) {
  2801. declare Command = Event.Control.DataAttributeGet("command");
  2802. if (Command != "") SendCustomEvent("SendMessage", ["*group*", Command]);
  2803. }
  2804.  
  2805. // ---------------------------------- //
  2806. // Change Evidence settings
  2807. if (Event.Control.HasClass("Check")) {
  2808. switch (Event.ControlId) {
  2809. case "Quad_CheckUseDynamicStatus" : Persistent_Evidence_UseDynamicStatus = !Persistent_Evidence_UseDynamicStatus;
  2810. case "Quad_CheckUseLinksPhrasing" : Persistent_Evidence_UseLinksPhrasing = !Persistent_Evidence_UseLinksPhrasing;
  2811. case "Quad_CheckEnableGlobalChat" : Persistent_Evidence_EnableGlobalChat = !Persistent_Evidence_EnableGlobalChat;
  2812. case "Quad_CheckNoticeOnNewMessage" : Persistent_Evidence_NoticeOnNewMessage = !Persistent_Evidence_NoticeOnNewMessage;
  2813. case "Quad_CheckNoticeOnConnection" : Persistent_Evidence_NoticeOnConnection = !Persistent_Evidence_NoticeOnConnection;
  2814. }
  2815. }
  2816.  
  2817. // ---------------------------------- //
  2818. // Play sounds
  2819. if (Event.Control.HasClass("valid-0")) Audio.PlaySoundEvent(CAudioManager::ELibSound::Valid, 0, 0.);
  2820. if (Event.Control.HasClass("valid-1")) Audio.PlaySoundEvent(CAudioManager::ELibSound::Valid, 1, 0.);
  2821. }
  2822. // ---------------------------------- //
  2823. // Mouse hover
  2824. else if (Event.Type == CMlEvent::Type::MouseOver) {
  2825. // ---------------------------------- //
  2826. // Highlight mode buttons
  2827. if (Event.ControlId == "Quad_ModeButtonIcon") {
  2828. HighlightModeButton = Event.Control.DataAttributeGet("mode");
  2829. UpdateModeButtons = True;
  2830. }
  2831. // ---------------------------------- //
  2832. // Highlight buddy slot
  2833. else if (Event.ControlId == "Quad_BuddySlotBgCard") {
  2834. HighlightBuddySlot = Event.Control.Id;
  2835. UpdateSlotsBgSlots = True;
  2836. }
  2837.  
  2838. // ---------------------------------- //
  2839. // Play sounds
  2840. if (Event.Control.HasClass("focus-1")) Audio.PlaySoundEvent(CAudioManager::ELibSound::Focus, 1, 0.);
  2841. if (Event.Control.HasClass("focus-2")) Audio.PlaySoundEvent(CAudioManager::ELibSound::Focus, 2, 0.);
  2842. }
  2843. // ---------------------------------- //
  2844. // Mouse hover end
  2845. else if (Event.Type == CMlEvent::Type::MouseOut) {
  2846. // ---------------------------------- //
  2847. // Highlight mode buttons
  2848. if (Event.ControlId == "Quad_ModeButtonIcon") {
  2849. HighlightModeButton = "";
  2850. UpdateModeButtons = True;
  2851. }
  2852. // ---------------------------------- //
  2853. // Highlight buddy slot
  2854. else if (Event.ControlId == "Quad_BuddySlotBgCard") {
  2855. HighlightBuddySlot = NullId;
  2856. UpdateSlotsBgSlots = True;
  2857. }
  2858. }
  2859. // ---------------------------------- //
  2860. // Entry submission
  2861. else if (Event.Type == CMlEvent::Type::EntrySubmit) {
  2862. declare Entry <=> (Event.Control as CMlEntry);
  2863. // ---------------------------------- //
  2864. // Message input
  2865. if (Event.ControlId == "Entry_MessageSubmit") {
  2866. if (Entry.Value != "" && Entry.Value != "$") {
  2867. // ---------------------------------- //
  2868. // Select conversation
  2869. declare Text TargetConversation;
  2870. switch (CurrentWidgetMode) {
  2871. case "Group" : TargetConversation = "*group*";
  2872. case "Global" : TargetConversation = "*global*";
  2873. default : TargetConversation = SelectedConversation;
  2874. }
  2875.  
  2876. // Send message
  2877. if (TargetConversation != "") {
  2878. declare FormattedMessage = FormatMessage(Entry.Value);
  2879. SendCustomEvent("SendMessage", [TargetConversation, FormattedMessage]);
  2880. if (TargetConversation != "*global*" && TargetConversation != "*group*" && TL::SubString(Entry.Value, 0, 1) != "/")
  2881. NewReceivedMessages.add([TargetConversation, LocalUser.Login, FormattedMessage]);
  2882. Entry.Value = "";
  2883.  
  2884. // ---------------------------------- //
  2885. // Reset laste message read state
  2886. if (Persistent_Evidence_UsersSeenMessages.exists(TargetConversation)) {
  2887. declare Removed = Persistent_Evidence_UsersSeenMessages.remove(TargetConversation);
  2888. }
  2889. }
  2890. }
  2891. Entry.StartEdition();
  2892. }
  2893. // ---------------------------------- //
  2894. // Send buddy invitation
  2895. else if (Event.ControlId == "Entry_InvitePlayerInput") {
  2896. SendCustomEvent("AddBuddy", [Entry.Value]);
  2897. Entry.Value = "";
  2898. }
  2899. }
  2900. }
  2901.  
  2902. GameIsInFocus = <MouseX, MouseY> != <-1000., -1000.>;
  2903.  
  2904. // ---------------------------------- //
  2905. // New messages to display
  2906. while (NewReceivedMessages.count > 0) {
  2907. declare MessageData = NewReceivedMessages[0];
  2908. declare Removed = NewReceivedMessages.removekey(0);
  2909.  
  2910. // ---------------------------------- //
  2911. // Get new message data
  2912. if (MessageData.count >= 3) {
  2913. declare ConversationLogin = MessageData[0];
  2914. declare SenderLogin = MessageData[1];
  2915. declare MessageBody = FormatMessage(MessageData[2]);
  2916.  
  2917. // Initialize conversation history array if empty
  2918. if (
  2919. !Persistent_Evidence_ChatHistoryBody.existskey(ConversationLogin) ||
  2920. !Persistent_Evidence_ChatHistorySender.existskey(ConversationLogin) ||
  2921. !Persistent_Evidence_ChatHistoryDate.existskey(ConversationLogin)
  2922. ) {
  2923. Persistent_Evidence_ChatHistoryBody[ConversationLogin] = Text[];
  2924. Persistent_Evidence_ChatHistorySender[ConversationLogin] = Text[];
  2925. Persistent_Evidence_ChatHistoryDate[ConversationLogin] = Text[];
  2926. }
  2927.  
  2928. // ---------------------------------- //
  2929. // Look up for images
  2930. declare MessageIsImage = TL::SubText(MessageBody, 0, 6) == "image:";
  2931.  
  2932. if (!MessageIsImage) {
  2933. declare ReceivedImages = FindImages(MessageBody);
  2934. foreach (URL in ReceivedImages) {
  2935. // Remove images links from message
  2936. MessageBody = TL::Replace(MessageBody, "$<$FA3$l"^URL^"$>", "");
  2937.  
  2938. // Re-send message
  2939. NewReceivedMessages.add([ConversationLogin, SenderLogin, "image:"^URL]);
  2940. }
  2941. }
  2942.  
  2943. if (MessageBody == "") continue;
  2944.  
  2945. // ---------------------------------- //
  2946. // Attach message to previous one if sender is the same
  2947. declare PreviousMessageId = Persistent_Evidence_ChatHistoryBody[ConversationLogin].count - 1;
  2948. if (
  2949. !MessageIsImage &&
  2950. Persistent_Evidence_ChatHistorySender[ConversationLogin].existskey(PreviousMessageId) &&
  2951. Persistent_Evidence_ChatHistorySender[ConversationLogin][PreviousMessageId] == SenderLogin &&
  2952. TL::SubText(Persistent_Evidence_ChatHistoryBody[ConversationLogin][PreviousMessageId], 0, 6) != "image:"
  2953. ) {
  2954. Persistent_Evidence_ChatHistoryBody[ConversationLogin][PreviousMessageId] ^= "\n$z"^MessageBody;
  2955. Persistent_Evidence_ChatHistoryDate[ConversationLogin][PreviousMessageId] = CurrentLocalDateText;
  2956. }
  2957.  
  2958. // ---------------------------------- //
  2959. // Save new message in history
  2960. else {
  2961. Persistent_Evidence_ChatHistoryBody[ConversationLogin].add(MessageBody);
  2962. Persistent_Evidence_ChatHistorySender[ConversationLogin].add(SenderLogin);
  2963. Persistent_Evidence_ChatHistoryDate[ConversationLogin].add(CurrentLocalDateText);
  2964. }
  2965.  
  2966. // ---------------------------------- //
  2967. // Remove oldest messages from history
  2968. declare SavedMessagesAmount = Persistent_Evidence_ChatHistoryBody[ConversationLogin].count;
  2969. if (SavedMessagesAmount > C_MaxMessagesInHistory) for (I, 1, SavedMessagesAmount - C_MaxMessagesInHistory) {
  2970. declare Boolean Removed;
  2971. Removed = Persistent_Evidence_ChatHistoryBody[ConversationLogin].removekey(0);
  2972. Removed = Persistent_Evidence_ChatHistorySender[ConversationLogin].removekey(0);
  2973. Removed = Persistent_Evidence_ChatHistoryDate[ConversationLogin].removekey(0);
  2974. }
  2975.  
  2976. // ---------------------------------- //
  2977. // Move buddy to the top of the list
  2978. if (!BuddiesList_ListOnTop.exists(ConversationLogin)) {
  2979. BuddiesList_ListOnTop.add(ConversationLogin);
  2980. SortBuddiesList = True;
  2981. }
  2982.  
  2983. // ---------------------------------- //
  2984. // Update messages slots manialink
  2985. declare SpecialMessageModes = ["Group" => "*group*", "Global" => "*global*"];
  2986. if (
  2987. (ConversationLogin == SelectedConversation && !SpecialMessageModes.exists(CurrentWidgetMode)) ||
  2988. (SpecialMessageModes.existskey(CurrentWidgetMode) && SpecialMessageModes[CurrentWidgetMode] == ConversationLogin)
  2989. )
  2990. UpdateMessagesSlots = 2;
  2991.  
  2992. // ---------------------------------- //
  2993. // Check if user should receive notification
  2994. declare NotifyUser = False;
  2995. switch (ConversationLogin) {
  2996. case "*group*" : NotifyUser = (CurrentWidgetMode != "Group");
  2997. case "*global*" : NotifyUser = (CurrentWidgetMode != "Global");
  2998. default : NotifyUser = (SelectedConversation != ConversationLogin || SpecialMessageModes.existskey(CurrentWidgetMode));
  2999. }
  3000.  
  3001. if (SenderLogin != LocalUser.Login && (NotifyUser || !ChatWidgetIsOpen || !GameIsInFocus)) {
  3002. // ---------------------------------- //
  3003. // Increase amount of unread messages
  3004. if (!Persistent_Evidence_NbUnreadMessages.existskey(ConversationLogin))
  3005. Persistent_Evidence_NbUnreadMessages[ConversationLogin] = 0;
  3006. Persistent_Evidence_NbUnreadMessages[ConversationLogin] += 1;
  3007.  
  3008. // ---------------------------------- //
  3009. // Play notification sound
  3010. if (CurrentPluginPresenceId != 3 && ConversationLogin != "*global*")
  3011. Audio.PlaySoundEvent(CAudioManager::ELibSound::Alert, 1, 0.);
  3012.  
  3013. // ---------------------------------- //
  3014. // Display notification
  3015. if (NoticeOnNewMessage) SendCustomEvent("ShowMessageNotice", [SenderLogin, MessageBody]);
  3016. }
  3017.  
  3018. else if (SenderLogin != LocalUser.Login) SendCustomEvent("SeenMessage", [SenderLogin]);
  3019.  
  3020. // ---------------------------------- //
  3021. // Flash taskbar
  3022. if (SenderLogin != LocalUser.Login && ConversationLogin != "*global*")
  3023. FlashTaskbar = True;
  3024. }
  3025. }
  3026.  
  3027. // ---------------------------------- //
  3028. // Get users that seen the message
  3029. while (UsersThatSeenMessage.count > 0) {
  3030. if (!Persistent_Evidence_UsersSeenMessages.exists(UsersThatSeenMessage[0])) {
  3031. Persistent_Evidence_UsersSeenMessages.add(UsersThatSeenMessage[0]);
  3032. if (UsersThatSeenMessage[0] == SelectedConversation) UpdateMessagesSlots = 2;
  3033. }
  3034. declare Removed = UsersThatSeenMessage.removekey(0);
  3035. }
  3036.  
  3037. // ---------------------------------- //
  3038. // Update messages on focus change
  3039. if (PrevGameIsInFocus != GameIsInFocus) {
  3040. PrevGameIsInFocus = GameIsInFocus;
  3041.  
  3042. if (
  3043. GameIsInFocus &&
  3044. Persistent_Evidence_NbUnreadMessages.existskey(SelectedConversation) &&
  3045. Persistent_Evidence_NbUnreadMessages[SelectedConversation] > 0
  3046. ) {
  3047. UpdateMessagesSlots = 2;
  3048. }
  3049. }
  3050.  
  3051. // ---------------------------------- //
  3052. // Update unread messages amount
  3053. NbUnreadMessages["Buddies"] = 0;
  3054. foreach (Login => Amount in Persistent_Evidence_NbUnreadMessages) {
  3055. switch (Login) {
  3056. case "*group*" : NbUnreadMessages["Group"] = Amount;
  3057. case "*global*" : NbUnreadMessages["Global"] = Amount;
  3058. default : NbUnreadMessages["Buddies"] += Amount;
  3059. }
  3060. }
  3061.  
  3062. // ---------------------------------- //
  3063. // Set mode buttons notifications amount
  3064. foreach (Group in UnreadMessagesGroups) {
  3065. if (PrevNbUnreadMessages[Group] != NbUnreadMessages[Group]) {
  3066. PrevNbUnreadMessages[Group] = NbUnreadMessages[Group];
  3067. SetModeNotificationsCount(Group, NbUnreadMessages[Group]);
  3068. TotalNbUnreadMessages = NbUnreadMessages["Buddies"] + NbUnreadMessages["Group"];
  3069. }
  3070. }
  3071.  
  3072. // ---------------------------------- //
  3073. // Animations
  3074. // ---------------------------------- //
  3075.  
  3076. // ---------------------------------- //
  3077. // Trigger Evidence window animation
  3078. if (PrevChatWidgetIsOpen != ChatWidgetIsOpen) {
  3079. PrevChatWidgetIsOpen = ChatWidgetIsOpen;
  3080.  
  3081. declare PositionY = C_EvidenceFramePosY;
  3082. declare Easing = "EaseOutCirc";
  3083.  
  3084. if (!ChatWidgetIsOpen) {
  3085. PositionY += C_EvidenceFramePosHide;
  3086. Easing = "EaseInCirc";
  3087. }
  3088.  
  3089. LibManialink_AnimStop(Frame_EvidencePlugin);
  3090. LibManialink_Anim(Frame_EvidencePlugin, "<frame posn=\"0 "^PositionY^"\"/>", 250, Easing);
  3091. }
  3092.  
  3093. Frame_EvidencePlugin.Visible = Frame_EvidencePlugin.RelativePosition.Y != C_EvidenceFramePosY + C_EvidenceFramePosHide;
  3094.  
  3095. // Set messenger window visibility
  3096. MessengerIsOpen = (CurrentWidgetMode == "Group" || CurrentWidgetMode == "Global" || SelectedConversation != "");
  3097.  
  3098. // ---------------------------------- //
  3099. // Trigger Messenger window animation
  3100. if (PrevMessengerIsOpen != MessengerIsOpen) {
  3101. PrevMessengerIsOpen = MessengerIsOpen;
  3102.  
  3103. declare PositionY = Frame_MessengerWindow.RelativePosition.Y;
  3104. declare PositionX = C_MessengerFramePosX;
  3105. declare Easing = "EaseOutCirc";
  3106.  
  3107. if (!MessengerIsOpen) {
  3108. PositionX += C_MessengerFramePosHide;
  3109. Easing = "EaseInCirc";
  3110. }
  3111.  
  3112. LibManialink_AnimStop(Frame_MessengerWindow);
  3113. LibManialink_Anim(Frame_MessengerWindow, "<frame posn=\""^PositionX^" "^PositionY^"\"/>", 250, Easing);
  3114. }
  3115.  
  3116. Frame_MessengerWindow.Visible = Frame_MessengerWindow.RelativePosition.Y != C_MessengerFramePosX + C_MessengerFramePosHide;
  3117.  
  3118. // ---------------------------------- //
  3119. // Update settings
  3120. // ---------------------------------- //
  3121.  
  3122. // ---------------------------------- //
  3123. // Dynamic status
  3124. if (UseDynamicStatus != Persistent_Evidence_UseDynamicStatus) {
  3125. UseDynamicStatus = Persistent_Evidence_UseDynamicStatus;
  3126. Quad_CheckUseDynamicStatus.StyleSelected = UseDynamicStatus;
  3127. }
  3128.  
  3129. // ---------------------------------- //
  3130. // Links phrasing
  3131. if (UseLinksPhrasing != Persistent_Evidence_UseLinksPhrasing) {
  3132. UseLinksPhrasing = Persistent_Evidence_UseLinksPhrasing;
  3133. Quad_CheckUseLinksPhrasing.StyleSelected = UseLinksPhrasing;
  3134. }
  3135.  
  3136. // ---------------------------------- //
  3137. // Group Chat password
  3138. if (GroupChatPassword != Entry_GroupChatPassword.Value) {
  3139. GroupChatPassword = Entry_GroupChatPassword.Value;
  3140. Persistent_Evidence_GroupChatPassword = GroupChatPassword;
  3141. }
  3142.  
  3143. // ---------------------------------- //
  3144. // Global Chat
  3145. if (EnableGlobalChat != Persistent_Evidence_EnableGlobalChat) {
  3146. EnableGlobalChat = Persistent_Evidence_EnableGlobalChat;
  3147. Quad_CheckEnableGlobalChat.StyleSelected = EnableGlobalChat;
  3148. }
  3149.  
  3150. // ---------------------------------- //
  3151. // Notice on new message
  3152. if (NoticeOnNewMessage != Persistent_Evidence_NoticeOnNewMessage) {
  3153. NoticeOnNewMessage = Persistent_Evidence_NoticeOnNewMessage;
  3154. Quad_CheckNoticeOnNewMessage.StyleSelected = NoticeOnNewMessage;
  3155. }
  3156.  
  3157. // ---------------------------------- //
  3158. // Notice on new connection
  3159. if (NoticeOnConnection != Persistent_Evidence_NoticeOnConnection) {
  3160. NoticeOnConnection = Persistent_Evidence_NoticeOnConnection;
  3161. Quad_CheckNoticeOnConnection.StyleSelected = NoticeOnConnection;
  3162. }
  3163.  
  3164. // ---------------------------------- //
  3165. // Save Clipboard
  3166. if (Persistent_Evidence_PasteBin != TextEdit_PasteBin.Value)
  3167. Persistent_Evidence_PasteBin = TextEdit_PasteBin.Value;
  3168.  
  3169. // ---------------------------------- //
  3170. // Start next update check request
  3171. if (Now > NextUpdateCheckout) {
  3172. NextUpdateCheckout = Now + C_UpdateCheckInterval;
  3173.  
  3174. // Destroy ongoing request
  3175. if (UpdateCheckRequest != Null) {
  3176. Http.Destroy(UpdateCheckRequest);
  3177. UpdateCheckRequest = Null;
  3178. }
  3179.  
  3180. // Start new request
  3181. UpdateCheckRequest = Http.CreateGet(C_UpdateCheckAddress, False);
  3182. }
  3183.  
  3184. // ---------------------------------- //
  3185. // Display update notification
  3186. if (UpdateCheckRequest != Null && UpdateCheckRequest.IsCompleted) {
  3187. PluginIsOutdated = !IsNewest("{{{ScriptVersion}}}", UpdateCheckRequest.Result);
  3188. if (PluginIsOutdated) SetModeNotificationsCount("Settings", 1);
  3189.  
  3190. Http.Destroy(UpdateCheckRequest);
  3191. UpdateCheckRequest = Null;
  3192. }
  3193.  
  3194. // Hold everything until chat is visible again
  3195. if (!ChatWidgetIsOpen) continue;
  3196.  
  3197. // ---------------------------------- //
  3198. // Update information
  3199. // ---------------------------------- //
  3200.  
  3201. // ---------------------------------- //
  3202. // Online buddies amount change
  3203. if (PrevBuddiesOnline != BuddiesList_Online.count) {
  3204. PrevBuddiesOnline = BuddiesList_Online.count;
  3205. SortBuddiesList = True;
  3206. }
  3207.  
  3208. // ---------------------------------- //
  3209. // Offline buddies amount change
  3210. if (PrevBuddiesOffline != BuddiesList_Offline.count) {
  3211. PrevBuddiesOffline = BuddiesList_Offline.count;
  3212. SortBuddiesList = True;
  3213. }
  3214.  
  3215. // ---------------------------------- //
  3216. // Incoming buddy requests amount change
  3217. if (PrevBuddiesRequestFrom != BuddiesList_RequestFrom.count) {
  3218. PrevBuddiesRequestFrom = BuddiesList_RequestFrom.count;
  3219. SortRequestsList = True;
  3220. SetModeNotificationsCount("Requests", PrevBuddiesRequestFrom);
  3221. }
  3222.  
  3223. // ---------------------------------- //
  3224. // Sent buddy requests amount change
  3225. if (PrevBuddiesRequestTo != BuddiesList_RequestTo.count) {
  3226. PrevBuddiesRequestTo = BuddiesList_RequestTo.count;
  3227. SortRequestsList = True;
  3228. }
  3229.  
  3230. // ---------------------------------- //
  3231. // Sent buddy requests amount change
  3232. if (PrevBuddiesOnServer != BuddiesList_OnServer.count) {
  3233. PrevBuddiesOnServer = BuddiesList_OnServer.count;
  3234. SortRequestsList = True;
  3235. }
  3236.  
  3237. // ---------------------------------- //
  3238. // Buddies in group amount change
  3239. if (PrevBuddiesInGroup != BuddiesList_InGroup.count) {
  3240. PrevBuddiesInGroup = BuddiesList_InGroup.count;
  3241. PagesCount["Group"] = (BuddiesList_InGroup.count - 1) / 10 + 1;
  3242. if (CurrentWidgetMode == "Group") UpdateBuddiesList = True;
  3243. }
  3244.  
  3245. // ---------------------------------- //
  3246. // Buddies in global chat amount change
  3247. if (PrevBuddiesGlobalList != BuddiesList_GlobalList.count) {
  3248. PrevBuddiesGlobalList = BuddiesList_GlobalList.count;
  3249. PagesCount["Global"] = (BuddiesList_GlobalList.count - 1) / 10 + 1;
  3250. if (CurrentWidgetMode == "Global") UpdateBuddiesList = True;
  3251. }
  3252.  
  3253. // ---------------------------------- //
  3254. // Muted buddies amount change
  3255. if (PrevBuddiesMutedUsers != BuddiesList_MutedUsers.count) {
  3256. PrevBuddiesMutedUsers = BuddiesList_MutedUsers.count;
  3257. if (CurrentWidgetMode == "Group") UpdateBuddiesList = True;
  3258. }
  3259.  
  3260. // ---------------------------------- //
  3261. // Buddy changed his name
  3262. foreach (Login => Name in BuddiesName) {
  3263. if (!PrevBuddiesName.existskey(Login) || PrevBuddiesName[Login] != Name) {
  3264. PrevBuddiesName[Login] = Name;
  3265. UpdateBuddiesList = True;
  3266.  
  3267. // Update messenger window
  3268. if (Login == SelectedConversation || CurrentWidgetMode == "Group" || CurrentWidgetMode == "Global") {
  3269. UpdateMessengerInfo = True;
  3270. UpdateMessagesSlots = 2;
  3271. }
  3272. }
  3273. }
  3274.  
  3275. // ---------------------------------- //
  3276. // Buddy changed his presence
  3277. foreach (Login => PresenceId in BuddiesPresenceId) {
  3278. if (!PrevBuddiesPresenceId.existskey(Login) || PrevBuddiesPresenceId[Login] != PresenceId) {
  3279. PrevBuddiesPresenceId[Login] = PresenceId;
  3280. SortBuddiesList = True;
  3281. UpdateBuddiesList = True;
  3282.  
  3283. // Update messenger window
  3284. if (Login == SelectedConversation || CurrentWidgetMode == "Group" || CurrentWidgetMode == "Global") {
  3285. UpdateMessengerInfo = True;
  3286. UpdateMessagesSlots = 2;
  3287. }
  3288. }
  3289. }
  3290.  
  3291. // ---------------------------------- //
  3292. // Buddy changed his status
  3293. foreach (Login => Status in BuddiesStatus) {
  3294. if (!PrevBuddiesStatus.existskey(Login) || PrevBuddiesStatus[Login] != Status) {
  3295. PrevBuddiesStatus[Login] = Status;
  3296. UpdateBuddiesList = True;
  3297.  
  3298. // Update messenger window
  3299. if (Login == SelectedConversation) UpdateMessengerInfo = True;
  3300. }
  3301. }
  3302.  
  3303. // ---------------------------------- //
  3304. // Buddy changed his server
  3305. foreach (Login => ServerLogin in BuddiesServerLogin) {
  3306. if (!PrevBuddiesServerLogin.existskey(Login) || PrevBuddiesServerLogin[Login] != ServerLogin) {
  3307. PrevBuddiesServerLogin[Login] = ServerLogin;
  3308. UpdateBuddiesList = True;
  3309.  
  3310. // Update messenger window
  3311. if (Login == SelectedConversation) UpdateMessengerInfo = True;
  3312. }
  3313. }
  3314.  
  3315. // ---------------------------------- //
  3316. // Global Chat users update
  3317. // ---------------------------------- //
  3318.  
  3319. // ---------------------------------- //
  3320. // User changed his name
  3321. foreach (Login => Name in GlobalChat_BuddiesName) {
  3322. if (!PrevGlobalBuddiesName.existskey(Login) || PrevGlobalBuddiesName[Login] != Name) {
  3323. PrevGlobalBuddiesName[Login] = Name;
  3324. UpdateBuddiesList = True;
  3325.  
  3326. // Update messenger window
  3327. if (CurrentWidgetMode == "Global") {
  3328. UpdateMessengerInfo = True;
  3329. UpdateMessagesSlots = 2;
  3330. }
  3331. }
  3332. }
  3333.  
  3334. // ---------------------------------- //
  3335. // User changed his presence
  3336. foreach (Login => PresenceId in GlobalChat_BuddiesPresenceId) {
  3337. if (!PrevGlobalBuddiesPresenceId.existskey(Login) || PrevGlobalBuddiesPresenceId[Login] != PresenceId) {
  3338. PrevGlobalBuddiesPresenceId[Login] = PresenceId;
  3339. UpdateBuddiesList = True;
  3340.  
  3341. // Update messenger window
  3342. if (CurrentWidgetMode == "Global") {
  3343. UpdateMessengerInfo = True;
  3344. UpdateMessagesSlots = 2;
  3345. }
  3346. }
  3347. }
  3348.  
  3349. // ---------------------------------- //
  3350. // Evidence widget
  3351. // ---------------------------------- //
  3352.  
  3353. // ---------------------------------- //
  3354. // Widget mode change
  3355. if (PrevWidgetMode != CurrentWidgetMode) {
  3356. UpdateModeButtons = True;
  3357. UpdateBuddiesList = True;
  3358. UpdateMessengerInfo = True;
  3359.  
  3360. // ---------------------------------- //
  3361. // Set local user card visibility
  3362. if (Frame_SearchModeCard.Visible && CurrentWidgetMode != "Buddies") Frame_SearchModeCard.Hide();
  3363.  
  3364. declare ModesUsingLocalSlot = ["Buddies", "Group", "Global"];
  3365. Frame_LocalUserSlot.Visible = ModesUsingLocalSlot.exists(CurrentWidgetMode) && !Frame_SearchModeCard.Visible;
  3366.  
  3367. Frame_BuddyInviteCard.Visible = CurrentWidgetMode == "Requests";
  3368. Frame_SettingsMenu.Visible = CurrentWidgetMode == "Settings";
  3369. TextEdit_PasteBin.Visible = CurrentWidgetMode == "Settings";
  3370. Label_ButtonUpdate.Visible = (CurrentWidgetMode == "Settings" && PluginIsOutdated);
  3371.  
  3372. // ---------------------------------- //
  3373. // Reset search mode
  3374. Quad_LocalUserSearch.Visible = CurrentWidgetMode == "Buddies" && !Frame_SearchModeCard.Visible;
  3375. Entry_SearchModeInput.Value = "";
  3376.  
  3377. // ---------------------------------- //
  3378. // Update messages slots
  3379. declare MessageUpdateModes = ["Group", "Global"];
  3380. if (MessageUpdateModes.exists(CurrentWidgetMode) || (MessageUpdateModes.exists(PrevWidgetMode) && SelectedConversation != "")) {
  3381. PrevMessengerIsOpen = False;
  3382. UpdateMessagesSlots = 2;
  3383. }
  3384.  
  3385. PrevWidgetMode = CurrentWidgetMode;
  3386. }
  3387.  
  3388. // ---------------------------------- //
  3389. // Set mode buttons color
  3390. if (UpdateModeButtons) {
  3391. UpdateModeButtons = False;
  3392. foreach (Mode => Frame in Frame_ModeButtons) {
  3393. declare Quad_ModeButtonIcon <=> (Frame.GetFirstChild("Quad_ModeButtonIcon") as CMlQuad);
  3394. Quad_ModeButtonIcon.Opacity = C_ModeButtonsOpacity[CurrentWidgetMode == Mode][(HighlightModeButton == Mode)];
  3395. }
  3396. }
  3397.  
  3398. // ---------------------------------- //
  3399. // Custom status updates
  3400. if (PrevEntryStatusValue != Entry_MessengerStatusInput.Value) {
  3401. PrevEntryStatusValue = Entry_MessengerStatusInput.Value;
  3402. Persistent_Evidence_UserCustomStatus = PrevEntryStatusValue;
  3403. ManialinkCustomStatus = PrevEntryStatusValue;
  3404. }
  3405.  
  3406. // ---------------------------------- //
  3407. // Force sort buddies list
  3408. if (SortBuddiesList) {
  3409. SortBuddiesList = False;
  3410. BuddiesList_SortedList.clear();
  3411. if (CurrentWidgetMode == "Buddies") UpdateBuddiesList = True;
  3412.  
  3413. // Online buddies listed on top
  3414. foreach (Login in BuddiesList_ListOnTop)
  3415. if (BuddiesList_Online.exists(Login)) BuddiesList_SortedList.add(Login);
  3416.  
  3417. // Other online buddies
  3418. foreach (Login in BuddiesList_Online)
  3419. if (!BuddiesList_SortedList.exists(Login)) BuddiesList_SortedList.add(Login);
  3420.  
  3421. // Offline buddies listed top
  3422. foreach (Login in BuddiesList_ListOnTop)
  3423. if (BuddiesList_Offline.exists(Login)) BuddiesList_SortedList.add(Login);
  3424.  
  3425. // Other offline buddies
  3426. foreach (Login in BuddiesList_Offline)
  3427. if (!BuddiesList_SortedList.exists(Login)) BuddiesList_SortedList.add(Login);
  3428.  
  3429. // Update pages amount
  3430. PagesCount["Buddies"] = (BuddiesList_SortedList.count - 1) / 10 + 1;
  3431. if (CurrentPage["Buddies"] > PagesCount["Buddies"]) CurrentPage["Buddies"] = PagesCount["Buddies"];
  3432. }
  3433.  
  3434. // ---------------------------------- //
  3435. // Force sort requests list
  3436. if (SortRequestsList) {
  3437. SortRequestsList = False;
  3438. BuddiesList_RequestList.clear();
  3439. if (CurrentWidgetMode == "Requests") UpdateBuddiesList = True;
  3440.  
  3441. foreach (Login in BuddiesList_RequestFrom) BuddiesList_RequestList.add(Login);
  3442. foreach (Login in BuddiesList_RequestTo) BuddiesList_RequestList.add(Login);
  3443. foreach (Login in BuddiesList_OnServer) {
  3444. if (
  3445. !BuddiesList_Online.exists(Login) && !BuddiesList_Offline.exists(Login) &&
  3446. !BuddiesList_RequestFrom.exists(Login) && !BuddiesList_RequestTo.exists(Login)
  3447. )
  3448. BuddiesList_RequestList.add(Login);
  3449. }
  3450.  
  3451. // Update pages amount
  3452. PagesCount["Requests"] = (BuddiesList_RequestList.count - 1) / 10 + 1;
  3453. if (CurrentPage["Requests"] > PagesCount["Requests"]) CurrentPage["Requests"] = PagesCount["Requests"];
  3454. }
  3455.  
  3456. // ---------------------------------- //
  3457. // Update searched buddies list
  3458. if (PrevEntrySearchValue != Entry_SearchModeInput.Value) {
  3459. BuddiesList_SearchList.clear();
  3460.  
  3461. // ---------------------------------- //
  3462. // Find matching players
  3463. if (Entry_SearchModeInput.Value != "") {
  3464. declare Text[] CompleteList;
  3465. foreach (Login in BuddiesList_Online) CompleteList.add(Login);
  3466. foreach (Login in BuddiesList_Offline) CompleteList.add(Login);
  3467. foreach (Login in BuddiesList_RequestFrom) CompleteList.add(Login);
  3468. foreach (Login in BuddiesList_RequestTo) CompleteList.add(Login);
  3469. foreach (Login in BuddiesList_OnServer) CompleteList.add(Login);
  3470.  
  3471. foreach (Login in CompleteList) {
  3472. if (
  3473. TL::Find(Entry_SearchModeInput.Value, Login, False, False) ||
  3474. (BuddiesName.existskey(Login) && TL::Find(Entry_SearchModeInput.Value, BuddiesName[Login], False, False))
  3475. )
  3476. BuddiesList_SearchList.add(Login);
  3477. }
  3478. }
  3479.  
  3480. // ---------------------------------- //
  3481. // Revert search mode if entry id empty
  3482. if (PrevEntrySearchValue != "" && Entry_SearchModeInput.Value == "") {
  3483. Frame_SearchModeCard.Visible = False;
  3484. PrevWidgetMode = "";
  3485. }
  3486.  
  3487. PrevEntrySearchValue = Entry_SearchModeInput.Value;
  3488.  
  3489. CurrentPage["Search"] = 1;
  3490. PagesCount["Search"] = (BuddiesList_SearchList.count - 1) / 10 + 1;
  3491. UpdateBuddiesList = True;
  3492. }
  3493.  
  3494. // ---------------------------------- //
  3495. // Update buddies list slots
  3496. if (UpdateBuddiesList) {
  3497. UpdateBuddiesList = False;
  3498. UpdateSlotsBgSlots = True;
  3499.  
  3500. // ---------------------------------- //
  3501. // Configure page switch
  3502. declare PagerMode = CurrentWidgetMode;
  3503. if (Frame_SearchModeCard.Visible) PagerMode = "Search";
  3504.  
  3505. declare ListCurrentPage = CurrentPage[PagerMode];
  3506. declare ListPagesCount = PagesCount[PagerMode];
  3507.  
  3508. Frame_PageSwitch.Visible = (ListPagesCount > 1);
  3509. if (Frame_PageSwitch.Visible) {
  3510. Label_PageSwitchCounter.SetText(ListCurrentPage^" / "^ListPagesCount);
  3511. Quad_PrevBuddiesPage.Visible = (ListCurrentPage > 1);
  3512. Quad_NextBuddiesPage.Visible = (ListCurrentPage < ListPagesCount);
  3513. }
  3514.  
  3515. // ---------------------------------- //
  3516. // Setup slots
  3517. declare ListPageIndexOffset = (ListCurrentPage - 1) * 10;
  3518. foreach (I => Frame in Frame_BuddiesSlots) {
  3519. declare BuddyId = I + ListPageIndexOffset;
  3520. declare Text BuddyLogin;
  3521.  
  3522. // ---------------------------------- //
  3523. // Get current buddy
  3524. switch (CurrentWidgetMode) {
  3525. case "Buddies" : {
  3526. if (Frame_SearchModeCard.Visible) {
  3527. if (BuddiesList_SearchList.existskey(BuddyId)) BuddyLogin = BuddiesList_SearchList[BuddyId];
  3528. }
  3529. else if (BuddiesList_SortedList.existskey(BuddyId)) BuddyLogin = BuddiesList_SortedList[BuddyId];
  3530. }
  3531. case "Group" : if (BuddiesList_InGroup.existskey(BuddyId)) BuddyLogin = BuddiesList_InGroup[BuddyId];
  3532. case "Requests" : if (BuddiesList_RequestList.existskey(BuddyId)) BuddyLogin = BuddiesList_RequestList[BuddyId];
  3533. case "Global" : if (BuddiesList_GlobalList.existskey(BuddyId)) BuddyLogin = BuddiesList_GlobalList[BuddyId];
  3534. }
  3535.  
  3536. Frame.Visible = (BuddyLogin != "");
  3537. if (!Frame.Visible) continue;
  3538.  
  3539. // ---------------------------------- //
  3540. // Load buddy slot elements
  3541. declare Quad_BuddySlotBgCard <=> (Frame.GetFirstChild("Quad_BuddySlotBgCard") as CMlQuad);
  3542. declare Label_BuddySlotName <=> (Frame.GetFirstChild("Label_BuddySlotName") as CMlLabel);
  3543. declare Quad_BuddySlotPresence <=> (Frame.GetFirstChild("Quad_BuddySlotPresence") as CMlQuad);
  3544. declare Quad_BuddySlotGlow <=> (Frame.GetFirstChild("Quad_BuddySlotGlow") as CMlQuad);
  3545. declare Label_BuddySlotStatus <=> (Frame.GetFirstChild("Label_BuddySlotStatus") as CMlLabel);
  3546. declare Label_EvidenceUser <=> (Frame.GetFirstChild("Label_EvidenceUser") as CMlLabel);
  3547.  
  3548. declare Quad_BuddySlotBtnJoin <=> (Frame.GetFirstChild("Quad_BuddySlotBtnJoin") as CMlQuad);
  3549. declare Quad_BuddySlotBtnAdd <=> (Frame.GetFirstChild("Quad_BuddySlotBtnAdd") as CMlQuad);
  3550. declare Quad_BuddySlotBtnDeny <=> (Frame.GetFirstChild("Quad_BuddySlotBtnDeny") as CMlQuad);
  3551. declare Quad_BuddySlotBtnPlus <=> (Frame.GetFirstChild("Quad_BuddySlotBtnPlus") as CMlQuad);
  3552. declare Quad_BuddySlotBtnKick <=> (Frame.GetFirstChild("Quad_BuddySlotBtnKick") as CMlQuad);
  3553. declare Quad_BuddySlotBtnMute <=> (Frame.GetFirstChild("Quad_BuddySlotBtnMute") as CMlQuad);
  3554.  
  3555. // ---------------------------------- //
  3556. // Set buddy name
  3557. declare BuddyName = BuddyLogin;
  3558. if (BuddiesName.existskey(BuddyLogin)) BuddyName = BuddiesName[BuddyLogin];
  3559. else if (GlobalChat_BuddiesName.existskey(BuddyLogin)) BuddyName = GlobalChat_BuddiesName[BuddyLogin];
  3560. Label_BuddySlotName.SetText(BuddyName);
  3561.  
  3562. // ---------------------------------- //
  3563. // Set buddy presence
  3564. declare BuddyPresenceId = 0;
  3565. if (BuddiesPresenceId.existskey(BuddyLogin)) BuddyPresenceId = BuddiesPresenceId[BuddyLogin];
  3566. else if (GlobalChat_BuddiesPresenceId.existskey(BuddyLogin)) BuddyPresenceId = GlobalChat_BuddiesPresenceId[BuddyLogin];
  3567. Quad_BuddySlotPresence.BgColor = C_UserPresenceColors[BuddyPresenceId];
  3568. Quad_BuddySlotGlow.Colorize = Quad_BuddySlotPresence.BgColor;
  3569. Quad_BuddySlotGlow.Visible = (BuddyPresenceId > 0);
  3570.  
  3571. // ---------------------------------- //
  3572. // Set buddy status text
  3573. declare BuddyStatus = C_UserPresenceStatus[BuddyPresenceId];
  3574.  
  3575. // Put server name or login in buddy status
  3576. if (BuddiesServerLogin.existskey(BuddyLogin) && BuddiesServerLogin[BuddyLogin] != "") {
  3577. declare ServerLogin = BuddiesServerLogin[BuddyLogin];
  3578. if (!ServersName.existskey(ServerLogin)) BuddyStatus = ServerLogin;
  3579. else BuddyStatus = ServersName[ServerLogin];
  3580. }
  3581. // Put buddys own status
  3582. else if (BuddiesStatus.existskey(BuddyLogin) && BuddiesStatus[BuddyLogin] != "")
  3583. BuddyStatus = BuddiesStatus[BuddyLogin];
  3584. // Put Global Chat buddy status
  3585. else if (GlobalChat_BuddiesStatus.existskey(BuddyLogin) && GlobalChat_BuddiesStatus[BuddyLogin] != "")
  3586. BuddyStatus = GlobalChat_BuddiesStatus[BuddyLogin];
  3587.  
  3588. Label_BuddySlotStatus.SetText(BuddyStatus);
  3589.  
  3590. // ---------------------------------- //
  3591. // Setup background
  3592. Quad_BuddySlotBgCard.DataAttributeSet("login", BuddyLogin);
  3593.  
  3594. // ---------------------------------- //
  3595. // Setup join button
  3596. Quad_BuddySlotBtnJoin.Visible = (
  3597. CurrentWidgetMode == "Buddies" &&
  3598. BuddiesJoinLink.existskey(BuddyLogin) && BuddiesJoinLink[BuddyLogin] != ""
  3599. );
  3600. if (Quad_BuddySlotBtnJoin.Visible)
  3601. Quad_BuddySlotBtnJoin.DataAttributeSet("manialink", BuddiesJoinLink[BuddyLogin]);
  3602.  
  3603. // ---------------------------------- //
  3604. // Display Evidence information
  3605. Label_EvidenceUser.Visible = BuddiesList_Evidence.exists(BuddyLogin);
  3606.  
  3607. // ---------------------------------- //
  3608. // Accept / refuse buttons
  3609. Quad_BuddySlotBtnAdd.Visible = (CurrentWidgetMode == "Requests" && BuddiesList_RequestFrom.exists(BuddyLogin));
  3610. Quad_BuddySlotBtnDeny.Visible = (CurrentWidgetMode == "Requests" && (BuddiesList_RequestTo.exists(BuddyLogin) || BuddiesList_RequestFrom.exists(BuddyLogin)));
  3611. Quad_BuddySlotBtnPlus.Visible = (CurrentWidgetMode == "Requests" && !Quad_BuddySlotBtnDeny.Visible && BuddiesList_OnServer.exists(BuddyLogin));
  3612.  
  3613. if (CurrentWidgetMode == "Requests") {
  3614. Quad_BuddySlotBtnDeny.DataAttributeSet("login", BuddyLogin);
  3615. Quad_BuddySlotBtnAdd.DataAttributeSet("login", BuddyLogin);
  3616. Quad_BuddySlotBtnPlus.DataAttributeSet("login", BuddyLogin);
  3617.  
  3618. // ---------------------------------- //
  3619. // Replacement status
  3620. declare Text ReplacementStatus;
  3621. if (Quad_BuddySlotBtnAdd.Visible)
  3622. ReplacementStatus = "Incoming invitation";
  3623. else if (Quad_BuddySlotBtnDeny.Visible)
  3624. ReplacementStatus = "Sent invitation";
  3625. else if (BuddiesList_OnServer.exists(BuddyLogin))
  3626. ReplacementStatus = "Playing on this server";
  3627.  
  3628. if (ReplacementStatus != "") Label_BuddySlotStatus.SetText(ReplacementStatus);
  3629. }
  3630.  
  3631. // ---------------------------------- //
  3632. // Kick from the group button
  3633. Quad_BuddySlotBtnKick.Visible = (CurrentWidgetMode == "Group");
  3634. if (Quad_BuddySlotBtnKick.Visible)
  3635. Quad_BuddySlotBtnKick.DataAttributeSet("command", "/kick "^BuddyLogin);
  3636.  
  3637. // ---------------------------------- //
  3638. // Mute user button
  3639. Quad_BuddySlotBtnMute.Visible = (CurrentWidgetMode == "Group");
  3640. if (Quad_BuddySlotBtnMute.Visible) {
  3641. declare BuddyIsMuted = BuddiesList_MutedUsers.exists(BuddyLogin);
  3642. Quad_BuddySlotBtnMute.ImageUrl = C_SlotMuteButtonImages[BuddyIsMuted][False];
  3643. Quad_BuddySlotBtnMute.ImageUrlFocus = C_SlotMuteButtonImages[BuddyIsMuted][True];
  3644.  
  3645. if (!BuddyIsMuted) Quad_BuddySlotBtnMute.DataAttributeSet("command", "/mute "^BuddyLogin);
  3646. else Quad_BuddySlotBtnMute.DataAttributeSet("command", "/unmute "^BuddyLogin);
  3647. }
  3648. }
  3649. }
  3650.  
  3651. // ---------------------------------- //
  3652. // Update buddies slots backgrounds colors
  3653. if (UpdateSlotsBgSlots) {
  3654. UpdateSlotsBgSlots = False;
  3655. Quad_LocalUserBgCard.BgColor = C_BuddySlotBgColors[False][Quad_LocalUserBgCard.Id == HighlightBuddySlot];
  3656.  
  3657. declare Modes = ["Buddies", "Requests"];
  3658. foreach (Frame in Frame_BuddiesSlots) {
  3659. if (!Frame.Visible) continue;
  3660. declare Quad_BuddySlotBgCard <=> (Frame.GetFirstChild("Quad_BuddySlotBgCard") as CMlQuad);
  3661. declare BuddyLogin = Quad_BuddySlotBgCard.DataAttributeGet("login");
  3662.  
  3663. declare SlotIsSelected = (Modes.exists(CurrentWidgetMode) && SelectedConversation == BuddyLogin);
  3664. Quad_BuddySlotBgCard.BgColor = C_BuddySlotBgColors[SlotIsSelected][(Quad_BuddySlotBgCard.Id == HighlightBuddySlot)];
  3665. }
  3666. }
  3667.  
  3668. // ---------------------------------- //
  3669. // Blink buddies cards on new messages
  3670. foreach (Frame in Frame_BuddiesSlots) {
  3671. if (!Frame.Visible) continue;
  3672. declare Quad_BuddySlotBgCard <=> (Frame.GetFirstChild("Quad_BuddySlotBgCard") as CMlQuad);
  3673. declare Quad_BuddySlotBlink <=> (Frame.GetFirstChild("Quad_BuddySlotBlink") as CMlQuad);
  3674. declare Label_BuddySlotNbNotice <=> (Frame.GetFirstChild("Label_BuddySlotNbNotice") as CMlLabel);
  3675. declare BuddyLogin = Quad_BuddySlotBgCard.DataAttributeGet("login");
  3676.  
  3677. // Get amount of unread messages from slot buddy
  3678. declare Integer BuddyNbUnreadMessages;
  3679. if (Persistent_Evidence_NbUnreadMessages.existskey(BuddyLogin))
  3680. BuddyNbUnreadMessages = Persistent_Evidence_NbUnreadMessages[BuddyLogin];
  3681.  
  3682. // Blink card background
  3683. if (BuddyNbUnreadMessages <= 0) Quad_BuddySlotBlink.Opacity = 0.;
  3684. else Quad_BuddySlotBlink.Opacity = Pulse(Now, 1.) / 2;
  3685.  
  3686. // Set unread messages counter
  3687. Label_BuddySlotNbNotice.Visible = (BuddyNbUnreadMessages > 0);
  3688. if (Label_BuddySlotNbNotice.Visible)
  3689. Label_BuddySlotNbNotice.Value = TL::ToText(BuddyNbUnreadMessages);
  3690. }
  3691.  
  3692. if (Frame_LocalUserSlot.Visible) {
  3693. // ---------------------------------- //
  3694. // Update local user name
  3695. if (Label_LocalUserBgName.Value != LocalUser.Name) {
  3696. Label_LocalUserBgName.SetText(LocalUser.Name);
  3697. if (CurrentWidgetMode == "Group") UpdateMessengerInfo = True;
  3698. }
  3699.  
  3700. // ---------------------------------- //
  3701. // Update local presence light
  3702. if (PrevPluginPresenceId != CurrentPluginPresenceId) {
  3703. PrevPluginPresenceId = CurrentPluginPresenceId;
  3704. if (CurrentWidgetMode == "Group") UpdateMessengerInfo = True;
  3705.  
  3706. if (CurrentPluginPresenceId >= 0) {
  3707. Quad_LocalUserPresence.BgColor = C_UserPresenceColors[CurrentPluginPresenceId];
  3708. Quad_LocalUserGlow.Visible = (CurrentPluginPresenceId > 0);
  3709. Quad_LocalUserGlow.Colorize = Quad_LocalUserPresence.BgColor;
  3710. }
  3711. }
  3712.  
  3713. // ---------------------------------- //
  3714. // Update local user status
  3715. if (Label_LocalUserStatus.Value != CurrentPluginStatusText) {
  3716. Label_LocalUserStatus.SetText(CurrentPluginStatusText);
  3717. if (CurrentWidgetMode == "Group") UpdateMessengerInfo = True;
  3718. }
  3719. }
  3720.  
  3721. // ---------------------------------- //
  3722. // Update mails amount
  3723. if (PrevLegacyMailsAmount != LegacyMailsAmount) {
  3724. PrevLegacyMailsAmount = LegacyMailsAmount;
  3725. SetModeNotificationsCount("Mailbox", LegacyMailsAmount);
  3726. }
  3727.  
  3728. // ---------------------------------- //
  3729. // Change add buddy button visibility
  3730. if (Frame_BuddyInviteCard.Visible) {
  3731. Quad_InvitePlayerButton.Visible = (Entry_InvitePlayerInput.Value != "");
  3732. }
  3733.  
  3734. // Dont update messenger if it's hidden
  3735. if (!MessengerIsOpen) continue;
  3736.  
  3737. // ---------------------------------- //
  3738. // Messenger window
  3739. // ---------------------------------- //
  3740.  
  3741. // ---------------------------------- //
  3742. // Update messenger on conversation change
  3743. if (PrevSelectedConversation != SelectedConversation) {
  3744. PrevSelectedConversation = SelectedConversation;
  3745. UpdateMessagesSlots = 2;
  3746. UpdateMessengerInfo = True;
  3747.  
  3748. // ---------------------------------- //
  3749. // Trigger window animation
  3750. if (SelectedConversation != "") {
  3751. PrevMessengerIsOpen = False;
  3752. Frame_MessengerWindow.RelativePosition.X = C_MessengerFramePosX + C_MessengerFramePosHide;
  3753. }
  3754. }
  3755.  
  3756. // ---------------------------------- //
  3757. // Update messages Slots
  3758. if (UpdateMessagesSlots > 0) {
  3759. UpdateMessagesSlots -= 1;
  3760. declare CurrentOffsetY = 0.;
  3761. Quad_SeenMessage.Hide();
  3762.  
  3763. // ---------------------------------- //
  3764. // Select active conversation
  3765. declare Text BuddyLogin;
  3766. switch (CurrentWidgetMode) {
  3767. case "Group" : BuddyLogin = "*group*";
  3768. case "Global" : BuddyLogin = "*global*";
  3769. default : BuddyLogin = SelectedConversation;
  3770. }
  3771.  
  3772. // ---------------------------------- //
  3773. // Reset unread messages amount
  3774. if (
  3775. GameIsInFocus &&
  3776. Persistent_Evidence_NbUnreadMessages.existskey(BuddyLogin) &&
  3777. Persistent_Evidence_NbUnreadMessages[BuddyLogin] > 0
  3778. ) {
  3779. Persistent_Evidence_NbUnreadMessages[BuddyLogin] = 0;
  3780. SendCustomEvent("SeenMessage", [BuddyLogin]);
  3781. }
  3782.  
  3783. // ---------------------------------- //
  3784. // Initialize conversation history array if empty
  3785. if (
  3786. !Persistent_Evidence_ChatHistoryBody.existskey(BuddyLogin) ||
  3787. !Persistent_Evidence_ChatHistorySender.existskey(BuddyLogin) ||
  3788. !Persistent_Evidence_ChatHistoryDate.existskey(BuddyLogin)
  3789. ) {
  3790. Persistent_Evidence_ChatHistoryBody[BuddyLogin] = Text[];
  3791. Persistent_Evidence_ChatHistorySender[BuddyLogin] = Text[];
  3792. Persistent_Evidence_ChatHistoryDate[BuddyLogin] = Text[];
  3793. }
  3794.  
  3795. // ---------------------------------- //
  3796. // Setup scrolling buttons
  3797. declare MessageOffset = 0;
  3798. if (MessagesOffset.existskey(BuddyLogin)) MessageOffset = MessagesOffset[BuddyLogin];
  3799.  
  3800. Quad_MessagesScrollUp.Visible = (MessageOffset < Persistent_Evidence_ChatHistoryBody[BuddyLogin].count - 1);
  3801. Quad_MessagesScrollDown.Visible = (MessageOffset > 0);
  3802.  
  3803. // ---------------------------------- //
  3804. // Format messages frames
  3805. foreach (I => Frame in Frame_MessagesSlots) {
  3806. declare Text SenderLogin;
  3807. declare Text MessageBody;
  3808. declare Text MessageTime;
  3809.  
  3810. // ---------------------------------- //
  3811. // Load message from history
  3812. if (Persistent_Evidence_ChatHistoryBody.existskey(BuddyLogin)) {
  3813. declare Index = Persistent_Evidence_ChatHistoryBody[BuddyLogin].count - 1 - I - MessageOffset;
  3814.  
  3815. if (Persistent_Evidence_ChatHistoryBody[BuddyLogin].existskey(Index))
  3816. MessageBody = Persistent_Evidence_ChatHistoryBody[BuddyLogin][Index];
  3817.  
  3818. if (Persistent_Evidence_ChatHistorySender[BuddyLogin].existskey(Index))
  3819. SenderLogin = Persistent_Evidence_ChatHistorySender[BuddyLogin][Index];
  3820.  
  3821. if (Persistent_Evidence_ChatHistoryDate[BuddyLogin].existskey(Index))
  3822. MessageTime = Persistent_Evidence_ChatHistoryDate[BuddyLogin][Index];
  3823. }
  3824.  
  3825. // ---------------------------------- //
  3826. // Show the "seen" check
  3827. Quad_SeenMessage.Visible = SenderLogin == LocalUser.Login && Persistent_Evidence_UsersSeenMessages.exists(BuddyLogin);
  3828.  
  3829. Frame.Visible = MessageBody != "";
  3830. if (!Frame.Visible) continue;
  3831.  
  3832. // ---------------------------------- //
  3833. // Load message slot elements
  3834. declare Quad_MessageSlotBgCard <=> (Frame.GetFirstChild("Quad_MessageSlotBgCard") as CMlQuad);
  3835. declare Label_MessageSlotName <=> (Frame.GetFirstChild("Label_MessageSlotName") as CMlLabel);
  3836. declare Label_MessageSlotBody <=> (Frame.GetFirstChild("Label_MessageSlotBody") as CMlLabel);
  3837. declare Label_MessageSlotTime <=> (Frame.GetFirstChild("Label_MessageSlotTime") as CMlLabel);
  3838. declare Quad_MessageSlotBtnCopy <=> (Frame.GetFirstChild("Quad_MessageSlotBtnCopy") as CMlQuad);
  3839. declare Quad_MessageSlotImage <=> (Frame.GetFirstChild("Quad_MessageSlotImage") as CMlQuad);
  3840.  
  3841. // Set sender login
  3842. declare SenderName = SenderLogin;
  3843. if (SenderLogin == "") SenderName = "$t$888Evidence";
  3844. else if (SenderLogin == LocalUser.Login) SenderName = LocalUser.Name;
  3845. else if (BuddiesName.existskey(SenderLogin)) SenderName = BuddiesName[SenderLogin];
  3846. else if (GlobalChat_BuddiesName.existskey(SenderLogin)) SenderName = GlobalChat_BuddiesName[SenderLogin];
  3847. Label_MessageSlotName.SetText(SenderName);
  3848.  
  3849. // ---------------------------------- //
  3850. // Display message as image
  3851. Quad_MessageSlotImage.Visible = TL::SubText(MessageBody, 0, 6) == "image:";
  3852. if (Quad_MessageSlotImage.Visible) {
  3853. Quad_MessageSlotImage.ImageUrl = TL::Replace(MessageBody, "image:", "");
  3854. Quad_MessageSlotImage.Size.X = Quad_MessageSlotImage.Size.Y;
  3855.  
  3856. if (TL::Find(".webm", MessageBody, False, False)) Quad_MessageSlotImage.Size.X *= 16/9.;
  3857. }
  3858.  
  3859. // ---------------------------------- //
  3860. // Message body
  3861. if (!Quad_MessageSlotImage.Visible) Label_MessageSlotBody.SetText(MessageBody);
  3862. else Label_MessageSlotBody.SetText("");
  3863.  
  3864. // ---------------------------------- //
  3865. // Message time
  3866. Label_MessageSlotTime.SetText(MessageTime);
  3867.  
  3868. // ---------------------------------- //
  3869. // Sender presence
  3870. if (SenderLogin == LocalUser.Login || SenderLogin == "") Quad_MessageSlotBgCard.BgColor = <0., 0., 0.>;
  3871. else if (BuddiesPresenceId.existskey(SenderLogin))
  3872. Quad_MessageSlotBgCard.BgColor = C_UserPresenceColors[BuddiesPresenceId[SenderLogin]];
  3873. else if (GlobalChat_BuddiesPresenceId.existskey(SenderLogin))
  3874. Quad_MessageSlotBgCard.BgColor = C_UserPresenceColors[GlobalChat_BuddiesPresenceId[SenderLogin]];
  3875. else
  3876. Quad_MessageSlotBgCard.BgColor = C_UserPresenceColors[0];
  3877.  
  3878. // ---------------------------------- //
  3879. // Copy button
  3880. declare ClipboardContent = Label_MessageSlotBody.Value;
  3881. if (Quad_MessageSlotImage.Visible) ClipboardContent = Quad_MessageSlotImage.ImageUrl;
  3882. Quad_MessageSlotBtnCopy.DataAttributeSet("clipboard", ClipboardContent);
  3883.  
  3884. // ---------------------------------- //
  3885. // Frame position
  3886. declare PositionX = 0.;
  3887. if (SenderLogin == LocalUser.Login) PositionX = 8.;
  3888. Frame.RelativePosition.X = PositionX;
  3889.  
  3890. Quad_MessageSlotBgCard.Size.Y = 3 * Label_MessageSlotBody.ValueLineCount + 4.5;
  3891. if (Quad_MessageSlotImage.Visible) Quad_MessageSlotBgCard.Size.Y += Quad_MessageSlotImage.Size.Y - 2;
  3892. CurrentOffsetY += Quad_MessageSlotBgCard.Size.Y + .5;
  3893. Frame.RelativePosition.Y = CurrentOffsetY;
  3894. }
  3895. }
  3896.  
  3897. // ---------------------------------- //
  3898. // Update info on Global Chat connection change
  3899. if (PrevGlobalChatConnectionStatus != GlobalChat_ConnectionStatus) {
  3900. PrevGlobalChatConnectionStatus = GlobalChat_ConnectionStatus;
  3901. UpdateMessengerInfo = True;
  3902. }
  3903.  
  3904. // ---------------------------------- //
  3905. // Update name and status of curreent conversation buddy
  3906. if (UpdateMessengerInfo) {
  3907. UpdateMessengerInfo = False;
  3908.  
  3909. // ---------------------------------- //
  3910. // Set conversation name
  3911. declare Text ConversationName;
  3912. declare Text ConversationLogin;
  3913.  
  3914. switch (CurrentWidgetMode) {
  3915. case "Group" : {
  3916. ConversationName = LocalUser.Name;
  3917. ConversationLogin = LocalUser.Login;
  3918. }
  3919. case "Global" : ConversationName = "Evidence Global Chat";
  3920. default : {
  3921. ConversationLogin = SelectedConversation;
  3922. if (BuddiesName.existskey(ConversationLogin)) ConversationName = BuddiesName[ConversationLogin];
  3923. else ConversationName = ConversationLogin;
  3924. }
  3925. }
  3926.  
  3927. Label_MessengerBuddyName.SetText(ConversationName);
  3928.  
  3929. // ---------------------------------- //
  3930. // Set conversation presence
  3931. declare Integer PresenceId;
  3932. switch (CurrentWidgetMode) {
  3933. case "Group" : PresenceId = CurrentPluginPresenceId;
  3934. case "Global" : PresenceId = GlobalChat_ConnectionStatus;
  3935. default : {
  3936. if (BuddiesPresenceId.existskey(ConversationLogin)) PresenceId = BuddiesPresenceId[ConversationLogin];
  3937. }
  3938. }
  3939. if (PresenceId >= 0) Quad_MessengerBuddyPresence.Colorize = C_UserPresenceColors[PresenceId];
  3940.  
  3941. // ---------------------------------- //
  3942. // Set conversation status
  3943. Label_MessengerBuddyStatus.Visible = (CurrentWidgetMode != "Group");
  3944. if (Label_MessengerBuddyStatus.Visible) {
  3945. declare StatusText = C_UserPresenceStatus[0];
  3946. switch (CurrentWidgetMode) {
  3947. case "Global" : StatusText = C_GlobalChatConnectionStatus[GlobalChat_ConnectionStatus];
  3948. default : {
  3949. if (BuddiesStatus.existskey(ConversationLogin)) StatusText = BuddiesStatus[ConversationLogin];
  3950. }
  3951. }
  3952. Label_MessengerBuddyStatus.SetText(StatusText);
  3953. }
  3954.  
  3955. // ---------------------------------- //
  3956. // Show status edition field
  3957. Entry_MessengerStatusInput.Visible = (CurrentWidgetMode == "Group");
  3958. if (Entry_MessengerStatusInput.Visible) {
  3959. Entry_MessengerStatusInput.Value = ManialinkCustomStatus;
  3960. }
  3961.  
  3962. // ---------------------------------- //
  3963. // Configure action buttons
  3964. Frame_MessengerBuddyActions.Visible = (CurrentWidgetMode != "Group" && CurrentWidgetMode != "Global");
  3965. if (Frame_MessengerBuddyActions.Visible) {
  3966. // ---------------------------------- //
  3967. // Set buddy login
  3968. Label_MessengerBuddyLogin.SetText(ConversationLogin);
  3969.  
  3970. // ---------------------------------- //
  3971. // Set buddy server name
  3972. declare ServerName = _("Not playing on a server");
  3973. if (BuddiesServerLogin.existskey(ConversationLogin) && BuddiesServerLogin[ConversationLogin] != "") {
  3974. declare ServerLogin = BuddiesServerLogin[ConversationLogin];
  3975. if (!ServersName.existskey(ServerLogin)) ServerName = ServerLogin;
  3976. else ServerName = ServersName[ServerLogin];
  3977. }
  3978. Label_MessengerBuddyServer.SetText(ServerName);
  3979.  
  3980. // ---------------------------------- //
  3981. // Setup join button
  3982. Quad_MessengerBuddyJoin.Visible = (BuddiesJoinLink.existskey(ConversationLogin) && BuddiesJoinLink[ConversationLogin] != "");
  3983. if (Quad_MessengerBuddyJoin.Visible)
  3984. Quad_MessengerBuddyJoin.DataAttributeSet("manialink", BuddiesJoinLink[ConversationLogin]);
  3985.  
  3986. // ---------------------------------- //
  3987. // Setup mail button
  3988. Quad_MessengerBuddyMail.DataAttributeSet("login", ConversationLogin);
  3989.  
  3990. // ---------------------------------- //
  3991. // Setup remove button
  3992. Quad_MessengerBuddyRemove.DataAttributeSet("login", ConversationLogin);
  3993. }
  3994. }
  3995. ***
  3996.  
  3997. // ---------------------------------- //
  3998. // Functions
  3999. // ---------------------------------- //
  4000.  
  4001. // ---------------------------------- //
  4002. /** Compute width of the label text
  4003. *
  4004. * @param _Label Label to check text length
  4005.  
  4006. * @return Width of the label text
  4007. */
  4008. Real ComputeWidth(CMlLabel _Label) {
  4009. if (_Label == Null) return 0.;
  4010. return _Label.ComputeWidth(_Label.Value) * _Label.RelativeScale;
  4011. }
  4012.  
  4013. // ---------------------------------- //
  4014. /** Change number of notifications in mode button
  4015. *
  4016. * @param _Mode Mode to set noticifications amount
  4017. * @param _NotificationsCount Amount of the notifications to set
  4018. */
  4019. Void SetModeNotificationsCount(Text _Mode, Integer _NotificationsCount) {
  4020. if (!C_ChatWidgetModes.exists(_Mode)) return;
  4021. declare Frame <=> (Page.GetFirstChild("Frame_ModeButton"^_Mode) as CMlFrame);
  4022. declare Frame_ModeButtonNotice <=> (Frame.GetFirstChild("Frame_ModeButtonNotice") as CMlFrame);
  4023. declare Label_ModeButtonNotice <=> (Frame.GetFirstChild("Label_ModeButtonNotice") as CMlLabel);
  4024.  
  4025. Frame_ModeButtonNotice.Visible = (_NotificationsCount > 0);
  4026. if (Frame_ModeButtonNotice.Visible)
  4027. Label_ModeButtonNotice.SetText(TL::ToText(_NotificationsCount));
  4028. }
  4029.  
  4030. // ---------------------------------- //
  4031. /** Return pulse value for animations
  4032. *
  4033. * @param _Time Time of the pulse animations
  4034. * @param _Frequency Frequency of the pulse in Hz
  4035. *
  4036. * @return Pulse animation value
  4037. */
  4038. Real Pulse(Integer _Time, Real _Frequency) {
  4039. return (ML::Sin(ML::PI() * 2 * (_Time / 1000.) * _Frequency) + 1) / 2;
  4040. }
  4041.  
  4042. // ---------------------------------- //
  4043. /** Detect and automatically format sent and received URLs
  4044. *
  4045. * @param _InputText Text to find and format URLs
  4046. *
  4047. * @return Formatted text
  4048. */
  4049. Text AutoFormatURL(Text _InputText) {
  4050. if (_InputText == "") return "";
  4051. declare TextObjects = TL::Split(" ", _InputText);
  4052. declare Text OutputText;
  4053.  
  4054. foreach (I => Object in TextObjects) {
  4055. if (I > 0) OutputText ^= " ";
  4056.  
  4057. // HTTP
  4058. if (TL::SubText(Object, 0, 7) == "http://") OutputText ^= "$<$FA3$l"^Object^"$>";
  4059.  
  4060. // HTTPS
  4061. else if (TL::SubText(Object, 0, 8) == "https://") OutputText ^= "$<$FA3$l"^Object^"$>";
  4062.  
  4063. // WWW
  4064. else if (TL::SubText(Object, 0, 4) == "www.") OutputText ^= "$<$FA3$l"^Object^"$>";
  4065.  
  4066. // Manialink
  4067. else if (TL::SubText(Object, 0, 14) == "maniaplanet://") OutputText ^= "$<$6BF$h"^Object^"$>";
  4068.  
  4069. // ManiapPanet action
  4070. else if (TL::SubText(Object, 0, 1) == "#") OutputText ^= "$<$6BF$h"^Object^"$>";
  4071.  
  4072. // No address
  4073. else OutputText ^= Object;
  4074. }
  4075.  
  4076. return OutputText;
  4077. }
  4078.  
  4079. // ---------------------------------- //
  4080. /** Detect images links in specified message
  4081. *
  4082. * @param _MessageBody Text to find and images
  4083. *
  4084. * @return Array of images links
  4085. */
  4086. Text[] FindImages(Text _MessageBody) {
  4087. if (_MessageBody == "") return Text[];
  4088. declare Formats = ["jpg", "jpeg", "png", "tga", "dds", "webm"];
  4089. declare TextObjects = TL::Split(" ", TL::StripFormatting(_MessageBody));
  4090. declare Text[] Images;
  4091.  
  4092. foreach (I => Object in TextObjects) {
  4093. declare IsLink =
  4094. TL::SubText(Object, 0, 7) == "http://" ||
  4095. TL::SubText(Object, 0, 8) == "https://" ||
  4096. TL::SubText(Object, 0, 4) == "www.";
  4097. if (!IsLink) continue;
  4098.  
  4099. foreach (Format in Formats) if (TL::Find("."^Format, Object, False, False)) Images.add(Object);
  4100. }
  4101.  
  4102. return Images;
  4103. }
  4104.  
  4105. // ---------------------------------- //
  4106. /** Format message with buily-in functions
  4107. *
  4108. * @param _Message Message to format
  4109. *
  4110. * @return Formatted message
  4111. */
  4112. Text FormatMessage(Text _Message) {
  4113. if (_Message == "") return "";
  4114. declare OutputMessage = _Message;
  4115.  
  4116. // ---------------------------------- //
  4117. // Phrase links
  4118. declare persistent Boolean Persistent_Evidence_UseLinksPhrasing for Page = True;
  4119. if (Persistent_Evidence_UseLinksPhrasing) OutputMessage = AutoFormatURL(OutputMessage);
  4120.  
  4121. return OutputMessage;
  4122. }
  4123.  
  4124. // ---------------------------------- //
  4125. /** Check if the given text is date format
  4126. *
  4127. * @param _Text Text to check
  4128. *
  4129. * @return True, if the text is a date
  4130. */
  4131. Boolean TextIsDate(Text _Text) {
  4132. if (_Text == "") return False;
  4133. declare SplitDate = TL::Split("-", TL::Replace(_Text, "\n", ""));
  4134. if (SplitDate.count < 3) return False;
  4135.  
  4136. if (TL::Length(SplitDate[0]) != 4 || TL::Length(SplitDate[1]) != 2 || TL::Length(SplitDate[2]) != 2) return False;
  4137. return True;
  4138. }
  4139.  
  4140. // ---------------------------------- //
  4141. /** Check if the local date is newest
  4142. *
  4143. * @param _LocalDate Local script version
  4144. * @param _OnlineDate Online script version
  4145. *
  4146. * @return True, if date is newest
  4147. */
  4148. Boolean IsNewest(Text _LocalDate, Text _OnlineDate) {
  4149. if (!TextIsDate(_LocalDate) || !TextIsDate(_OnlineDate)) return True;
  4150. declare LocalDate = TL::Split("-", _LocalDate);
  4151. declare OnlineDate = TL::Split("-", _OnlineDate);
  4152.  
  4153. declare IsNewestYear = TL::ToInteger(LocalDate[0]) > TL::ToInteger(OnlineDate[0]);
  4154. if (IsNewestYear) return True;
  4155.  
  4156. declare IsNewestMonth = TL::ToInteger(LocalDate[1]) > TL::ToInteger(OnlineDate[1]);
  4157. if (IsNewestMonth) return True;
  4158.  
  4159. declare IsNewestDay = TL::ToInteger(LocalDate[2]) > TL::ToInteger(OnlineDate[2]);
  4160. if (IsNewestDay) return True;
  4161.  
  4162. return False;
  4163. }
  4164.  
  4165. {{{Manialink::Animations(["EaseOutCirc", "EaseInCirc"])}}}
  4166.  
  4167. // ---------------------------------- //
  4168. // Main
  4169. // ---------------------------------- //
  4170. main() {
  4171. wait(LocalUser != Null);
  4172. +++Main+++
  4173. while (True) {
  4174. yield;
  4175. LibManialink_AnimLoop();
  4176. +++Yield+++
  4177. }
  4178. }
  4179. --></script>
  4180. </manialink>""";
  4181. }
  4182.  
  4183. Text CreateManialinkNotifications() {
  4184. return """
  4185. <manialink version="2" name="Evidence:Notifications" background="0">
  4186. <framemodel id="FrameModel_Notification">
  4187. <quad posn="0 0 .5" sizen="60 7" bgcolor="000" opacity=".875" id="Quad_Background"/>
  4188. <quad sizen="60 7" style="Bgs1" substyle="BgDialogBlur" opacity="0"/>
  4189. <quad posn="-2.5 2.5" sizen="130 24" scale=".5" style="Bgs1InRace" substyle="BgButtonShadow"/>
  4190. <quad posn="1 -3.5 1" sizen="6 6" valign="center" id="Quad_NoticeIcon"/>
  4191. <label posn="8 -2 1" sizen="33.5 3" valign="center2" scale=".9" textsize="1" textemboss="1" textcolor="AAA" id="Label_NoticeHeader"/>
  4192. <label posn="8 -5 1" sizen="48.5 3" valign="center2" textsize="1" textemboss="1" textcolor="FFF" maxline="1" id="Label_NoticeBody"/>
  4193. </framemodel>
  4194.  
  4195. <frame id="Frame_Notifications" posn="-159.5 89.5">
  4196. <frameinstance modelid="FrameModel_Notification" id="Frame_Notification#0" hidden="1"/>
  4197. <frameinstance modelid="FrameModel_Notification" id="Frame_Notification#1" hidden="1"/>
  4198. <frameinstance modelid="FrameModel_Notification" id="Frame_Notification#2" hidden="1"/>
  4199. <frameinstance modelid="FrameModel_Notification" id="Frame_Notification#3" hidden="1"/>
  4200. <frameinstance modelid="FrameModel_Notification" id="Frame_Notification#4" hidden="1"/>
  4201. <frameinstance modelid="FrameModel_Notification" id="Frame_Notification#5" hidden="1"/>
  4202. <frameinstance modelid="FrameModel_Notification" id="Frame_Notification#6" hidden="1"/>
  4203. <frameinstance modelid="FrameModel_Notification" id="Frame_Notification#7" hidden="1"/>
  4204. <frameinstance modelid="FrameModel_Notification" id="Frame_Notification#8" hidden="1"/>
  4205. <frameinstance modelid="FrameModel_Notification" id="Frame_Notification#9" hidden="1"/>
  4206. </frame>
  4207.  
  4208. <script><!--
  4209. /**
  4210. * EVIDENCE by domino54
  4211. * Notifications manialink
  4212. */
  4213.  
  4214. #Include "MathLib" as ML
  4215. #Include "TextLib" as TL
  4216.  
  4217. #Const C_MaxNbNotifications 10
  4218. #Const C_NoticeDisplayTime 6500
  4219.  
  4220. // ---------------------------------- //
  4221. // Main
  4222. // ---------------------------------- //
  4223. ***Main***
  4224. ***
  4225. // ---------------------------------- //
  4226. // Load interface elements
  4227. declare Frame_Notices <=> (Page.GetFirstChild("Frame_Notifications") as CMlFrame);
  4228.  
  4229. declare CMlFrame[] Frame_Notifications;
  4230. for (I, 0, C_MaxNbNotifications - 1)
  4231. Frame_Notifications.add((Page.GetFirstChild("Frame_Notification#"^I) as CMlFrame));
  4232.  
  4233. // ---------------------------------- //
  4234. // Plugin shared variables
  4235. declare Text[][] NewNotifications for Page; ///< New notifications to display
  4236. declare Boolean ToolbarActive for Page; ///< ManiaPlanet toolbar visibility
  4237.  
  4238. // ---------------------------------- //
  4239. // Variables
  4240. declare Text[][Integer] CurrentNotifications;
  4241. declare Integer[] NotificationsToRemove;
  4242. declare Boolean UpdateNotifications;
  4243.  
  4244. declare PrevToolbarActive = False;
  4245. ***
  4246.  
  4247. // ---------------------------------- //
  4248. // Yield
  4249. // ---------------------------------- //
  4250. ***Yield***
  4251. ***
  4252. // ---------------------------------- //
  4253. // Save new notifications
  4254. while (NewNotifications.count > 0) {
  4255. declare NoticeData = NewNotifications[0];
  4256. CurrentNotifications[Now] = NoticeData;
  4257. declare Removed = NewNotifications.removekey(0);
  4258. UpdateNotifications = True;
  4259.  
  4260. // ---------------------------------- //
  4261. // Remove oldest notification if there are too many
  4262. if (CurrentNotifications.count > C_MaxNbNotifications) {
  4263. declare OldestNoticeTime = 0;
  4264. foreach (Time => NoticeData in CurrentNotifications)
  4265. if (OldestNoticeTime == 0) OldestNoticeTime = Time;
  4266. CurrentNotifications.removekey(OldestNoticeTime);
  4267. }
  4268.  
  4269. // ---------------------------------- //
  4270. // Create blink animation
  4271. declare Max = CurrentNotifications.count - 1;
  4272. declare Quad_Background <=> (Frame_Notifications[Max].GetFirstChild("Quad_Background") as CMlQuad);
  4273. LibManialink_AnimStop(Quad_Background);
  4274. Quad_Background.BgColor = <.4, .7, 1.>;
  4275. LibManialink_Anim(Quad_Background, "<quad bgcolor=\"000\"/>", 1000, "EaseOutCirc");
  4276. }
  4277.  
  4278. // ---------------------------------- //
  4279. // Remove old notifications
  4280. foreach (Time => NoticeData in CurrentNotifications)
  4281. if (Now >= Time + C_NoticeDisplayTime) NotificationsToRemove.add(Time);
  4282.  
  4283. if (NotificationsToRemove.count > 0) {
  4284. UpdateNotifications = True;
  4285. for (I, 0, NotificationsToRemove.count - 1) {
  4286. declare Removed1 = CurrentNotifications.removekey(NotificationsToRemove[0]);
  4287. declare Removed2 = NotificationsToRemove.removekey(0);
  4288. }
  4289. }
  4290.  
  4291. // ---------------------------------- //
  4292. // Update notifications models
  4293. if (UpdateNotifications) {
  4294. UpdateNotifications = False;
  4295.  
  4296. // ---------------------------------- //
  4297. // Hide all frames
  4298. foreach (Frame in Frame_Notifications) {
  4299. Frame.RelativePosition.Y = 0.;
  4300. Frame.Hide();
  4301. }
  4302.  
  4303. declare I = 0;
  4304. foreach (NoticeData in CurrentNotifications) {
  4305. declare Frame = Frame_Notifications[I];
  4306. declare Label_NoticeHeader <=> (Frame.GetFirstChild("Label_NoticeHeader") as CMlLabel);
  4307. declare Label_NoticeBody <=> (Frame.GetFirstChild("Label_NoticeBody") as CMlLabel);
  4308. declare Quad_NoticeIcon <=> (Frame.GetFirstChild("Quad_NoticeIcon") as CMlQuad);
  4309.  
  4310. // ---------------------------------- //
  4311. // Set notice text
  4312. if (NoticeData.existskey(0)) Label_NoticeHeader.SetText(NoticeData[0]);
  4313. if (NoticeData.existskey(1)) Label_NoticeBody.SetText(NoticeData[1]);
  4314.  
  4315. // ---------------------------------- //
  4316. // Set icon
  4317. if (NoticeData.existskey(2)) {
  4318. if (TL::Find("|", NoticeData[2], False, False)) {
  4319. declare SplitStyle = TL::Split("|", NoticeData[2]);
  4320. Quad_NoticeIcon.Style = SplitStyle[0];
  4321. Quad_NoticeIcon.Substyle = SplitStyle[1];
  4322. Quad_NoticeIcon.ImageUrl = "";
  4323. } else {
  4324. Quad_NoticeIcon.ImageUrl = NoticeData[2];
  4325. }
  4326. }
  4327.  
  4328. // ---------------------------------- //
  4329. // Move other notifications
  4330. foreach (Frame_Notification in Frame_Notifications)
  4331. if (Frame_Notification.Visible) Frame_Notification.RelativePosition.Y -= 7.5;
  4332.  
  4333. Frame.Show();
  4334. I += 1;
  4335. }
  4336. }
  4337.  
  4338. // ---------------------------------- //
  4339. // Update notifications position
  4340. if (PrevToolbarActive != ToolbarActive) {
  4341. PrevToolbarActive = ToolbarActive;
  4342. Frame_Notices.RelativePosition.Y = 89.5;
  4343. if (ToolbarActive) Frame_Notices.RelativePosition.Y -= 6;
  4344. }
  4345. ***
  4346.  
  4347. {{{Manialink::Animations(["EaseOutCirc"])}}}
  4348.  
  4349. // ---------------------------------- //
  4350. // Main
  4351. // ---------------------------------- //
  4352. main() {
  4353. +++Main+++
  4354. while (True) {
  4355. +++Yield+++
  4356. LibManialink_AnimLoop();
  4357. yield;
  4358. }
  4359. }
  4360. --></script>
  4361. </manialink>""";
  4362. }
  4363.  
  4364. // ---------------------------------- //
  4365. // Main
  4366. // ---------------------------------- //
  4367. main() {
  4368. +++Main+++
  4369. +++GlobalChatStart+++
  4370. while (True) {
  4371. +++Yield+++
  4372. // +++GlobalChatYield+++
  4373. yield;
  4374. }
  4375. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement