FailerZ

Labels Creator [LC]

Jan 10th, 2014
777
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 17.22 KB | None | 0 0
  1. //      /$$$$$$$$            /$$ /$$                     /$$$$$$$$
  2. //      | $$_____/          |__/| $$                    |_____ $$
  3. //      | $$        /$$$$$$  /$$| $$  /$$$$$$   /$$$$$$      /$$/
  4. //      | $$$$$    |____  $$| $$| $$ /$$__  $$ /$$__  $$    /$$/
  5. //      | $$__/     /$$$$$$$| $$| $$| $$$$$$$$| $$  \__/   /$$/
  6. //      | $$       /$$__  $$| $$| $$| $$_____/| $$        /$$/
  7. //      | $$      |  $$$$$$$| $$| $$|  $$$$$$$| $$       /$$$$$$$$
  8. //      |__/       \_______/|__/|__/ \_______/|__/      |________/
  9.  
  10. /*******************************************************************************
  11. *                        Labels Creator [LC] - by FailerZ                      *
  12. *                                  Copyright ©                                *
  13. *******************************************************************************/
  14.  
  15.  
  16. //================================ [Includes] ==================================
  17. #include          <a_samp>             //Credits to Kalcor/Kye
  18. //================================ [Defines] ===================================
  19. //Settings
  20. #define          LABELS_PATH          "/Labels.txt"
  21. #define          DELAY_DELETE         10000         //[10 Seconds] - The time before the label will be deleted (it will still saved in scriptfiles)
  22. //Colors
  23. #define          COL_GREY             "{8C8C8C}"
  24. #define          COLOR_GREY           0x8C8C8CFF
  25. #define          COL_WHITE            "{FAFAFA}"
  26. #define          COLOR_WHITE          0xFAFAFAFF
  27. #define          COL_ORANGE           "{FF6E00}"
  28. #define          COLOR_ORANGE         0xFF6E00FF
  29. #define          COL_RED              "{FF0005}"
  30. #define          COLOR_RED            0xFF0005FF
  31. #define          COL_BLUE             "{0087FF}"
  32. #define          COLOR_BLUE           0x0087FFFF
  33. #define          COL_GREEN            "{0FFF00}"
  34. #define          COLOR_GREEN          0x0FFF00FF
  35. #define          COL_PURPLE           "{B400FF}"
  36. #define          COLOR_PURPLE         0xB400FFFF
  37. #define          COL_YELLOW           "{F5FF00}"
  38. #define          COLOR_YELLOW         0xF5FF00FF
  39. //Dialogs
  40. /* Note: Change the dialog values if these number used in any other GM/FS */
  41. #define          DIALOG_STRING        1000
  42. #define          DIALOG_STRINGCON     1100
  43.  
  44. #define          DIALOG_COLOR         2000
  45. #define          DIALOG_COLORCON      2200
  46. #define          DIALOG_COLOR1        2220
  47. #define          DIALOG_COLOR2        2222
  48.  
  49. #define          DIALOG_LOS           3000
  50. //Easy Codes
  51. #define          SCM                  SendClientMessage
  52. #define          function%0(%1)       forward%0(%1); public%0(%1)
  53. #define          PRESSED(%0)          (((newkeys & (%0)) == (%0)) && ((oldkeys & (%0)) != (%0)))
  54. //Others
  55.  
  56. //================================= [Script] ===================================
  57. //Variables
  58. new IsCreating[MAX_PLAYERS], IsPickingPos[MAX_PLAYERS];
  59. new Text3D:CLabel;
  60. //------------------------------------------------------------------------------
  61. //CallBacks & Publics
  62. public OnFilterScriptInit()
  63. {
  64.     print("-----------------------------");
  65.     print("| Labels Creator by FailerZ |");
  66.     print("|           Loaded          |");
  67.     print("-----------------------------");
  68.    
  69.     Delete3DTextLabel(CLabel);
  70.     if(!fexist(LABELS_PATH))
  71.     {
  72.         new File:intro = fopen(LABELS_PATH, io_write);
  73.         if(intro)
  74.         {
  75.             fwrite(intro, "---------------------------------------------------------------");
  76.             fwrite(intro, "\r\n| * ** Labels Creator | By FailerZ | Thanks For Using It ** * |");
  77.             fwrite(intro, "\r\n|    Copy + Paste These Codes In Your GameMode/FilterScript   |");
  78.             fwrite(intro, "\r\n---------------------------------------------------------------");
  79.             fclose(intro);
  80.         }
  81.     }
  82.     return 1;
  83. }
  84. //------------------------------------------------------------------------------
  85. public OnFilterScriptExit()
  86. {
  87.     print("-----------------------------");
  88.     print("| Labels Creator by FailerZ |");
  89.     print("|         Unloaded          |");
  90.     print("-----------------------------");
  91.    
  92.     Delete3DTextLabel(CLabel);
  93.     return 1;
  94. }
  95. //------------------------------------------------------------------------------
  96. public OnPlayerDisconnect(playerid)
  97. {
  98.     ResetAllPVars(playerid);
  99.     Delete3DTextLabel(CLabel);
  100.     return 1;
  101. }
  102. //------------------------------------------------------------------------------
  103. function OnPlayerFinishCreating(playerid)
  104. {
  105.     new string[75];
  106.     GetPVarString(playerid, "LString", string, sizeof(string));
  107.    
  108.     CLabel = Create3DTextLabel(string, GetPVarInt(playerid, "LColor"), GetPVarFloat(playerid, "LPosX"), GetPVarFloat(playerid, "LPosY"), GetPVarFloat(playerid, "LPosZ"), 30.0, GetPVarInt(playerid, "LVWorld"), GetPVarInt(playerid, "LOS"));
  109.    
  110.     new File:labels = fopen(LABELS_PATH, io_append);
  111.     if(labels)
  112.     {
  113.         new str[128];
  114.         format(str, sizeof(str), "\r\nCreate3DTextLabel(\"%s\", 0x%x, %.2f, %.2f, %.2f, 30, %d, %d);", string, GetPVarInt(playerid, "LColor"), GetPVarFloat(playerid, "LPosX"), GetPVarFloat(playerid, "LPosY"), GetPVarFloat(playerid, "LPosZ"), GetPVarInt(playerid, "LVWorld"), GetPVarInt(playerid, "LOS"));
  115.         fwrite(labels, str);
  116.         fclose(labels);
  117.     }
  118.     SCM(playerid, -1, ""COL_ORANGE"[LC] "COL_BLUE"Label Successfully Created, Check Your Scriptfiles.");
  119.    
  120.     SetTimerEx("DeleteLabel", DELAY_DELETE, false,"i", playerid);
  121.     new dstr[100];
  122.     format(dstr, sizeof(dstr), ""COL_ORANGE"[LC] "COL_YELLOW"You Need To Wait %d Seconds Before You Can Create Another One.", DELAY_DELETE/1000);
  123.     SCM(playerid, -1, dstr);
  124.     return 1;
  125. }
  126. //------------------------------------------------------------------------------
  127. function DeleteLabel(playerid)
  128. {
  129.     Delete3DTextLabel(CLabel);
  130.     ResetAllPVars(playerid);
  131.     return 1;
  132. }
  133. //------------------------------------------------------------------------------
  134. public OnPlayerKeyStateChange(playerid, newkeys, oldkeys)
  135. {
  136.     if(PRESSED(KEY_SECONDARY_ATTACK))
  137.     {
  138.         if(IsPickingPos[playerid] == 1)
  139.         {
  140.             new Float:lPos[3], World;
  141.             GetPlayerPos(playerid, lPos[0], lPos[1], lPos[2]);
  142.             World = GetPlayerVirtualWorld(playerid);
  143.             SetPVarFloat(playerid, "LPosX", lPos[0]);
  144.             SetPVarFloat(playerid, "LPosY", lPos[1]);
  145.             SetPVarFloat(playerid, "LPosZ", lPos[2]);
  146.             SetPVarInt(playerid, "LVWorld", World);
  147.             IsPickingPos[playerid] = 0;
  148.             SCM(playerid, -1, ""COL_ORANGE"[LC] "COL_GREEN"Position Saved!");
  149.            
  150.             ShowPlayerDialog(playerid, DIALOG_STRING, DIALOG_STYLE_INPUT, ""COL_ORANGE"Labels Creator "COL_WHITE"- "COL_RED"By FailerZ", ""COL_WHITE"Type Your 3D Text Label String", "Ok", "Cancel");
  151.         }
  152.     }
  153.     return 1;
  154. }
  155. //================================== [Dialogs] =================================
  156. public OnDialogResponse(playerid, dialogid, response, listitem, inputtext[])
  157. {
  158.     new cstr[300];
  159.     strcat(cstr, ""COL_WHITE"White\n"COL_BLUE"Blue\n"COL_PURPLE"Purple\n"COL_RED"Red\n"COL_GREEN"Green\n"COL_ORANGE"Orange\n"COL_GREY"Grey\n"COL_YELLOW"Yellow");
  160.  
  161.     switch(dialogid)
  162.     {
  163.         case DIALOG_STRING:
  164.         {
  165.             if(response) // 'Ok'
  166.             {
  167.                 if(!strlen(inputtext)) return ShowPlayerDialog(playerid, DIALOG_STRING, DIALOG_STYLE_INPUT, ""COL_ORANGE"Labels Creator "COL_WHITE"- "COL_RED"By FailerZ", ""COL_WHITE"Type Your 3D Text Label String", "Ok", "Cancel");
  168.                 SetPVarString(playerid, "LString", inputtext);
  169.                 SCM(playerid, -1, ""COL_ORANGE"[LC] "COL_GREEN"String Saved!");
  170.                
  171.                 ShowPlayerDialog(playerid, DIALOG_COLOR, DIALOG_STYLE_LIST, ""COL_ORANGE"Labels Creator "COL_WHITE"- "COL_RED"By FailerZ", "Select Color\nType Hex Code", "Ok", "Cancel");
  172.             }
  173.             else // 'Cancel'
  174.             {
  175.                 ShowPlayerDialog(playerid, DIALOG_STRINGCON, DIALOG_STYLE_MSGBOX, ""COL_ORANGE"Labels Creator "COL_WHITE"- "COL_RED"By FailerZ", ""COL_RED"Are You Sure You Want To Cancel Creating ?", "Yes", "No");
  176.             }
  177.         }
  178. //------------------------------------------------------------------------------
  179.         case DIALOG_STRINGCON:
  180.         {
  181.             if(response) // 'Yes'
  182.             {
  183.                 ResetAllPVars(playerid);
  184.                 SCM(playerid, -1, ""COL_ORANGE"[LC] "COL_RED"You Canceled Creating.");
  185.             }
  186.             else // 'No'
  187.             {
  188.                 ShowPlayerDialog(playerid, DIALOG_STRING, DIALOG_STYLE_INPUT, ""COL_ORANGE"Labels Creator "COL_WHITE"- "COL_RED"By FailerZ", ""COL_WHITE"Type Your 3D Text Label String", "Ok", "Cancel");
  189.             }
  190.         }
  191. //------------------------------------------------------------------------------
  192.         case DIALOG_COLOR:
  193.         {
  194.             if(response) // 'Ok'
  195.             {
  196.                 switch(listitem)
  197.                 {
  198.                     case 0: // 'Select Color'
  199.                     {
  200.                         ShowPlayerDialog(playerid, DIALOG_COLOR1, DIALOG_STYLE_LIST, ""COL_ORANGE"Labels Creator "COL_WHITE"- "COL_RED"By FailerZ", cstr, "Select", "Back");
  201.                     }
  202.                    
  203.                     case 1: // 'Type Hex Code'
  204.                     {
  205.                         ShowPlayerDialog(playerid, DIALOG_COLOR2, DIALOG_STYLE_INPUT, ""COL_ORANGE"Labels Creator "COL_WHITE"- "COL_RED"By FailerZ", ""COL_WHITE"Type Your Hex Color Code Here\n"COL_YELLOW"Example: "COL_WHITE"0xFAFAFAFF", "Use", "Back");
  206.                     }
  207.                 }
  208.             }
  209.             else // 'Cancel'
  210.             {
  211.                 ShowPlayerDialog(playerid, DIALOG_COLORCON, DIALOG_STYLE_MSGBOX, ""COL_ORANGE"Labels Creator "COL_WHITE"- "COL_RED"By FailerZ", ""COL_RED"Are You Sure You Want To Cancel Creating ?", "Yes", "No");
  212.             }
  213.         }
  214. //------------------------------------------------------------------------------
  215.         case DIALOG_COLORCON:
  216.         {
  217.             if(response) // 'Yes'
  218.             {
  219.                 ResetAllPVars(playerid);
  220.                 SCM(playerid, -1, ""COL_ORANGE"[LC] "COL_RED"You Canceled Creating.");
  221.             }
  222.             else // 'No'
  223.             {
  224.                 ShowPlayerDialog(playerid, DIALOG_COLOR, DIALOG_STYLE_LIST, ""COL_ORANGE"Labels Creator "COL_WHITE"- "COL_RED"By FailerZ", "Select Color\nType Hex Code", "Ok", "Cancel");
  225.             }
  226.         }
  227. //------------------------------------------------------------------------------
  228.         case DIALOG_COLOR1:
  229.         {
  230.             if(response) // 'Select'
  231.             {
  232.                 switch(listitem)
  233.                 {
  234.                     case 0: // 'White'
  235.                     {
  236.                         SetPVarInt(playerid, "LColor", COLOR_WHITE);
  237.                         SCM(playerid, -1, ""COL_ORANGE"[LC] "COL_GREEN"Color Saved!");
  238.                        
  239.                         ShowPlayerDialog(playerid, DIALOG_LOS, DIALOG_STYLE_MSGBOX, ""COL_ORANGE"Labels Creator "COL_WHITE"- "COL_RED"By FailerZ", ""COL_WHITE"Want The Label To Be Visible Through Objects ?", "Yes", "No");
  240.                     }
  241.                    
  242.                     case 1: // 'Blue'
  243.                     {
  244.                         SetPVarInt(playerid, "LColor", COLOR_BLUE);
  245.                         SCM(playerid, -1, ""COL_ORANGE"[LC] "COL_GREEN"Color Saved!");
  246.  
  247.                         ShowPlayerDialog(playerid, DIALOG_LOS, DIALOG_STYLE_MSGBOX, ""COL_ORANGE"Labels Creator "COL_WHITE"- "COL_RED"By FailerZ", ""COL_WHITE"Want The Label To Be Visible Through Objects ?", "Yes", "No");
  248.                     }
  249.                    
  250.                     case 2: // 'Purple'
  251.                     {
  252.                         SetPVarInt(playerid, "LColor", COLOR_PURPLE);
  253.                         SCM(playerid, -1, ""COL_ORANGE"[LC] "COL_GREEN"Color Saved!");
  254.  
  255.                         ShowPlayerDialog(playerid, DIALOG_LOS, DIALOG_STYLE_MSGBOX, ""COL_ORANGE"Labels Creator "COL_WHITE"- "COL_RED"By FailerZ", ""COL_WHITE"Want The Label To Be Visible Through Objects ?", "Yes", "No");
  256.                     }
  257.                    
  258.                     case 3: // 'Red'
  259.                     {
  260.                         SetPVarInt(playerid, "LColor", COLOR_RED);
  261.                         SCM(playerid, -1, ""COL_ORANGE"[LC] "COL_GREEN"Color Saved!");
  262.  
  263.                         ShowPlayerDialog(playerid, DIALOG_LOS, DIALOG_STYLE_MSGBOX, ""COL_ORANGE"Labels Creator "COL_WHITE"- "COL_RED"By FailerZ", ""COL_WHITE"Want The Label To Be Visible Through Objects ?", "Yes", "No");
  264.                     }
  265.                    
  266.                     case 4: // 'Green'
  267.                     {
  268.                         SetPVarInt(playerid, "LColor", COLOR_GREEN);
  269.                         SCM(playerid, -1, ""COL_ORANGE"[LC] "COL_GREEN"Color Saved!");
  270.  
  271.                         ShowPlayerDialog(playerid, DIALOG_LOS, DIALOG_STYLE_MSGBOX, ""COL_ORANGE"Labels Creator "COL_WHITE"- "COL_RED"By FailerZ", ""COL_WHITE"Want The Label To Be Visible Through Objects ?", "Yes", "No");
  272.                     }
  273.                    
  274.                     case 5: // 'Orange'
  275.                     {
  276.                         SetPVarInt(playerid, "LColor", COLOR_ORANGE);
  277.                         SCM(playerid, -1, ""COL_ORANGE"[LC] "COL_GREEN"Color Saved!");
  278.  
  279.                         ShowPlayerDialog(playerid, DIALOG_LOS, DIALOG_STYLE_MSGBOX, ""COL_ORANGE"Labels Creator "COL_WHITE"- "COL_RED"By FailerZ", ""COL_WHITE"Want The Label To Be Visible Through Objects ?", "Yes", "No");
  280.                     }
  281.                    
  282.                     case 6: // 'Grey'
  283.                     {
  284.                         SetPVarInt(playerid, "LColor", COLOR_GREY);
  285.                         SCM(playerid, -1, ""COL_ORANGE"[LC] "COL_GREEN"Color Saved!");
  286.  
  287.                         ShowPlayerDialog(playerid, DIALOG_LOS, DIALOG_STYLE_MSGBOX, ""COL_ORANGE"Labels Creator "COL_WHITE"- "COL_RED"By FailerZ", ""COL_WHITE"Want The Label To Be Visible Through Objects ?", "Yes", "No");
  288.                     }
  289.                    
  290.                     case 7: // 'Yellow'
  291.                     {
  292.                         SetPVarInt(playerid, "LColor", COLOR_YELLOW);
  293.                         SCM(playerid, -1, ""COL_ORANGE"[LC] "COL_GREEN"Color Saved!");
  294.  
  295.                         ShowPlayerDialog(playerid, DIALOG_LOS, DIALOG_STYLE_MSGBOX, ""COL_ORANGE"Labels Creator "COL_WHITE"- "COL_RED"By FailerZ", ""COL_WHITE"Want The Label To Be Visible Through Objects ?", "Yes", "No");
  296.                     }
  297.                 }
  298.             }
  299.             else
  300.             {
  301.                 ShowPlayerDialog(playerid, DIALOG_COLOR, DIALOG_STYLE_LIST, ""COL_ORANGE"Labels Creator "COL_WHITE"- "COL_RED"By FailerZ", "Select Color\nType Hex Code", "Ok", "Cancel");
  302.             }
  303.         }
  304. //------------------------------------------------------------------------------
  305.         case DIALOG_COLOR2:
  306.         {
  307.             if(response) // 'Use'
  308.             {
  309.                 if(!strlen(inputtext)) return ShowPlayerDialog(playerid, DIALOG_COLOR2, DIALOG_STYLE_INPUT, ""COL_ORANGE"Labels Creator "COL_WHITE"- "COL_RED"By FailerZ", ""COL_WHITE"Type Your Hex Color Code Here\n"COL_YELLOW"Example: "COL_WHITE"0xFAFAFAFF", "Use", "Back");
  310.                 if(strlen(inputtext) < 8 || strlen(inputtext) > 10) return ShowPlayerDialog(playerid, DIALOG_COLOR2, DIALOG_STYLE_INPUT, ""COL_ORANGE"Labels Creator "COL_WHITE"- "COL_RED"By FailerZ", ""COL_WHITE"Type Your Hex Color Code Here\n"COL_YELLOW"Example: "COL_WHITE"0xFAFAFAFF", "Use", "Back");
  311.                 if(IsHex(inputtext))
  312.                 {
  313.                     SetPVarInt(playerid, "LColor", HexStr(inputtext));
  314.                     SCM(playerid, -1, ""COL_ORANGE"[LC] "COL_GREEN"Color Saved!");
  315.  
  316.                     ShowPlayerDialog(playerid, DIALOG_LOS, DIALOG_STYLE_MSGBOX, ""COL_ORANGE"Labels Creator "COL_WHITE"- "COL_RED"By FailerZ", ""COL_WHITE"Want The Label To Be Visible Through Objects ?", "Yes", "No");
  317.                 }
  318.                 else return ShowPlayerDialog(playerid, DIALOG_COLOR2, DIALOG_STYLE_INPUT, ""COL_ORANGE"Labels Creator "COL_WHITE"- "COL_RED"By FailerZ", ""COL_WHITE"Type Your Hex Color Code Here\n"COL_YELLOW"Example: "COL_WHITE"0xFAFAFAFF", "Use", "Back");
  319.             }
  320.             else // 'Back'
  321.             {
  322.                 ShowPlayerDialog(playerid, DIALOG_COLOR, DIALOG_STYLE_LIST, ""COL_ORANGE"Labels Creator "COL_WHITE"- "COL_RED"By FailerZ", "Select Color\nType Hex Code", "Ok", "Cancel");
  323.             }
  324.         }
  325. //------------------------------------------------------------------------------
  326.         case DIALOG_LOS:
  327.         {
  328.             if(response) // 'Yes'
  329.             {
  330.                 SetPVarInt(playerid ,"LOS", 0);
  331.                 SCM(playerid, -1, ""COL_ORANGE"[LC] "COL_GREEN"LOS Saved!");
  332.                
  333.                 CallLocalFunction("OnPlayerFinishCreating", "i", playerid);
  334.             }
  335.             else // 'No'
  336.             {
  337.                 SetPVarInt(playerid ,"LOS", 1);
  338.                 SCM(playerid, -1, ""COL_ORANGE"[LC] "COL_GREEN"Line Of Sight Saved!");
  339.                
  340.                 CallLocalFunction("OnPlayerFinishCreating", "i", playerid);
  341.             }
  342.         }
  343.     }
  344.     return 1;
  345. }
  346. //================================= [Commands] =================================
  347. public OnPlayerCommandText(playerid, cmdtext[])
  348. {
  349.     if (strcmp("/label", cmdtext, true, 10) == 0)
  350.     {
  351.         if(IsPlayerInAnyVehicle(playerid)) return SCM(playerid, -1, ""COL_ORANGE"[LC] "COL_RED"You Cannot Create Labels In Car.");
  352.         if(IsCreating[playerid] == 1) return SCM(playerid, -1, ""COL_ORANGE"[LC] "COL_RED"Finish Creating Your Label First.");
  353.         if(IsPickingPos[playerid] == 1) return SCM(playerid, -1, ""COL_ORANGE"[LC] "COL_RED"Finish Choosing Position First.");
  354.         IsCreating[playerid] = 1;
  355.         IsPickingPos[playerid] = 1;
  356.         SCM(playerid, -1, ""COL_ORANGE"[LC] "COL_BLUE"Walk To The Place That You Want Your Label To Be Created At, Then.."COL_WHITE" [Press: Enter]");
  357.         return 1;
  358.     }
  359.     return 0;
  360. }
  361. //================================= [Stocks] ===================================
  362. stock ResetAllPVars(playerid)
  363. {
  364.     IsCreating[playerid] = 0;
  365.     IsPickingPos[playerid] = 0;
  366.    
  367.     DeletePVar(playerid, "LVWorld");
  368.     DeletePVar(playerid, "LPosX");
  369.     DeletePVar(playerid, "LPosY");
  370.     DeletePVar(playerid, "LPosZ");
  371.     DeletePVar(playerid, "LString");
  372.     DeletePVar(playerid, "LColor");
  373.     DeletePVar(playerid, "LOS");
  374.     return 1;
  375. }
  376. //------------------------------------------------------------------------------
  377. /* ** Credits to Y_Less ** */
  378. stock IsHex(str[])
  379. {
  380.     new
  381.     i,
  382.     cur;
  383.     if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X')) i = 2;
  384.     while (str[i])
  385.     {
  386.     cur = str[i++];
  387.     if (!(('0' <= cur <= '9') || ('A' <= cur <= 'F') || ('a' <= cur <= 'f'))) return 0;
  388.     //if ((cur < '0') || ('9' < cur < 'A') || ('F' < cur < 'a') || (cur > 'f')) return 0;
  389.     }
  390.     return 1;
  391. }
  392. //---------->
  393. stock HexStr(string[])
  394. {
  395.     new
  396.     ret,
  397.     val,
  398.     i;
  399.     if (string[0] == '0' && string[1] | 0x20 == 'x') i = 2;
  400.     for ( ; ; )
  401.     {
  402.         switch ((val = string[i++]))
  403.         {
  404.             case '0' .. '9':
  405.             {
  406.                 val -= '0';
  407.             }
  408.             case 'a' .. 'f':
  409.             {
  410.                 val -= 'a' - 10;
  411.             }
  412.             case 'A' .. 'F':
  413.             {
  414.                 val -= 'A' - 10;
  415.             }
  416.                 default: break;
  417.             }
  418.         ret = ret << 4 | val;
  419.         }
  420.     return ret;
  421. }
Advertisement
Add Comment
Please, Sign In to add comment