Advertisement
Guest User

Untitled

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