Advertisement
Guest User

ACS conversation system (multiplayer) - code

a guest
Sep 28th, 2015
318
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 23.71 KB | None | 0 0
  1. #include "zcommon.acs"
  2. #library "ZZCONV"
  3.  
  4. #define CONV_MAX_PLAYERS 64
  5. #define CONV_MAX_ITEMS 64
  6. bool ConvInternal_Active[CONV_MAX_PLAYERS];
  7. int ConvInternal_Count[CONV_MAX_PLAYERS];
  8. str ConvInternal_Text[CONV_MAX_PLAYERS];
  9. str ConvInternal_Strings[CONV_MAX_PLAYERS][CONV_MAX_ITEMS];
  10. int ConvInternal_Visible[CONV_MAX_PLAYERS][CONV_MAX_ITEMS];
  11. int ConvInternal_CanActivate[CONV_MAX_PLAYERS][CONV_MAX_ITEMS];
  12. int ConvInternal_Target[CONV_MAX_PLAYERS][CONV_MAX_ITEMS];
  13. int ConvInternal_VisibleArgs[CONV_MAX_PLAYERS][CONV_MAX_ITEMS*3];
  14. int ConvInternal_CanActivateArgs[CONV_MAX_PLAYERS][CONV_MAX_ITEMS*3];
  15. int ConvInternal_TargetArgs[CONV_MAX_PLAYERS][CONV_MAX_ITEMS*3];
  16. int ConvInternal_VisibleNamed[CONV_MAX_PLAYERS][CONV_MAX_ITEMS];
  17. int ConvInternal_CanActivateNamed[CONV_MAX_PLAYERS][CONV_MAX_ITEMS];
  18. int ConvInternal_TargetNamed[CONV_MAX_PLAYERS][CONV_MAX_ITEMS];
  19. int ConvInternal_CurrentItem[CONV_MAX_PLAYERS];
  20.  
  21. script "zzconv_initializer" OPEN
  22. {
  23.     for (int i = 0; i < CONV_MAX_PLAYERS; i++)
  24.     {
  25.         ConvInternal_CurrentItem[i] = -1;
  26.         ConvInternal_Text[i] = "";
  27.         ConvInternal_Count[i] = 0;
  28.         ConvInternal_Active[i] = false;
  29.     }
  30. }
  31.  
  32. // access to 2d arrays:
  33. // PlayerNumber() * CONV_MAX_PLAYERS + item
  34. // access to 3d arrays:
  35. // PlayerNumber() * CONV_MAX_PLAYERS3 + item * 3 + arg
  36.  
  37. #define ZZCONV_VISIBLE 0
  38. #define ZZCONV_CAN_ACTIVATE 1
  39. #define ZZCONV_TARGET 2
  40.  
  41. int ciargs[3]; // this is to support old zdoom
  42. function void ConvInternal_CallScript(int where, int num)
  43. {
  44.     int j;
  45.     int scr;
  46.     str named_scr;
  47.     switch(where)
  48.     {
  49.         case ZZCONV_VISIBLE:
  50.             scr = ConvInternal_Visible[PlayerNumber()][num];
  51.             named_scr = ConvInternal_VisibleNamed[PlayerNumber()][num];
  52.             for (j = 0; j < 3; j++)
  53.                 ciargs[j] = ConvInternal_VisibleArgs[PlayerNumber()][num*3+j];
  54.             break;
  55.         case ZZCONV_CAN_ACTIVATE:
  56.             scr = ConvInternal_CanActivate[PlayerNumber()][num];
  57.             named_scr = ConvInternal_CanActivateNamed[PlayerNumber()][num];
  58.             for (j = 0; j < 3; j++)
  59.                 ciargs[j] = ConvInternal_CanActivateArgs[PlayerNumber()][num*3+j];
  60.             break;
  61.         case ZZCONV_TARGET:
  62.             scr = ConvInternal_Target[PlayerNumber()][num];
  63.             named_scr = ConvInternal_TargetNamed[PlayerNumber()][num];
  64.             for (j = 0; j < 3; j++)
  65.                 ciargs[j] = ConvInternal_TargetArgs[PlayerNumber()][num*3+j];
  66.             break;
  67.         default:
  68.             return;
  69.     }
  70.     if (scr) ACS_ExecuteAlways(scr, 0, ciargs[0], ciargs[1], ciargs[2]);
  71.     else if (strlen(named_scr)) ACS_NamedExecuteAlways(named_scr, 0, ciargs[0], ciargs[1], ciargs[2]);
  72. }
  73.  
  74. function int ConvInternal_CallScriptResult(int where, int num, int def)
  75. {
  76.     int j;
  77.     int scr;
  78.     str named_scr;
  79.     switch(where)
  80.     {
  81.         case ZZCONV_VISIBLE:
  82.             scr = ConvInternal_Visible[PlayerNumber()][num];
  83.             named_scr = ConvInternal_VisibleNamed[PlayerNumber()][num];
  84.             for (j = 0; j < 3; j++)
  85.                 ciargs[j] = ConvInternal_VisibleArgs[PlayerNumber()][num*3+j];
  86.             break;
  87.         case ZZCONV_CAN_ACTIVATE:
  88.             scr = ConvInternal_CanActivate[PlayerNumber()][num];
  89.             named_scr = ConvInternal_CanActivateNamed[PlayerNumber()][num];
  90.             for (j = 0; j < 3; j++)
  91.                 ciargs[j] = ConvInternal_CanActivateArgs[PlayerNumber()][num*3+j];
  92.             break;
  93.         case ZZCONV_TARGET:
  94.             scr = ConvInternal_Target[PlayerNumber()][num];
  95.             named_scr = ConvInternal_TargetNamed[PlayerNumber()][num];
  96.             for (j = 0; j < 3; j++)
  97.                 ciargs[j] = ConvInternal_TargetArgs[PlayerNumber()][num*3+j];
  98.             break;
  99.         default:
  100.             return def;
  101.     }
  102.     if (scr) return ACS_ExecuteWithResult(scr, ciargs[0], ciargs[1], ciargs[2]);
  103.     else if (strlen(named_scr)) ACS_NamedExecuteWithResult(named_scr, ciargs[0], ciargs[1], ciargs[2], 0);
  104.     return def;
  105. }
  106.  
  107. function int ConvInternal_StrToInt(str string)
  108. {
  109.     int integer = 0;
  110.     int string_len = strlen(string);
  111.     int mul = 1;
  112.    
  113.     for (int i = string_len-1; i >= 0; i--)
  114.     {
  115.         int ch_raw = getchar(string, i);
  116.         if (ch_raw < '0' || ch_raw > '9')
  117.         {
  118.             if (ch_raw == '-' && i == 0) // this should be the last (oops, I mean first) character
  119.             {
  120.                 return -integer;
  121.             }
  122.             else
  123.             {
  124.                 return 0;
  125.             }
  126.         }
  127.        
  128.         ch_raw -= '0';
  129.         integer += ch_raw * mul;
  130.         mul *= 10;
  131.     }
  132.    
  133.     return integer;
  134. }
  135.  
  136. function bool Conversation_CheckActiveChoice(int num)
  137. {
  138.     if (num < 0 || num >= ConvInternal_Count[PlayerNumber()])
  139.         return false;
  140.     return !!ConvInternal_CallScriptResult(ZZCONV_CAN_ACTIVATE, num, 1);
  141. }
  142.  
  143. function str ConvInternal_ParseScriptArgs(str sc, int where, int num)
  144. {
  145.     // returns new str.
  146.     str out_sc = "";
  147.     bool in_args = false;
  148.     int argc = 0;
  149.     str arg = "";
  150.    
  151.     for (int i = 0; i < strlen(sc); i++)
  152.     {
  153.         int ch = getchar(sc, i);
  154.         if (in_args)
  155.         {
  156.             if (ch == ')' || ch == ',')
  157.             {
  158.                 if (ch == ')')
  159.                 {
  160.                     in_args = false;
  161.                     break;
  162.                 }
  163.                
  164.                 // arg = current arg.
  165.                 ciargs[argc] = ConvInternal_StrToInt(arg);
  166.                 argc++;
  167.                 arg = "";
  168.                
  169.                 if (argc >= 3)
  170.                 {
  171.                     in_args = false; // more than 3 args isn't supported
  172.                     break;
  173.                 }
  174.                
  175.                 continue;
  176.             }
  177.            
  178.             arg = strparam(s:arg, c:ch);
  179.            
  180.             continue;
  181.         }
  182.         else
  183.         {
  184.             if (ch == '(')
  185.             {
  186.                 in_args = true;
  187.                 continue;
  188.             }
  189.         }
  190.        
  191.         out_sc = strparam(s:out_sc, c:ch);
  192.     }
  193.    
  194.     // argv should contain args now.
  195.     // argc should contain arg count, although we'll copy all 3 anyway
  196.     int j;
  197.     switch(where)
  198.     {
  199.         case ZZCONV_VISIBLE:
  200.             for (j = 0; j < 3; j++)
  201.                 ConvInternal_VisibleArgs[PlayerNumber()][num*3+j] = ciargs[j];
  202.             break;
  203.         case ZZCONV_CAN_ACTIVATE:
  204.             for (j = 0; j < 3; j++)
  205.                 ConvInternal_CanActivateArgs[PlayerNumber()][num*3+j] = ciargs[j];
  206.             break;
  207.         case ZZCONV_TARGET:
  208.             for (j = 0; j < 3; j++)
  209.                 ConvInternal_TargetArgs[PlayerNumber()][num*3+j] = ciargs[j];
  210.             break;
  211.         default:
  212.             break;
  213.     }
  214.    
  215.     return out_sc;
  216. }
  217.  
  218. function bool Conversation_Init(str format)
  219. {
  220.     if (ConvInternal_Active[PlayerNumber()]) // you must deactivate the current conversation EXPLICITLY to switch a conversation screen.
  221.         return false;
  222.  
  223.     format = strparam(s:format, c:'\n');
  224.  
  225.     // format is as follows:
  226.     // <anything>[parameter=value,parameter=value]
  227.     // example:
  228.     // Hi[visible=10,target=11]
  229.     int current_item = 0;
  230.     int format_len = strlen(format);
  231.    
  232.     // now item-local declarations
  233.     bool reading_text = true;
  234.     bool reading_metadata = false; // after [
  235.     bool reading_parameter = false;
  236.     bool reading_value = false;
  237.     bool reading_args = false;
  238.     str current_parameter = "";
  239.     str current_value = "";
  240.    
  241.     str current_string = "";
  242.     int current_can_activate = 0;
  243.     str current_can_activate_named = "";
  244.     int current_target = 0;
  245.     str current_target_named = "";
  246.     int current_visible = 0;
  247.     str current_visible_named = "";
  248.     bool current_default = false;
  249.    
  250.     ConvInternal_Count[PlayerNumber()] = 0;
  251.     ConvInternal_CurrentItem[PlayerNumber()] = -1; // current active item is -1, means no item is selected.
  252.     ConvInternal_Active[PlayerNumber()] = true; // activate the conversation
  253.    
  254.     for (int i = 0; i <= format_len; i++)
  255.     {
  256.         int ch = getchar(format, i);
  257.         // if not reading metadata, this is either start of metadata or actual string.
  258.         if (!reading_metadata)
  259.         {
  260.             if (ch == '\n') // save.
  261.             {
  262.                 if (reading_text)
  263.                 {
  264.                     ConvInternal_Text[PlayerNumber()] = current_string;
  265.                     reading_text = false;
  266.                     current_string = "";
  267.                 }
  268.                 else
  269.                 {
  270.                     // test logging
  271.                     /*
  272.                     print(s:"string = ", s:current_string, c:'\n',
  273.                           s:"can_activate = ", d:current_can_activate, c:'\n',
  274.                           s:"can_activate_named = ", s:current_can_activate_named, c:'\n',
  275.                           s:"target = ", d:current_target, c:'\n',
  276.                           s:"target_named = ", s:current_target_named, c:'\n',
  277.                           s:"visible = ", d:current_visible, c:'\n',
  278.                           s:"visible_named = ", s:current_visible_named);*/
  279.                    
  280.                     // make sure that this line is visible.
  281.                     ConvInternal_Strings[PlayerNumber()][current_item] = current_string;
  282.                     ConvInternal_Visible[PlayerNumber()][current_item] = current_visible;
  283.                     ConvInternal_VisibleNamed[PlayerNumber()][current_item] = current_visible_named;
  284.                     ConvInternal_CanActivate[PlayerNumber()][current_item] = current_can_activate;
  285.                     ConvInternal_CanActivateNamed[PlayerNumber()][current_item] = current_can_activate_named;
  286.                     ConvInternal_Target[PlayerNumber()][current_item] = current_target;
  287.                     ConvInternal_TargetNamed[PlayerNumber()][current_item] = current_target_named;
  288.                     if (ConvInternal_CallScriptResult(ZZCONV_VISIBLE, current_item, 1))
  289.                     {
  290.                         if (current_default)
  291.                             ConvInternal_CurrentItem[PlayerNumber()] = ConvInternal_Count[PlayerNumber()];
  292.                         ConvInternal_Count[PlayerNumber()]++;
  293.                         current_item++;
  294.                     }
  295.                    
  296.                     // nullify the temporary data
  297.                     current_string = "";
  298.                     current_can_activate = 0;
  299.                     current_can_activate_named = "";
  300.                     current_target = 0;
  301.                     current_target_named = "";
  302.                     current_visible = 0;
  303.                     current_visible_named = "";
  304.                     current_default = false;
  305.                 }
  306.             }
  307.             else if (!reading_text && ch == '[')
  308.             {
  309.                 reading_metadata = true;
  310.                 reading_parameter = true;
  311.                 reading_value = false;
  312.                 current_parameter = "";
  313.                 current_value = "";
  314.             }
  315.             else
  316.             {
  317.                 if (reading_text && ch == '\\') // we can use \\n to have multiple lines in the conversation header
  318.                 {
  319.                     if (getchar(format, i+1) == 'n')
  320.                     {
  321.                         current_string = strparam(s:current_string, c:'\n');
  322.                         i++;
  323.                         continue;
  324.                     }
  325.                 }
  326.                
  327.                 current_string = strparam(s:current_string, c:ch);
  328.             }
  329.         }
  330.         else
  331.         {
  332.             // if reading parameter, append to parameter (if not = or ] or ,)
  333.             // if reading value, append to value (if not ] or ,)
  334.             if (!reading_args && (ch == ',' || ch == ']')) // end of current parameter
  335.             {
  336.                 // current_parameter = name, current_value = value.
  337.                 if (ch == ']')
  338.                 {
  339.                     reading_metadata = false;
  340.                     reading_parameter = false;
  341.                 }
  342.                 else // ,
  343.                 {
  344.                     reading_parameter = true;
  345.                 }
  346.                
  347.                 reading_value = false;
  348.  
  349.                 // parse parameter and value here
  350.  
  351.                 //print(s:current_parameter);
  352.                 //print(s:current_value);
  353.                
  354.                 // ZDoom 2.7.x promises that we can compare strings with ==
  355.                 if (!strcmp(current_parameter, "visible"))
  356.                 {
  357.                     current_visible = ConvInternal_StrToInt(ConvInternal_ParseScriptArgs(current_value, 0, current_item));
  358.                     current_visible_named = "";
  359.                 }
  360.                 else if (!strcmp(current_parameter, "visible_named"))
  361.                 {
  362.                     current_visible = 0;
  363.                     current_visible_named = ConvInternal_ParseScriptArgs(current_value, 0, current_item);
  364.                 }
  365.                 else if (!strcmp(current_parameter, "can_activate"))
  366.                 {
  367.                     current_can_activate = ConvInternal_StrToInt(ConvInternal_ParseScriptArgs(current_value, 1, current_item));
  368.                     current_can_activate_named = "";
  369.                 }
  370.                 else if (!strcmp(current_parameter, "can_activate_named"))
  371.                 {
  372.                     current_can_activate = 0;
  373.                     current_can_activate_named = ConvInternal_ParseScriptArgs(current_value, 1, current_item);
  374.                 }
  375.                 else if (!strcmp(current_parameter, "target"))
  376.                 {
  377.                     current_target = ConvInternal_StrToInt(ConvInternal_ParseScriptArgs(current_value, 2, current_item));
  378.                     current_target_named = "";
  379.                 }
  380.                 else if (!strcmp(current_parameter, "target_named"))
  381.                 {
  382.                     current_target = 0;
  383.                     current_target_named = ConvInternal_ParseScriptArgs(current_value, 2, current_item);
  384.                 }
  385.                 else if (!strcmp(current_parameter, "default"))
  386.                 {
  387.                     current_default = true;
  388.                 }
  389.  
  390.                 current_parameter = "";
  391.                 current_value = "";
  392.             }
  393.             else if (reading_parameter)
  394.             {
  395.                 if (ch == '=')
  396.                 {
  397.                     reading_value = true;
  398.                     reading_parameter = false;
  399.                 }
  400.                 else
  401.                 {
  402.                     current_parameter = strparam(s:current_parameter, c:ch);
  403.                 }
  404.             }
  405.             else if (reading_value)
  406.             {
  407.                 if (ch == '(')
  408.                 {
  409.                     reading_args = true;
  410.                 }
  411.                 else if (ch == ')')
  412.                 {
  413.                     reading_args = false;
  414.                 }
  415.                
  416.                 current_value = strparam(s:current_value, c:ch);
  417.             }
  418.         }
  419.     }
  420.    
  421.     return true;
  422. }
  423.  
  424. function int Clamp(int what, int min, int max)
  425. {
  426.     if (what < min) return min;
  427.     if (what > max) return max;
  428.     return what;
  429. }
  430.  
  431. function int GetCVarFixed(str name)
  432. {
  433.     str c = GetCVarString(name);
  434.    
  435.     // [-|+][123123123][.123123123]
  436.    
  437.     int part_integer = 0;
  438.     int part_fractional = 0;
  439.    
  440.     // first, get the location of the dot
  441.     int i;
  442.     int dot = 0;
  443.     for (i = 0; i < StrLen(c); i++)
  444.     {
  445.         if (GetChar(c, i) == '.')
  446.             break;
  447.     }
  448.     dot = i;
  449.    
  450.     bool negative = false;
  451.    
  452.     for (i = 0; i < dot; i++)
  453.     {
  454.         if (i == 0 && (GetChar(c, i) == '-'))
  455.         {
  456.             negative = true;
  457.         }
  458.         else
  459.         {
  460.             int ch = GetChar(c, i);
  461.             ch -= 0x30;
  462.             int countOr = dot-i-1;
  463.             for (int j = 0; j < countOr; j++)
  464.                 ch *= 10;
  465.             part_integer += ch;
  466.         }
  467.     }
  468.    
  469.     for (i = dot+1; i < StrLen(c); i++)
  470.     {
  471.         ch = GetChar(c, i);
  472.         ch -= 0x30;
  473.         ch <<= 16;
  474.         countOr = i-dot;
  475.         for (j = 0; j < countOr; j++)
  476.             ch /= 10;
  477.         part_fractional += ch;
  478.     }
  479.    
  480.     return ((part_integer & 0xFFFF) << 16) | (part_fractional & 0xFFFF);
  481. }
  482.  
  483. script "zzconv_gui" ENTER
  484. {
  485.     // I have literally NO IDEA if this will compile with non-Zandronum headers.
  486.     //if (PlayerNumber() != ConsolePlayerNumber())
  487.     //    terminate;
  488.  
  489.     int repeat_timer = 0;
  490.     bool last_conv_active = false;
  491.     bool last_use_active = true; // we sometimes get the dialogue as the result of pressing use.
  492.                                   // and we don't want that use to be understood as the "conversation" use.
  493.                                  
  494.     int disp_width = 800;
  495.     int disp_height = 600;
  496.     int mouse_x = (disp_width / 2) << 16;
  497.     int mouse_y = (disp_height / 2) << 16;
  498.    
  499.     int hmt; // for cycles
  500.    
  501.     bool MouseWasDown = false;
  502.     bool MouseDown = false;
  503.    
  504.     bool UseMouse = false;
  505.    
  506.     while (true)
  507.     {
  508.         int pib = GetPlayerInput(-1, INPUT_BUTTONS);
  509.         int pim = GetPlayerInput(-1, INPUT_FORWARDMOVE);
  510.        
  511.         bool buse = (pib & BT_ATTACK) || (pib & BT_USE);
  512.         bool buse2 = (pib & BT_ATTACK); // attack is only for mouse
  513.        
  514.         if (ConvInternal_Active[PlayerNumber()])
  515.         {
  516.             // move the mouse.
  517.             // the following code is copypasted from my relatively old MouseInGZDoom.wad
  518.             int DeltaX = -GetPlayerInput(-1, INPUT_YAW);
  519.             int DeltaY = -GetPlayerInput(-1, INPUT_PITCH);
  520.             if (DeltaX != 0 || DeltaY != 0 || buse2) // either coordinate change or left click
  521.             {
  522.                 UseMouse = true;
  523.                
  524.                 int m_yaw = GetCVarFixed("m_yaw");
  525.                 int m_pitch = GetCVarFixed("m_pitch");
  526.                 int mouse_sensitivity = GetCVarFixed("mouse_sensitivity"); // ok lets not touch this part
  527.                 DeltaX = FixedDiv(DeltaX, m_yaw);
  528.                 DeltaY = FixedDiv(DeltaY, m_pitch);
  529.                 if (!StrCmp(GetCVarString("invertmouse"), "true", 4))
  530.                     DeltaY = -DeltaY;
  531.                 // если всё равно нужно mouse_sensitivity учитывать, раскомменчиваем
  532.                 DeltaX = FixedDiv(DeltaX, mouse_sensitivity);
  533.                 DeltaY = FixedDiv(DeltaY, mouse_sensitivity);
  534.                 mouse_x += DeltaX*0.05;
  535.                 mouse_y += DeltaY*0.05;
  536.                 mouse_x = Clamp(mouse_x, 0, disp_width<<16);
  537.                 mouse_y = Clamp(mouse_y, 0, disp_height<<16);
  538.                 // debug message
  539.                 //SetFont("SMALLFONT");
  540.                 //HudMessage(f:mouse_x, c:'\n', f:mouse_y, c:'\n', c:'\n', f:DeltaX, c:'\n', f:DeltaY; HUDMSG_PLAIN, 0, CR_GOLD, 0.1, 0.1, 1.0);
  541.                
  542.                 MouseWasDown = MouseDown;
  543.                 MouseDown = buse; // attack is typically mouse1, which is buse
  544.             }
  545.            
  546.             if (pim != 0) // keyboard was used
  547.             {
  548.                 MouseWasDown = false;
  549.                 MouseDown = false;
  550.                 UseMouse = false;
  551.             }
  552.            
  553.             // PROCESS MOUSE
  554.             // check if mouse was moved actively.
  555.             if (UseMouse)
  556.             {
  557.                 int moffsetx = 32.0;
  558.                 int moffsetx2 = (disp_width << 16) - 32.0;
  559.                 int moffsety = (disp_height << 16) - ConvInternal_Count[PlayerNumber()] * 16.0 - 16.0;
  560.  
  561.                 ConvInternal_CurrentItem[PlayerNumber()] = -1;
  562.                 if (mouse_x >= moffsetx && mouse_x < moffsetx2)
  563.                 {
  564.                     for (int mi = 0; mi < ConvInternal_Count[PlayerNumber()]; mi++) // god damn the un-scoped variables
  565.                     {
  566.                         int moffsety2 = moffsety + 16.0;
  567.                         if (mouse_y >= moffsety && mouse_y < moffsety2)
  568.                         {
  569.                             ConvInternal_CurrentItem[PlayerNumber()] = mi; // this line is hovered
  570.                             break;
  571.                         }
  572.                        
  573.                         moffsety += 16.0;
  574.                     }
  575.                 }
  576.             }
  577.        
  578.             SetHudSize(disp_width, disp_height, true);     
  579.        
  580.             if (!last_conv_active)
  581.             {
  582.                 // make the player immobile.
  583.                 SetPlayerProperty(0, 1, PROP_TOTALLYFROZEN);
  584.             }
  585.             last_conv_active = true;
  586.            
  587.             if (!buse) last_use_active = false;
  588.            
  589.             // draw all items. active item = gold, inactive item = gray, unselectable item = dark gray
  590.             int offsetx = 32.1;
  591.             int offsety = ((disp_height << 16) + 0.1) - ConvInternal_Count[PlayerNumber()] * 16.0 - 16.0;
  592.             bool anygold = false;
  593.             for (int i = 0; i < ConvInternal_Count[PlayerNumber()]; i++)
  594.             {
  595.                 int color = CR_BLACK;
  596.                 if (Conversation_CheckActiveChoice(i))
  597.                 {
  598.                     if (i == ConvInternal_CurrentItem[PlayerNumber()])
  599.                         color = CR_GOLD;
  600.                     else color = CR_GRAY;
  601.                 }
  602.                
  603.                 SetFont("FONT1");
  604.                 HudMessage(s:ConvInternal_Strings[PlayerNumber()][i]; HUDMSG_PLAIN, 1200+i, color, offsetx, offsety, 40.0);
  605.                
  606.                 if (color == CR_GOLD && (Timer()%35 < 17)) // mark selected active item!
  607.                 {
  608.                     HudMessage(s:">"; HUDMSG_PLAIN, 1198, CR_GOLD, offsetx-16.0, offsety, 40.0);
  609.                     anygold = true;
  610.                 }
  611.                 else if (color == CR_GOLD)
  612.                 {
  613.                     HudMessage(s:""; HUDMSG_PLAIN, 1198, CR_GOLD, offsetx-16.0, offsety, 40.0);
  614.                     anygold = true;
  615.                 }
  616.                
  617.                 offsety += 16.0;
  618.             }
  619.            
  620.             if (!anygold)
  621.                 HudMessage(s:""; HUDMSG_PLAIN, 1198, CR_GOLD, 0, 0, 0); // remove the cursor if nothing is selected
  622.            
  623.             // draw actual text
  624.             HudMessage(s:ConvInternal_Text[PlayerNumber()]; HUDMSG_PLAIN, 1199, CR_RED, offsetx, ((disp_height << 16) + 0.2) - ConvInternal_Count[PlayerNumber()] * 16.0 - 24.0, 40.0);
  625.            
  626.             // action processing (item selection, item activation)
  627.             // up button
  628.             if (pim != 0) // positive
  629.             {
  630.                 if (Timer()-repeat_timer > 5) // if we hold forward/backward keys, don't allow us to change too quickly
  631.                 {
  632.                     int change_to = -1;
  633.                    
  634.                     if (pim < 0) // down
  635.                     {
  636.                         // don't allow inactive choices
  637.                         for (int j = ConvInternal_CurrentItem[PlayerNumber()]+1; j < ConvInternal_Count[PlayerNumber()]; j++)
  638.                         {
  639.                             if (Conversation_CheckActiveChoice(j))
  640.                             {
  641.                                 change_to = j;
  642.                                 break;
  643.                             }
  644.                         }
  645.                     }
  646.                     else // up
  647.                     {
  648.                         // active item can be -1. for down its handled naturally (-1+1=0), but not here.
  649.                         int kstart;
  650.                         if (ConvInternal_CurrentItem[PlayerNumber()] < 0) kstart = ConvInternal_Count[PlayerNumber()]-1;
  651.                         else kstart = ConvInternal_CurrentItem[PlayerNumber()]-1;
  652.                         for (int k = kstart; k >= 0; k--)
  653.                         {
  654.                             if (Conversation_CheckActiveChoice(k))
  655.                             {
  656.                                 change_to = k;
  657.                                 break;
  658.                             }
  659.                         }
  660.                     }
  661.                    
  662.                     if (change_to >= 0)
  663.                         ConvInternal_CurrentItem[PlayerNumber()] = change_to;
  664.                    
  665.                     repeat_timer = Timer();
  666.                 }
  667.             }
  668.             else if (buse && !last_use_active)
  669.             {
  670.                 if (Timer()-repeat_timer > 5)
  671.                 {
  672.                     // try to activate current item
  673.                     if (Conversation_CheckActiveChoice(ConvInternal_CurrentItem[PlayerNumber()]))
  674.                     {
  675.                         // deactivate conversation
  676.                         ConvInternal_Active[PlayerNumber()] = false;
  677.                         for (hmt = 1197; hmt < 1200+CONV_MAX_ITEMS; hmt++)
  678.                             HudMessage(s:""; HUDMSG_PLAIN, hmt, CR_RED, 0, 0, 0);
  679.                         ConvInternal_CallScript(ZZCONV_TARGET, ConvInternal_CurrentItem[PlayerNumber()]);
  680.                     }
  681.                     repeat_timer = Timer();
  682.                 }
  683.             }
  684.            
  685.             // render mouse
  686.             if (UseMouse)
  687.             {
  688.                 SetFont("MOUSE");
  689.                 HudMessage(s:"A"; HUDMSG_PLAIN, 1197, CR_UNTRANSLATED, (mouse_x & 0xFFFF0000) + 0.1 - 4.0, (mouse_y & 0xFFFF0000) + 0.1 - 4.0, 40.0);
  690.             }
  691.             else
  692.             {
  693.                 HudMessage(s:""; HUDMSG_PLAIN, 1197, CR_UNTRANSLATED, 0, 0, 0);
  694.             }
  695.         }
  696.         else
  697.         {
  698.             if (last_conv_active)
  699.             {
  700.                 last_conv_active = false;
  701.                 // reset mouse
  702.                 mouse_x = ((disp_width / 2) << 16) + 0.1;
  703.                 mouse_y = ((disp_height / 2) << 16) + 0.1;
  704.                 MouseWasDown = false;
  705.                 MouseDown = false;
  706.                 UseMouse = false;
  707.                 // erase hudmessages
  708.                 for (hmt = 1197; hmt < 1200+CONV_MAX_ITEMS; hmt++)
  709.                     HudMessage(s:""; HUDMSG_PLAIN, hmt, CR_RED, 0, 0, 0);
  710.                 // make the player mobile.
  711.                 last_use_active = true;
  712.                 Delay(1); // wait for a while. this is to release attack button.
  713.                 SetPlayerProperty(0, 0, PROP_TOTALLYFROZEN);
  714.             }
  715.         }
  716.        
  717.         Delay(1);
  718.     }
  719. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement