Advertisement
Guest User

Untitled

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