Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include "zcommon.acs"
- #library "ZZCONV"
- #define CONV_MAX_ITEMS 64
- bool ConvInternal_Active = false;
- int ConvInternal_Count = 0;
- str ConvInternal_Text = "";
- str ConvInternal_Strings[CONV_MAX_ITEMS];
- int ConvInternal_Visible[CONV_MAX_ITEMS];
- int ConvInternal_CanActivate[CONV_MAX_ITEMS];
- int ConvInternal_Target[CONV_MAX_ITEMS];
- int ConvInternal_VisibleArgs[CONV_MAX_ITEMS*3];
- int ConvInternal_CanActivateArgs[CONV_MAX_ITEMS*3];
- int ConvInternal_TargetArgs[CONV_MAX_ITEMS*3];
- int ConvInternal_VisibleNamed[CONV_MAX_ITEMS];
- int ConvInternal_CanActivateNamed[CONV_MAX_ITEMS];
- int ConvInternal_TargetNamed[CONV_MAX_ITEMS];
- int ConvInternal_CurrentItem = -1;
- #define ZZCONV_VISIBLE 0
- #define ZZCONV_CAN_ACTIVATE 1
- #define ZZCONV_TARGET 2
- function void ConvInternal_CallScript(int where, int num)
- {
- int args[3];
- int j;
- int scr;
- str named_scr;
- switch(where)
- {
- case ZZCONV_VISIBLE:
- scr = ConvInternal_Visible[num];
- named_scr = ConvInternal_VisibleNamed[num];
- for (j = 0; j < 3; j++)
- args[j] = ConvInternal_VisibleArgs[num*3+j];
- break;
- case ZZCONV_CAN_ACTIVATE:
- scr = ConvInternal_CanActivate[num];
- named_scr = ConvInternal_CanActivateNamed[num];
- for (j = 0; j < 3; j++)
- args[j] = ConvInternal_CanActivateArgs[num*3+j];
- break;
- case ZZCONV_TARGET:
- scr = ConvInternal_Target[num];
- named_scr = ConvInternal_TargetNamed[num];
- for (j = 0; j < 3; j++)
- args[j] = ConvInternal_TargetArgs[num*3+j];
- break;
- default:
- return;
- }
- if (scr) ACS_ExecuteAlways(scr, 0, args[0], args[1], args[2]);
- else if (strlen(named_scr)) ACS_NamedExecuteAlways(named_scr, 0, args[0], args[1], args[2]);
- }
- function int ConvInternal_CallScriptResult(int where, int num, int def)
- {
- int args[3];
- int j;
- int scr;
- str named_scr;
- switch(where)
- {
- case ZZCONV_VISIBLE:
- scr = ConvInternal_Visible[num];
- named_scr = ConvInternal_VisibleNamed[num];
- for (j = 0; j < 3; j++)
- args[j] = ConvInternal_VisibleArgs[num*3+j];
- break;
- case ZZCONV_CAN_ACTIVATE:
- scr = ConvInternal_CanActivate[num];
- named_scr = ConvInternal_CanActivateNamed[num];
- for (j = 0; j < 3; j++)
- args[j] = ConvInternal_CanActivateArgs[num*3+j];
- break;
- case ZZCONV_TARGET:
- scr = ConvInternal_Target[num];
- named_scr = ConvInternal_TargetNamed[num];
- for (j = 0; j < 3; j++)
- args[j] = ConvInternal_TargetArgs[num*3+j];
- break;
- default:
- return def;
- }
- if (scr) return ACS_ExecuteWithResult(scr, 0, 0, 0);
- else if (strlen(named_scr)) ACS_NamedExecuteWithResult(named_scr, 0, 0, 0, 0);
- return def;
- }
- function int ConvInternal_StrToInt(str string)
- {
- int integer = 0;
- int string_len = strlen(string);
- int mul = 1;
- for (int i = string_len-1; i >= 0; i--)
- {
- int ch_raw = getchar(string, i);
- if (ch_raw < '0' || ch_raw > '9')
- {
- if (ch_raw == '-' && i == 0) // this should be the last (oops, I mean first) character
- {
- return -integer;
- }
- else
- {
- return 0;
- }
- }
- ch_raw -= '0';
- integer += ch_raw * mul;
- mul *= 10;
- }
- return integer;
- }
- function bool Conversation_CheckActiveChoice(int num)
- {
- return !!ConvInternal_CallScriptResult(ZZCONV_CAN_ACTIVATE, num, 1);
- }
- function str ConvInternal_ParseScriptArgs(str sc, int where, int num)
- {
- // returns new str.
- str out_sc = "";
- bool in_args = false;
- int argc = 0;
- int argv[3];
- str arg = "";
- for (int i = 0; i < strlen(sc); i++)
- {
- int ch = getchar(sc, i);
- if (in_args)
- {
- if (ch == ')' || ch == ',')
- {
- if (ch == ')')
- {
- in_args = false;
- break;
- }
- // arg = current arg.
- argv[argc] = ConvInternal_StrToInt(arg);
- argc++;
- arg = "";
- if (argc >= 3)
- {
- in_args = false; // more than 3 args isn't supported
- break;
- }
- continue;
- }
- arg = strparam(s:arg, c:ch);
- continue;
- }
- else
- {
- if (ch == '(')
- {
- in_args = true;
- continue;
- }
- }
- out_sc = strparam(s:out_sc, c:ch);
- }
- // argv should contain args now.
- // argc should contain arg count, although we'll copy all 3 anyway
- int j;
- switch(where)
- {
- case ZZCONV_VISIBLE:
- for (j = 0; j < 3; j++)
- ConvInternal_VisibleArgs[num*3+j] = argv[j];
- break;
- case ZZCONV_CAN_ACTIVATE:
- for (j = 0; j < 3; j++)
- ConvInternal_CanActivateArgs[num*3+j] = argv[j];
- break;
- case ZZCONV_TARGET:
- for (j = 0; j < 3; j++)
- ConvInternal_TargetArgs[num*3+j] = argv[j];
- break;
- default:
- break;
- }
- return out_sc;
- }
- function bool Conversation_Init(str format)
- {
- if (ConvInternal_Active) // you must deactivate the current conversation EXPLICITLY to switch a conversation screen.
- return false;
- format = strparam(s:format, c:'\n');
- // format is as follows:
- // <anything>[parameter=value,parameter=value]
- // example:
- // Hi[visible=10,target=11]
- int current_item = 0;
- int format_len = strlen(format);
- // now item-local declarations
- bool reading_text = true;
- bool reading_metadata = false; // after [
- bool reading_parameter = false;
- bool reading_value = false;
- bool reading_args = false;
- str current_parameter = "";
- str current_value = "";
- str current_string = "";
- int current_can_activate = 0;
- str current_can_activate_named = "";
- int current_target = 0;
- str current_target_named = "";
- int current_visible = 0;
- str current_visible_named = "";
- bool current_default = false;
- ConvInternal_Count = 0;
- ConvInternal_CurrentItem = -1; // current active item is -1, means no item is selected.
- ConvInternal_Active = true; // activate the conversation
- for (int i = 0; i <= format_len; i++)
- {
- int ch = getchar(format, i);
- // if not reading metadata, this is either start of metadata or actual string.
- if (!reading_metadata)
- {
- if (ch == '\n') // save.
- {
- if (reading_text)
- {
- ConvInternal_Text = current_string;
- reading_text = false;
- current_string = "";
- }
- else
- {
- // test logging
- /*
- print(s:"string = ", s:current_string, c:'\n',
- s:"can_activate = ", d:current_can_activate, c:'\n',
- s:"can_activate_named = ", s:current_can_activate_named, c:'\n',
- s:"target = ", d:current_target, c:'\n',
- s:"target_named = ", s:current_target_named, c:'\n',
- s:"visible = ", d:current_visible, c:'\n',
- s:"visible_named = ", s:current_visible_named);*/
- // make sure that this line is visible.
- ConvInternal_Strings[current_item] = current_string;
- ConvInternal_Visible[current_item] = current_visible;
- ConvInternal_VisibleNamed[current_item] = current_visible_named;
- ConvInternal_CanActivate[current_item] = current_can_activate;
- ConvInternal_CanActivateNamed[current_item] = current_can_activate_named;
- ConvInternal_Target[current_item] = current_target;
- ConvInternal_TargetNamed[current_item] = current_target_named;
- if (ConvInternal_CallScriptResult(ZZCONV_VISIBLE, current_item, 1))
- {
- if (current_default)
- ConvInternal_CurrentItem = ConvInternal_Count;
- ConvInternal_Count++;
- current_item++;
- }
- // nullify the temporary data
- current_string = "";
- current_can_activate = 0;
- current_can_activate_named = "";
- current_target = 0;
- current_target_named = "";
- current_visible = 0;
- current_visible_named = "";
- current_default = false;
- }
- }
- else if (!reading_text && ch == '[')
- {
- reading_metadata = true;
- reading_parameter = true;
- reading_value = false;
- current_parameter = "";
- current_value = "";
- }
- else
- {
- current_string = strparam(s:current_string, c:ch);
- }
- }
- else
- {
- // if reading parameter, append to parameter (if not = or ] or ,)
- // if reading value, append to value (if not ] or ,)
- if (!reading_args && (ch == ',' || ch == ']')) // end of current parameter
- {
- // current_parameter = name, current_value = value.
- if (ch == ']')
- {
- reading_metadata = false;
- reading_parameter = false;
- }
- else // ,
- {
- reading_parameter = true;
- }
- reading_value = false;
- // parse parameter and value here
- //print(s:current_parameter);
- //print(s:current_value);
- // ZDoom 2.7.x promises that we can compare strings with ==
- if (!strcmp(current_parameter, "visible"))
- {
- current_visible = ConvInternal_StrToInt(ConvInternal_ParseScriptArgs(current_value, 0, current_item));
- current_visible_named = "";
- }
- else if (!strcmp(current_parameter, "visible_named"))
- {
- current_visible = 0;
- current_visible_named = ConvInternal_ParseScriptArgs(current_value, 0, current_item);
- }
- else if (!strcmp(current_parameter, "can_activate"))
- {
- current_can_activate = ConvInternal_StrToInt(ConvInternal_ParseScriptArgs(current_value, 1, current_item));
- current_can_activate_named = "";
- }
- else if (!strcmp(current_parameter, "can_activate_named"))
- {
- current_can_activate = 0;
- current_can_activate_named = ConvInternal_ParseScriptArgs(current_value, 1, current_item);
- }
- else if (!strcmp(current_parameter, "target"))
- {
- current_target = ConvInternal_StrToInt(ConvInternal_ParseScriptArgs(current_value, 2, current_item));
- current_target_named = "";
- }
- else if (!strcmp(current_parameter, "target_named"))
- {
- current_target = 0;
- current_target_named = ConvInternal_ParseScriptArgs(current_value, 2, current_item);
- }
- else if (!strcmp(current_parameter, "default"))
- {
- current_default = true;
- }
- current_parameter = "";
- current_value = "";
- }
- else if (reading_parameter)
- {
- if (ch == '=')
- {
- reading_value = true;
- reading_parameter = false;
- }
- else
- {
- current_parameter = strparam(s:current_parameter, c:ch);
- }
- }
- else if (reading_value)
- {
- if (ch == '(')
- {
- reading_args = true;
- }
- else if (ch == ')')
- {
- reading_args = false;
- }
- current_value = strparam(s:current_value, c:ch);
- }
- }
- }
- return true;
- }
- script 999 ENTER CLIENTSIDE
- {
- // I have literally NO IDEA if this will compile with non-Zandronum headers.
- if (PlayerNumber() != ConsolePlayerNumber())
- terminate;
- int repeat_timer = 0;
- bool last_conv_active = false;
- bool last_use_active = true; // we sometimes get the dialogue as the result of pressing use.
- // and we don't want that use to be understood as the "conversation" use.
- while (true)
- {
- int pib = GetPlayerInput(-1, INPUT_BUTTONS);
- int pim = GetPlayerInput(-1, INPUT_FORWARDMOVE);
- SetHudSize(800, 600, true);
- if (ConvInternal_Active)
- {
- if (!last_conv_active)
- {
- // make the player immobile.
- SetPlayerProperty(0, 1, PROP_TOTALLYFROZEN);
- }
- last_conv_active = true;
- if (!(pib & BT_USE)) last_use_active = false;
- // draw all items. active item = gold, inactive item = gray, unselectable item = dark gray
- int offsetx = 32.1;
- int offsety = 600.1 - ConvInternal_Count * 16.0 - 16.0;
- for (int i = 0; i < ConvInternal_Count; i++)
- {
- int color = CR_BLACK;
- if (Conversation_CheckActiveChoice(i))
- {
- if (i == ConvInternal_CurrentItem)
- color = CR_GOLD;
- else color = CR_GRAY;
- }
- SetFont("BIGFONT");
- HudMessage(s:ConvInternal_Strings[i]; HUDMSG_PLAIN, 1200+i, color, offsetx, offsety, 0.03);
- if (color == CR_GOLD && (Timer()%16 < 8)) // mark selected active item!
- {
- HudMessage(c:'>'; HUDMSG_PLAIN, 1198, CR_GOLD, offsetx-16.0, offsety, 0.03);
- }
- offsety += 16.0;
- }
- // draw actual text
- HudMessage(s:ConvInternal_Text; HUDMSG_PLAIN, 1199, CR_RED, offsetx, 600.2 - ConvInternal_Count * 16.0 - 24.0, 0.03);
- // action processing (item selection, item activation)
- // up button
- if (pim != 0) // positive
- {
- if (Timer()-repeat_timer > 5) // if we hold forward/backward keys, don't allow us to change too quickly
- {
- int change_to = -1;
- if (pim < 0) // down
- {
- // don't allow inactive choices
- for (int j = ConvInternal_CurrentItem+1; j < ConvInternal_Count; j++)
- {
- if (Conversation_CheckActiveChoice(j))
- {
- change_to = j;
- break;
- }
- }
- }
- else // up
- {
- // active item can be -1. for down its handled naturally (-1+1=0), but not here.
- int kstart;
- if (ConvInternal_CurrentItem < 0) kstart = ConvInternal_Count-1;
- else kstart = ConvInternal_CurrentItem-1;
- for (int k = kstart; k >= 0; k--)
- {
- if (Conversation_CheckActiveChoice(k))
- {
- change_to = k;
- break;
- }
- }
- }
- if (change_to >= 0)
- ConvInternal_CurrentItem = change_to;
- repeat_timer = Timer();
- }
- }
- else if (pib & BT_USE && !last_use_active)
- {
- if (Timer()-repeat_timer > 5)
- {
- // try to activate current item
- if (Conversation_CheckActiveChoice(ConvInternal_CurrentItem))
- {
- // deactivate conversation
- ConvInternal_Active = false;
- ConvInternal_CallScript(ZZCONV_TARGET, ConvInternal_CurrentItem);
- }
- repeat_timer = Timer();
- }
- }
- }
- else
- {
- if (last_conv_active)
- {
- // make the player mobile.
- SetPlayerProperty(0, 0, PROP_TOTALLYFROZEN);
- last_use_active = true;
- }
- last_conv_active = false;
- }
- Delay(1);
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement