Advertisement
Guest User

Untitled

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