diff -urN sourceold/example-plugin/ExamplePlugin.cpp source/example-plugin/ExamplePlugin.cpp --- sourceold/example-plugin/ExamplePlugin.cpp 2018-10-27 22:04:56.123400000 +1000 +++ source/example-plugin/ExamplePlugin.cpp 2022-05-16 09:59:28.964284200 +1000 @@ -32,6 +32,7 @@ RegisterEvent(EVENT_VEHICLE_PURCHASE_HOOK,this); RegisterEvent(EVENT_CHARACTER_PURCHASE_HOOK,this); RegisterEvent(EVENT_THINK_HOOK,this); + RegisterEvent(EVENT_DIALOG_HOOK,this); } ExamplePlugin::~ExamplePlugin() @@ -50,6 +51,7 @@ UnregisterEvent(EVENT_VEHICLE_PURCHASE_HOOK,this); UnregisterEvent(EVENT_CHARACTER_PURCHASE_HOOK,this); UnregisterEvent(EVENT_THINK_HOOK,this); + UnregisterEvent(EVENT_DIALOG_HOOK,this); } void ExamplePlugin::OnLoadGlobalINISettings(INIClass *SSGMIni) @@ -135,6 +137,11 @@ Console_Output(__FUNCTION__ "\n"); } +void ExamplePlugin::OnDialog(int PlayerID, int DialogID, int ControlID, DialogMessageType MessageType) +{ + Console_Output(__FUNCTION__ "\n"); +} + void Example_Script::Created(GameObject *obj) diff -urN sourceold/example-plugin/ExamplePlugin.h source/example-plugin/ExamplePlugin.h --- sourceold/example-plugin/ExamplePlugin.h 2018-10-27 22:04:56.124400000 +1000 +++ source/example-plugin/ExamplePlugin.h 2022-05-16 09:59:28.965303200 +1000 @@ -40,6 +40,7 @@ virtual int OnVehiclePurchase(BaseControllerClass *base,GameObject *purchaser,unsigned int cost,unsigned int preset,const char *data); virtual int OnCharacterPurchase(BaseControllerClass *base,GameObject *purchaser,unsigned int cost,unsigned int preset,const char *data); virtual void OnThink(); + virtual void OnDialog(int PlayerID, int DialogID, int ControlID, DialogMessageType MessageType); }; diff -urN sourceold/scripts/ScriptedControlClass.h source/scripts/ScriptedControlClass.h --- sourceold/scripts/ScriptedControlClass.h 1970-01-01 10:00:00.000000000 +1000 +++ source/scripts/ScriptedControlClass.h 2022-05-16 09:59:28.965303200 +1000 @@ -0,0 +1,74 @@ +/* Renegade Scripts.dll + Copyright 2022 Tiberian Technologies + + This file is part of the Renegade scripts.dll + The Renegade scripts.dll is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License as published by the Free + Software Foundation; either version 2, or (at your option) any later + version. See the file COPYING for more details. + In addition, an exemption is given to allow Run Time Dynamic Linking of this code with any closed source module that does not contain code covered by this licence. + Only the source code to the module(s) containing the licenced code has to be released. +*/ + +#pragma once + +#include "engine_vector.h" +#include "vector2.h" + +class ScriptedDialogClass; +class ScriptedLabelControlClass; +class ScriptedImageControlClass; +class ScriptedButtonControlClass; +class ScriptedTextAreaControlClass; +class ScriptedCheckBoxControlClass; +class ScriptedComboBoxControlClass; +class ScriptedSliderControlClass; +class ScriptedProgressBarControlClass; + +typedef enum +{ + CONTROLTYPE_LABEL = 1, + CONTROLTYPE_IMAGE, + CONTROLTYPE_BUTTON, + CONTROLTYPE_TEXTAREA, + CONTROLTYPE_CHECKBOX, + CONTROLTYPE_COMBOBOX, + CONTROLTYPE_SLIDER, + CONTROLTYPE_PROGRESSBAR +} ControlType; + +class ScriptedControlClass +{ +public: + ScriptedControlClass(int ctl_id); + virtual ~ScriptedControlClass(); + + virtual ControlType Get_Control_Type() = 0; + virtual ScriptedLabelControlClass* As_ScriptedLabelControlClass() { return NULL; } + virtual ScriptedImageControlClass* As_ScriptedImageControlClass() { return NULL; } + virtual ScriptedButtonControlClass* As_ScriptedButtonControlClass() { return NULL; } + virtual ScriptedTextAreaControlClass* As_ScriptedTextAreaControlClass() { return NULL; } + virtual ScriptedCheckBoxControlClass* As_ScriptedCheckBoxControlClass() { return NULL; } + virtual ScriptedComboBoxControlClass* As_ScriptedComboBoxControlClass() { return NULL; } + virtual ScriptedSliderControlClass* As_ScriptedSliderControlClass() { return NULL; } + virtual ScriptedProgressBarControlClass* As_ScriptedProgressBarControlClass() { return NULL; } + + int Get_Control_ID() { return controlId; } + const Vector2& Get_Location() { return location; } + void Set_Location(Vector2& newLocation) { location = newLocation; Set_Dirty(true); } + void Set_Location(int x, int y) { location.X = (float)x; location.Y = (float)y; Set_Dirty(true); } + const Vector2& Get_Size() { return size; } + void Set_Size(Vector2& newSize) { size = newSize; Set_Dirty(true); } + void Set_Size(int width, int height) { size.X = (float)width; size.Y = (float)height; Set_Dirty(true); } + bool Is_Enabled() { return isEnabled; } + void Set_Enabled(bool enabled) { isEnabled = enabled; Set_Dirty(true); } + bool Is_Dirty() { return isDirty; } + void Set_Dirty(bool dirty) { isDirty = dirty; } + +protected: + int controlId; + Vector2 location; + Vector2 size; + bool isEnabled; + bool isDirty; +}; \ No newline at end of file diff -urN sourceold/scripts/ScriptedControls.h source/scripts/ScriptedControls.h --- sourceold/scripts/ScriptedControls.h 1970-01-01 10:00:00.000000000 +1000 +++ source/scripts/ScriptedControls.h 2022-05-16 09:59:28.966278300 +1000 @@ -0,0 +1,223 @@ +/* Renegade Scripts.dll + Copyright 2022 Tiberian Technologies + + This file is part of the Renegade scripts.dll + The Renegade scripts.dll is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License as published by the Free + Software Foundation; either version 2, or (at your option) any later + version. See the file COPYING for more details. + In addition, an exemption is given to allow Run Time Dynamic Linking of this code with any closed source module that does not contain code covered by this licence. + Only the source code to the module(s) containing the licenced code has to be released. +*/ + +#pragma once + +#include "engine_string.h" +#include "Vector3.h" +#include "ScriptedControlClass.h" + +typedef enum +{ + TEXTORIENTATION_LEFT, + TEXTORIENTATION_CENTER, + TEXTORIENTATION_RIGHT +} TextOrientation; + +typedef enum +{ + BUTTONSTYLE_BORDERED, + BUTTONSTYLE_TITLE, + BUTTONSTYLE_IMAGE +} ButtonStyle; + +/********************************************************************************/ + +class ScriptedLabelControlClass : public ScriptedControlClass +{ +public: + ScriptedLabelControlClass(int ctl_id); + + virtual ControlType Get_Control_Type() { return CONTROLTYPE_LABEL; } + virtual ScriptedLabelControlClass* As_ScriptedLabelControlClass() { return this; } + + const WideStringClass& Get_Label_Text() { return text; } + void Set_Label_Text(const wchar_t* newText) { text = newText; Set_Dirty(true); } + const Vector3& Get_Text_Color() { return color; } + void Set_Text_Color(Vector3& newColor) { color = newColor; Set_Dirty(true); } + void Set_Text_Color(int r, int g, int b) { color.X = r / 255.f; color.Y = g / 255.f; color.Z = b / 255.f; Set_Dirty(true); } + bool Get_Is_Title() { return isTitle; } + void Set_Is_Title(bool title) { isTitle = title; Set_Dirty(true); } + TextOrientation Get_Orientation() { return orientation; } + void Set_Orientation(TextOrientation newOrientation) { orientation = newOrientation; Set_Dirty(true); } +private: + WideStringClass text; + Vector3 color; + bool isTitle; + TextOrientation orientation; +}; + +/********************************************************************************/ + +class ScriptedImageControlClass : public ScriptedControlClass +{ +public: + ScriptedImageControlClass(int ctl_id); + + virtual ControlType Get_Control_Type() { return CONTROLTYPE_IMAGE; } + virtual ScriptedImageControlClass* As_ScriptedImageControlClass() { return this; } + + const StringClass& Get_Image_Name() { return imageName; } + void Set_Image_Name(const char* newName) { imageName = newName; Set_Dirty(true); } +private: + StringClass imageName; +}; + +/********************************************************************************/ + +class ScriptedButtonControlClass : public ScriptedControlClass +{ +public: + ScriptedButtonControlClass(int ctl_id); + + virtual ControlType Get_Control_Type() { return CONTROLTYPE_BUTTON; } + virtual ScriptedButtonControlClass* As_ScriptedButtonControlClass() { return this; } + + const WideStringClass& Get_Button_Text() { return buttonText; } + void Set_Button_Text(const wchar_t* newText) { buttonText = newText; Set_Dirty(true); } + const StringClass& Get_Button_Up_Image_Name() { return imageNameUp; } + void Set_Button_Up_Image_Name(const char* newName) { imageNameUp = newName; Set_Dirty(true); } + const StringClass& Get_Button_Down_Image_Name() { return imageNameDn; } + void Set_Button_Down_Image_Name(const char* newName) { imageNameDn = newName; Set_Dirty(true); } + ButtonStyle Get_Button_Style() { return style; } + void Set_Button_Style(ButtonStyle newStyle) { style = newStyle; Set_Dirty(true); } +private: + WideStringClass buttonText; + StringClass imageNameUp; + StringClass imageNameDn; + ButtonStyle style; +}; + +/********************************************************************************/ + +class ScriptedTextAreaControlClass : public ScriptedControlClass +{ +public: + ScriptedTextAreaControlClass(int ctl_id); + + virtual ControlType Get_Control_Type() { return CONTROLTYPE_TEXTAREA; } + virtual ScriptedTextAreaControlClass* As_ScriptedTextAreaControlClass() { return this; } + + int Get_Text_Limit() { return textLimit; } + void Set_Text_Limit(int newLimit) { textLimit = newLimit; Set_Dirty(true); } + bool Is_Password_Field() { return isPassword; } + void Set_Password_Field(bool password) { isPassword = password; Set_Dirty(true); } + bool Is_Numeric_Field() { return isNumeric; } + void Set_Numeric_Field(bool numeric) { isNumeric = numeric; Set_Dirty(true); } + bool Is_Automatic_Horizontal_Scroll() { return autoHorizontalScroll; } + void Set_Automatic_Horizontal_Scroll(bool scroll) { autoHorizontalScroll = scroll; Set_Dirty(true); } + const WideStringClass& Get_Text() { return textareaText; } + void Set_Text(const wchar_t* newText) { textareaText = newText; Set_Dirty(true); } + int Get_Text_Length() { return textareaText.Get_Length(); } +private: + int textLimit; + bool isNumeric; + bool isPassword; + bool autoHorizontalScroll; + WideStringClass textareaText; +}; + +/********************************************************************************/ + +class ScriptedCheckBoxControlClass : public ScriptedControlClass +{ +public: + ScriptedCheckBoxControlClass(int ctl_id); + + virtual ControlType Get_Control_Type() { return CONTROLTYPE_CHECKBOX; } + virtual ScriptedCheckBoxControlClass* As_ScriptedCheckBoxControlClass() { return this; } + + const WideStringClass& Get_Text() { return checkboxText; } + void Set_Text(const wchar_t* newText) { checkboxText = newText; Set_Dirty(true); } + bool Is_Checked() { return isChecked; } + void Set_Checked(bool checked) { isChecked = checked; Set_Dirty(true); } +private: + WideStringClass checkboxText; + bool isChecked; +}; + +/********************************************************************************/ + +class ScriptedComboBoxControlClass : public ScriptedControlClass +{ +public: + ScriptedComboBoxControlClass(int ctl_id); + + virtual ControlType Get_Control_Type() { return CONTROLTYPE_COMBOBOX; } + virtual ScriptedComboBoxControlClass* As_ScriptedComboBoxControlClass() { return this; } + + int Get_Selected_Index() { return selectedIndex; } + void Set_Selected_Index(int newIndex) { selectedIndex = newIndex; Set_Dirty(true); } + void Add_Item(const wchar_t* item) { options.Add(item); Set_Dirty(true); } + void Insert_Item(int index, const wchar_t* item) { options.Insert(index, item); Set_Dirty(true); } + int Get_Item_Count() { return options.Count(); } + const WideStringClass& Get_Item(int index) { return options[index]; } + const WideStringClass& Get_Selected_Item_Text() { return options[selectedIndex]; } + void Remove_Item(int index) { options.Delete(index); Set_Dirty(true); } + void Remove_Item(const WideStringClass& item) { options.DeleteObj(item); Set_Dirty(true); } + void Clear_Items() { options.Delete_All(); Set_Dirty(true); } +private: + DynamicVectorClass options; + int selectedIndex; +}; + +/********************************************************************************/ + +class ScriptedSliderControlClass : public ScriptedControlClass +{ +public: + ScriptedSliderControlClass(int ctl_id); + + virtual ControlType Get_Control_Type() { return CONTROLTYPE_SLIDER; } + virtual ScriptedSliderControlClass* As_ScriptedSliderControlClass() { return this; } + + int Get_Minimum() { return minVal; } + void Set_Minimum(int newMin) { minVal = newMin; Set_Dirty(true); } + int Get_Maximum() { return maxVal; } + void Set_Maximum(int newMax) { maxVal = newMax; Set_Dirty(true); } + int Get_Value() { return value; } + void Set_Value(int newValue) { value = newValue; Set_Dirty(true); } +private: + int minVal; + int maxVal; + int value; +}; + +/********************************************************************************/ + +class ScriptedProgressBarControlClass : public ScriptedControlClass +{ +public: + ScriptedProgressBarControlClass(int ctl_id); + + virtual ControlType Get_Control_Type() { return CONTROLTYPE_PROGRESSBAR; } + virtual ScriptedProgressBarControlClass* As_ScriptedProgressBarControlClass() { return this; } + + int Get_Minimum() { return minVal; } + void Set_Minimum(int newMin) { minVal = newMin; Set_Dirty(true); } + int Get_Maximum() { return maxVal; } + void Set_Maximum(int newMax) { maxVal = newMax; Set_Dirty(true); } + int Get_Progress() { return progress; } + void Set_Progress(int newProgress) { progress = newProgress > maxVal ? maxVal : newProgress < minVal ? minVal : newProgress; Set_Dirty(true); } + int Get_Step_Count() { return stepCount; } + void Set_Step_Count(int newStep) { stepCount = newStep; /* don't need to set dirty here */ } + void Increment_Value() { progress += progress + stepCount > maxVal ? maxVal - progress : stepCount; Set_Dirty(true); } + void Decrement_Value() { progress -= progress - stepCount < minVal ? progress - minVal : stepCount; Set_Dirty(true); } + +private: + int minVal; + int maxVal; + int progress; + int stepCount; +}; + +/********************************************************************************/ diff -urN sourceold/scripts/ScriptedDialogClass.h source/scripts/ScriptedDialogClass.h --- sourceold/scripts/ScriptedDialogClass.h 1970-01-01 10:00:00.000000000 +1000 +++ source/scripts/ScriptedDialogClass.h 2022-05-16 09:59:28.966795900 +1000 @@ -0,0 +1,109 @@ +/* Renegade Scripts.dll + Copyright 2022 Tiberian Technologies + + This file is part of the Renegade scripts.dll + The Renegade scripts.dll is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License as published by the Free + Software Foundation; either version 2, or (at your option) any later + version. See the file COPYING for more details. + In addition, an exemption is given to allow Run Time Dynamic Linking of this code with any closed source module that does not contain code covered by this licence. + Only the source code to the module(s) containing the licenced code has to be released. +*/ + +#pragma once + +#include "engine_string.h" +#include "engine_vector.h" +#include "vector2.h" +#include "ScriptedControlClass.h" + +class ScriptedMenuDialogClass; +class ScriptedPopupDialogClass; + +typedef enum +{ + DIALOGTYPE_POPUP, + DIALOGTYPE_MENU +} DialogType; + +typedef enum +{ + DIALOGORIENTATION_NONE, + DIALOGORIENTATION_TOPLEFT, + DIALOGORIENTATION_TOPCENTER, + DIALOGORIENTATION_TOPRIGHT, + DIALOGORIENTATION_MIDDLELEFT, + DIALOGORIENTATION_MIDDLECENTER, + DIALOGORIENTATION_MIDDLERIGHT, + DIALOGORIENTATION_BOTTOMLEFT, + DIALOGORIENTATION_BOTTOMCENTER, + DIALOGORIENTATION_BOTTOMRIGHT +} DialogOrientation; + +class ScriptedDialogClass +{ +public: + ScriptedDialogClass(int client, int dlg_id); + ~ScriptedDialogClass(); + + virtual DialogType Get_Dialog_Type() = 0; + virtual ScriptedMenuDialogClass* As_ScriptedMenuDialogClass() { return NULL; } + virtual ScriptedPopupDialogClass* As_ScriptedPopupDialogClass() { return NULL; } + + int Get_Dialog_ID() { return id; } + int Get_Client_ID() { return clientId; } + bool Is_Dirty() { return isDirty; } + void Set_Dirty(bool dirty) { isDirty = dirty; } + + virtual void Add_Control(ScriptedControlClass* control); + virtual ScriptedControlClass* Create_Control(ControlType type); + virtual ScriptedControlClass* Find_Control(int id); + virtual int Get_Control_Count(); + virtual ScriptedControlClass* Get_Control_Index(int index); + virtual void Remove_Control(int id); + virtual void Remove_Control(ScriptedControlClass* control); + virtual void Clear_Controls(); + +protected: + int id; + int clientId; + DynamicVectorClass controls; + bool isDirty; +}; + +class ScriptedMenuDialogClass : public ScriptedDialogClass +{ +public: + ScriptedMenuDialogClass(int client, int dlg_id); + ~ScriptedMenuDialogClass(); + + virtual DialogType Get_Dialog_Type() { return DIALOGTYPE_MENU; } + virtual ScriptedMenuDialogClass* As_ScriptedMenuDialogClass() { return this; } +}; + +class ScriptedPopupDialogClass : public ScriptedDialogClass +{ +public: + ScriptedPopupDialogClass(int client, int dlg_id); + ~ScriptedPopupDialogClass(); + + virtual DialogType Get_Dialog_Type() { return DIALOGTYPE_POPUP; } + virtual ScriptedPopupDialogClass* As_ScriptedPopupDialogClass() { return this; } + + DialogOrientation Get_Orientation() { return orientation; } + void Set_Orientation(DialogOrientation newOrientation) { orientation = newOrientation; Set_Dirty(true); } + const Vector2& Get_Dialog_Size() { return size; } + void Set_Dialog_Size(Vector2& newSize) { size = newSize; Set_Dirty(true); } + void Set_Dialog_Size(int width, int height) { size.X = (float)width; size.Y = (float)height; Set_Dirty(true); } + const Vector2& Get_Dialog_Location() { return location; } + void Set_Dialog_Location(Vector2& newLocation) { location = newLocation; Set_Dirty(true); } + void Set_Dialog_Location(int x, int y) { location.X = (float)x; location.Y = (float)y; Set_Dirty(true); } + const WideStringClass& Get_Dialog_Title() { return title; } + void Set_Dialog_Title(const wchar_t* newTitle) { title = newTitle; Set_Dirty(true); } + +protected: + Vector2 size; + Vector2 location; + DialogOrientation orientation; + WideStringClass title; +}; \ No newline at end of file diff -urN sourceold/scripts/dllmain.cpp source/scripts/dllmain.cpp --- sourceold/scripts/dllmain.cpp 2020-09-26 08:59:57.387156900 +1000 +++ source/scripts/dllmain.cpp 2022-05-16 09:59:28.966795900 +1000 @@ -414,6 +414,16 @@ Set_Time_Scale = (sts)Address(tt,"Set_Time_Scale"); Set_Subobject_Animation_Player = (ssap)Address(tt,"Set_Subobject_Animation_Player"); Write_File_Async = (wfa)Address(tt, "Write_File_Async"); + AddDialogHook = (adh)Address(tt, "AddDialogHook"); + RemoveDialogHook = (rdh)Address(tt, "RemoveDialogHook"); + Create_Menu_Dialog = (cmd)Address(tt, "Create_Menu_Dialog"); + Create_Popup_Dialog = (cpd)Address(tt, "Create_Popup_Dialog"); + Find_Dialog = (idlg)Address(tt, "Find_Dialog"); + Show_Dialog = (dlg)Address(tt, "Show_Dialog"); + Hide_Dialog = (dlg)Address(tt, "Hide_Dialog"); + Delete_Dialog = (dlg)Address(tt, "Delete_Dialog"); + Display_HUD_Weapon_Grant_Player = (dhwg)Address(tt, "Display_HUD_Weapon_Grant_Player"); + Display_HUD_Ammo_Grant_Player = (dhwg)Address(tt, "Display_HUD_Ammo_Grant_Player"); #ifdef SSGM SSGMGameManager::Init(); diff -urN sourceold/scripts/engine.h source/scripts/engine.h --- sourceold/scripts/engine.h 2018-10-27 22:04:56.402400000 +1000 +++ source/scripts/engine.h 2022-05-16 09:59:28.967795300 +1000 @@ -27,6 +27,7 @@ #include "engine_tdb.h" #include "engine_dmg.h" #include "engine_phys.h" +#include "engine_dialog.h" #ifndef TT #include "engine_script.h" #include "engine_tt.h" diff -urN sourceold/scripts/engine_dialog.cpp source/scripts/engine_dialog.cpp --- sourceold/scripts/engine_dialog.cpp 1970-01-01 10:00:00.000000000 +1000 +++ source/scripts/engine_dialog.cpp 2022-05-16 09:59:28.968793000 +1000 @@ -0,0 +1,213 @@ +/* Renegade Scripts.dll + Copyright 2022 Tiberian Technologies + + This file is part of the Renegade scripts.dll + The Renegade scripts.dll is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License as published by the Free + Software Foundation; either version 2, or (at your option) any later + version. See the file COPYING for more details. + In addition, an exemption is given to allow Run Time Dynamic Linking of this code with any closed source module that does not contain code covered by this licence. + Only the source code to the module(s) containing the licenced code has to be released. +*/ +#include "General.h" +#include "engine.h" +#include "engine_dialog.h" + +SCRIPTS_API ScriptedLabelControlClass* Create_Label_Control(ScriptedDialogClass* dialog, int x, int y, int width, int height, const wchar_t* text, bool title, Vector3 label_color) +{ + ScriptedLabelControlClass* control = dialog->Create_Control(CONTROLTYPE_LABEL)->As_ScriptedLabelControlClass(); + Set_Control_Bounds(control, x, y, width, height); + control->Set_Text_Color(label_color); + control->Set_Label_Text(text); + return control; +} + +SCRIPTS_API ScriptedImageControlClass* Create_Image_Control(ScriptedDialogClass* dialog, int x, int y, int width, int height, const char* texture_name) +{ + ScriptedImageControlClass* control = dialog->Create_Control(CONTROLTYPE_IMAGE)->As_ScriptedImageControlClass(); + Set_Control_Bounds(control, x, y, width, height); + control->Set_Image_Name(texture_name); + return control; +} + +SCRIPTS_API ScriptedButtonControlClass* Create_Bordered_Button_Control(ScriptedDialogClass* dialog, int x, int y, int width, int height, const wchar_t* text) +{ + ScriptedButtonControlClass* control = dialog->Create_Control(CONTROLTYPE_BUTTON)->As_ScriptedButtonControlClass(); + Set_Control_Bounds(control, x, y, width, height); + control->Set_Button_Style(BUTTONSTYLE_BORDERED); + control->Set_Button_Text(text); + return control; +} + +SCRIPTS_API ScriptedButtonControlClass* Create_Image_Button_Control(ScriptedDialogClass* dialog, int x, int y, int width, int height, const char* button_up_texture, const char* button_down_texture) +{ + ScriptedButtonControlClass* control = dialog->Create_Control(CONTROLTYPE_BUTTON)->As_ScriptedButtonControlClass(); + Set_Control_Bounds(control, x, y, width, height); + control->Set_Button_Style(BUTTONSTYLE_IMAGE); + control->Set_Button_Up_Image_Name(button_up_texture); + control->Set_Button_Down_Image_Name(button_down_texture); + return control; +} + +SCRIPTS_API ScriptedButtonControlClass* Create_Title_Button_Control(ScriptedDialogClass* dialog, int x, int y, int width, int height, const wchar_t* text) +{ + ScriptedButtonControlClass* control = dialog->Create_Control(CONTROLTYPE_BUTTON)->As_ScriptedButtonControlClass(); + Set_Control_Bounds(control, x, y, width, height); + control->Set_Button_Style(BUTTONSTYLE_TITLE); + control->Set_Button_Text(text); + return control; +} + +SCRIPTS_API ScriptedTextAreaControlClass* Create_TextArea_Control(ScriptedDialogClass* dialog, int x, int y, int width, int height, const wchar_t* default_text, int limit) +{ + ScriptedTextAreaControlClass* control = dialog->Create_Control(CONTROLTYPE_TEXTAREA)->As_ScriptedTextAreaControlClass(); + Set_Control_Bounds(control, x, y, width, height); + control->Set_Text_Limit(limit); + control->Set_Text(default_text); + return control; +} + +SCRIPTS_API ScriptedCheckBoxControlClass* Create_CheckBox_Control(ScriptedDialogClass* dialog, int x, int y, int width, int height, const wchar_t* text, bool checked) +{ + ScriptedCheckBoxControlClass* control = dialog->Create_Control(CONTROLTYPE_CHECKBOX)->As_ScriptedCheckBoxControlClass(); + Set_Control_Bounds(control, x, y, width, height); + control->Set_Text(text); + control->Set_Checked(checked); + return control; +} + +SCRIPTS_API ScriptedComboBoxControlClass* Create_ComboBox_Control(ScriptedDialogClass* dialog, int x, int y, int width, int height, DynamicVectorClass* items, int selected_index) +{ + ScriptedComboBoxControlClass* control = dialog->Create_Control(CONTROLTYPE_COMBOBOX)->As_ScriptedComboBoxControlClass(); + Set_Control_Bounds(control, x, y, width, height); + + if (items) + { + for (int i = 0; i < items->Count(); ++i) + { + control->Add_Item((*items)[i].Peek_Buffer()); + } + + control->Set_Selected_Index(selected_index); + } + + return control; +} + +SCRIPTS_API ScriptedSliderControlClass* Create_Slider_Control(ScriptedDialogClass* dialog, int x, int y, int width, int height, int value, int min, int max) +{ + ScriptedSliderControlClass* control = dialog->Create_Control(CONTROLTYPE_SLIDER)->As_ScriptedSliderControlClass(); + Set_Control_Bounds(control, x, y, width, height); + control->Set_Minimum(min); + control->Set_Maximum(max); + control->Set_Value(value); + return control; +} + +SCRIPTS_API ScriptedProgressBarControlClass* Create_ProgressBar_Control(ScriptedDialogClass* dialog, int x, int y, int width, int height, int value, int min, int max) +{ + ScriptedProgressBarControlClass* control = dialog->Create_Control(CONTROLTYPE_PROGRESSBAR)->As_ScriptedProgressBarControlClass(); + Set_Control_Bounds(control, x, y, width, height); + control->Set_Minimum(min); + control->Set_Maximum(max); + control->Set_Progress(value); + return control; +} + +SCRIPTS_API void Set_Control_Bounds(ScriptedControlClass* control, int x, int y, int width, int height) +{ + control->Set_Location(x > 400 ? 400 : (x < 0 ? 0 : x), y > 300 ? 300 : (y < 0 ? 0 : y)); + control->Set_Size(width + x > 400 ? 400 - x : width, height + y > 300 ? 300 - y : height); +} + +ScriptedPopupDialogClass* Create_Centered_Popup(int client, int width, int height, const wchar_t* title) +{ + ScriptedPopupDialogClass* dialog = Create_Popup_Dialog(client); + dialog->Set_Dialog_Size(width, height); + dialog->Set_Orientation(DIALOGORIENTATION_MIDDLECENTER); + dialog->Set_Dialog_Title(title); + return dialog; +} + +SCRIPTS_API ScriptedDialogClass* Create_Yes_No_Dialog(GameObject* obj, const wchar_t* popup_title, const wchar_t* label_text, int& yes_button_id, int& no_button_id, Vector3 label_color) +{ + if (!obj) + { + return NULL; + } + + int playerId = Get_Player_ID(obj); + if (playerId == -1) + { + return NULL; + } + + ScriptedPopupDialogClass* dialog = Create_Centered_Popup(playerId, 230, 80, popup_title); + + Create_Label_Control(dialog, 10, 10, 210, 30, label_text, false, label_color); + + ScriptedButtonControlClass* yes_button = Create_Bordered_Button_Control(dialog, 30, 50, 60, 20, L"Yes"); + ScriptedButtonControlClass* no_button = Create_Bordered_Button_Control(dialog, 140, 50, 60, 20, L"No"); + + yes_button_id = yes_button->Get_Control_ID(); + no_button_id = no_button->Get_Control_ID(); + + return dialog; +} + +SCRIPTS_API ScriptedDialogClass* Create_Yes_No_Cancel_Dialog(GameObject* obj, const wchar_t* popup_title, const wchar_t* label_text, int& yes_button_id, int& no_button_id, int& cancel_button_id, Vector3 label_color) +{ + if (!obj) + { + return NULL; + } + + int playerId = Get_Player_ID(obj); + if (playerId == -1) + { + return NULL; + } + + ScriptedPopupDialogClass* dialog = Create_Centered_Popup(playerId, 230, 80, popup_title); + + Create_Label_Control(dialog, 10, 10, 210, 30, label_text, false, label_color); + + ScriptedButtonControlClass* yes_button = Create_Bordered_Button_Control(dialog, 10, 50, 60, 20, L"Yes"); + ScriptedButtonControlClass* no_button = Create_Bordered_Button_Control(dialog, 85, 50, 60, 20, L"No"); + ScriptedButtonControlClass* cancel_button = Create_Bordered_Button_Control(dialog, 160, 50, 60, 20, L"Cancel"); + + yes_button_id = yes_button->Get_Control_ID(); + no_button_id = no_button->Get_Control_ID(); + cancel_button_id = cancel_button->Get_Control_ID(); + + return dialog; +} + +SCRIPTS_API ScriptedDialogClass* Create_User_Prompt(GameObject* obj, const wchar_t* popup_title, const wchar_t* label_text, int text_limit, int& textbox_id, int& ok_button_id, int& cancel_button_id, const wchar_t* initial_text, Vector3 label_color) +{ + if (!obj) + { + return NULL; + } + + int playerId = Get_Player_ID(obj); + if (playerId == -1) + { + return NULL; + } + + ScriptedPopupDialogClass* dialog = Create_Centered_Popup(playerId, 230, 85, popup_title); + + Create_Label_Control(dialog, 10, 10, 210, 20, label_text, false, label_color); + + ScriptedTextAreaControlClass* textarea = Create_TextArea_Control(dialog, 10, 30, 210, 15, initial_text, text_limit); + ScriptedButtonControlClass* ok_button = Create_Bordered_Button_Control(dialog, 35, 55, 60, 20, L"Okay"); + ScriptedButtonControlClass* cancel_button = Create_Bordered_Button_Control(dialog, 135, 55, 60, 20, L"Cancel"); + + textbox_id = textarea->Get_Control_ID(); + ok_button_id = ok_button->Get_Control_ID(); + cancel_button_id = cancel_button->Get_Control_ID(); + + return dialog; +} + diff -urN sourceold/scripts/engine_dialog.h source/scripts/engine_dialog.h --- sourceold/scripts/engine_dialog.h 1970-01-01 10:00:00.000000000 +1000 +++ source/scripts/engine_dialog.h 2022-05-16 09:59:28.968793000 +1000 @@ -0,0 +1,33 @@ +/* Renegade Scripts.dll + Copyright 2022 Tiberian Technologies + + This file is part of the Renegade scripts.dll + The Renegade scripts.dll is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License as published by the Free + Software Foundation; either version 2, or (at your option) any later + version. See the file COPYING for more details. + In addition, an exemption is given to allow Run Time Dynamic Linking of this code with any closed source module that does not contain code covered by this licence. + Only the source code to the module(s) containing the licenced code has to be released. +*/ +#ifndef SCRIPTS_INCLUDE__ENGINE_DIALOG_H +#define SCRIPTS_INCLUDE__ENGINE_DIALOG_H +#include "ScriptedDialogClass.h" +#include "ScriptedControlClass.h" +#include "ScriptedControls.h" + +SCRIPTS_API ScriptedLabelControlClass* Create_Label_Control(ScriptedDialogClass* dialog, int x, int y, int width, int height, const wchar_t* text, bool title = false, Vector3 label_color = Vector3(1.0f, 0.9f, 0.0f)); +SCRIPTS_API ScriptedImageControlClass* Create_Image_Control(ScriptedDialogClass* dialog, int x, int y, int width, int height, const char* texture_name); +SCRIPTS_API ScriptedButtonControlClass* Create_Bordered_Button_Control(ScriptedDialogClass* dialog, int x, int y, int width, int height, const wchar_t* text); +SCRIPTS_API ScriptedButtonControlClass* Create_Image_Button_Control(ScriptedDialogClass* dialog, int x, int y, int width, int height, const char* button_up_texture, const char* button_down_texture); +SCRIPTS_API ScriptedButtonControlClass* Create_Title_Button_Control(ScriptedDialogClass* dialog, int x, int y, int width, int height, const wchar_t* text); +SCRIPTS_API ScriptedTextAreaControlClass* Create_TextArea_Control(ScriptedDialogClass* dialog, int x, int y, int width, int height, const wchar_t* default_text = NULL, int limit = 128 /* 128 is maximum */); +SCRIPTS_API ScriptedCheckBoxControlClass* Create_CheckBox_Control(ScriptedDialogClass* dialog, int x, int y, int width, int height, const wchar_t* text, bool checked = false); +SCRIPTS_API ScriptedComboBoxControlClass* Create_ComboBox_Control(ScriptedDialogClass* dialog, int x, int y, int width, int height, DynamicVectorClass* items = NULL, int selected_index = -1); // "height" is the height of dropdown, combobox height is calculated separately. +SCRIPTS_API ScriptedSliderControlClass* Create_Slider_Control(ScriptedDialogClass* dialog, int x, int y, int width, int height, int value = 50, int min = 0, int max = 100); +SCRIPTS_API ScriptedProgressBarControlClass* Create_ProgressBar_Control(ScriptedDialogClass* dialog, int x, int y, int width, int height, int value = 50, int min = 0, int max = 100); +void SCRIPTS_API Set_Control_Bounds(ScriptedControlClass* control, int x, int y, int width, int height); +SCRIPTS_API ScriptedPopupDialogClass* Create_Centered_Popup(int client, int width, int height, const wchar_t* title = NULL); +SCRIPTS_API ScriptedDialogClass* Create_Yes_No_Dialog(GameObject* obj, const wchar_t* popup_title, const wchar_t* label_text, int& yes_button_id, int& no_button_id, Vector3 label_color = Vector3(1.0f, 0.9f, 0.0f)); +SCRIPTS_API ScriptedDialogClass* Create_Yes_No_Cancel_Dialog(GameObject* obj, const wchar_t* popup_title, const wchar_t* label_text, int& yes_button_id, int& no_button_id, int& cancel_button_id, Vector3 label_color = Vector3(1.0f, 0.9f, 0.0f)); +SCRIPTS_API ScriptedDialogClass* Create_User_Prompt(GameObject* obj, const wchar_t* popup_title, const wchar_t* label_text, int text_limit, int& textbox_id, int& ok_button_id, int& cancel_button_id, const wchar_t* initial_text = NULL, Vector3 label_color = Vector3(1.0f, 0.9f, 0.0f)); +#endif \ No newline at end of file diff -urN sourceold/scripts/engine_tt.cpp source/scripts/engine_tt.cpp --- sourceold/scripts/engine_tt.cpp 2020-09-26 08:59:57.388154600 +1000 +++ source/scripts/engine_tt.cpp 2022-05-16 09:59:28.969482700 +1000 @@ -40,6 +40,7 @@ #include "TeamPurchaseSettingsDefClass.h" #include "PurchaseSettingsDefClass.h" #include "PowerUpGameObjDef.h" +#include "ScriptedControls.h" class WideStringClass; @@ -264,6 +265,16 @@ SCRIPTS_API sts Set_Time_Scale; SCRIPTS_API ssap Set_Subobject_Animation_Player; SCRIPTS_API wfa Write_File_Async; +SCRIPTS_API adh AddDialogHook; +SCRIPTS_API rdh RemoveDialogHook; +SCRIPTS_API cmd Create_Menu_Dialog; +SCRIPTS_API cpd Create_Popup_Dialog; +SCRIPTS_API idlg Find_Dialog; +SCRIPTS_API dlg Show_Dialog; +SCRIPTS_API dlg Hide_Dialog; +SCRIPTS_API dlg Delete_Dialog; +SCRIPTS_API dhwg Display_HUD_Weapon_Grant_Player; +SCRIPTS_API dhwg Display_HUD_Ammo_Grant_Player; SCRIPTS_API bool Can_Team_Build_Vehicle(int Team) { @@ -1245,5 +1256,4 @@ PowerUpGameObjDef *def = (PowerUpGameObjDef *)Find_Named_Definition(Preset_Name); def->Grant(o,0,true); } -} - +} \ No newline at end of file diff -urN sourceold/scripts/engine_tt.h source/scripts/engine_tt.h --- sourceold/scripts/engine_tt.h 2020-09-26 08:59:57.389151600 +1000 +++ source/scripts/engine_tt.h 2022-05-16 09:59:28.971069100 +1000 @@ -19,6 +19,7 @@ #include "HashTemplateClass.h" #include "SList.h" #include "cPlayer.h" +#include "ScriptedDialogClass.h" class ConnectionAcceptanceFilter; class WideStringClass; class cScTextObj; @@ -221,6 +222,13 @@ typedef void (*sts) (float scale); typedef int (*ssap) (GameObject *player,GameObject *obj,const char *animation,bool looping,const char *subobject,float startFrame,float endFrame,bool blended); typedef int (*wfa) (const char *_FileName, const char *_Text); +typedef int (*adh) (DialogHook h); +typedef void (*rdh) (int pos); +typedef ScriptedMenuDialogClass* (*cmd) (int target); +typedef ScriptedPopupDialogClass* (*cpd) (int target); +typedef ScriptedDialogClass* (*idlg) (int id); +typedef void (*dlg) (ScriptedDialogClass* dialog); +typedef void (*dhwg) (GameObject* obj, int weapon, int rounds); SCRIPTS_API extern gpl Get_Player_List; SCRIPTS_API extern gcmi Get_Current_Map_Index; SCRIPTS_API extern gm Get_Map; @@ -443,6 +451,16 @@ SCRIPTS_API extern sts Set_Time_Scale; SCRIPTS_API extern ssap Set_Subobject_Animation_Player; SCRIPTS_API extern wfa Write_File_Async; +SCRIPTS_API extern adh AddDialogHook; +SCRIPTS_API extern rdh RemoveDialogHook; +SCRIPTS_API extern cmd Create_Menu_Dialog; +SCRIPTS_API extern cpd Create_Popup_Dialog; +SCRIPTS_API extern idlg Find_Dialog; +SCRIPTS_API extern dlg Show_Dialog; +SCRIPTS_API extern dlg Hide_Dialog; +SCRIPTS_API extern dlg Delete_Dialog; +SCRIPTS_API extern dhwg Display_HUD_Weapon_Grant_Player; +SCRIPTS_API extern dhwg Display_HUD_Ammo_Grant_Player; class SCRIPTS_API JFW_Key_Hook_Base : public ScriptImpClass { public: diff -urN sourceold/scripts/engine_ttdef.h source/scripts/engine_ttdef.h --- sourceold/scripts/engine_ttdef.h 2019-06-22 07:43:44.228400000 +1000 +++ source/scripts/engine_ttdef.h 2022-05-16 09:59:28.971713700 +1000 @@ -30,6 +30,13 @@ ANNOUNCE_TEAM, ANNOUNCE_PRIVATE, }; +enum DialogMessageType +{ + MESSAGE_TYPE_DIALOG_SHOW, + MESSAGE_TYPE_DIALOG_CLOSE, + MESSAGE_TYPE_CONTROL_MOUSE_CLICK, + MESSAGE_TYPE_CONTROL_VALUE_CHANGE +}; typedef bool (*ChatHook) (int PlayerID,TextMessageEnum Type,const wchar_t *Message,int recieverID); typedef bool (*HostHook) (int PlayerID,TextMessageEnum Type,const char *Message); typedef void (*ObjectCreateHook) (void *data,GameObject *obj); @@ -43,6 +50,7 @@ typedef bool (*RadioHook) (int PlayerType, int PlayerID, int AnnouncementID, int IconID, AnnouncementEnum AnnouncementType); typedef bool (*StockDamageHook) (PhysicalGameObj* damager, PhysicalGameObj* target, float damage, uint warheadId); typedef bool (*TtDamageHook) (PhysicalGameObj* damager, PhysicalGameObj* target, const AmmoDefinitionClass* ammo, const char* bone); +typedef void (*DialogHook) (int PlayerID, int DialogID, int ControlID, DialogMessageType MessageType); struct ObjectCreateHookStruct { ObjectCreateHook hook; diff -urN sourceold/scripts/gmgame.cpp source/scripts/gmgame.cpp --- sourceold/scripts/gmgame.cpp 2020-03-28 21:10:59.027822400 +1000 +++ source/scripts/gmgame.cpp 2022-05-16 09:59:28.972712500 +1000 @@ -285,6 +285,7 @@ AddConsoleOutputHook(ConsoleOutputHook); AddLogFileHook(LogFileHook); AddRefillHook(RefillHook); + AddDialogHook(DialogHook); } void SSGMGameManager::Shutdown() @@ -1087,6 +1088,14 @@ } } +void SSGMGameManager::DialogHook(int PlayerID, int DialogID, int ControlID, DialogMessageType MessageType) +{ + for (int i = 0; i < RegisteredEvents[EVENT_DIALOG_HOOK].Count(); i++) + { + RegisteredEvents[EVENT_DIALOG_HOOK][i]->OnDialog(PlayerID,DialogID,ControlID,MessageType); + } +} + void SSGM_Random_Weather::Created(GameObject *obj) { Range = Commands->Get_Random(0,1); diff -urN sourceold/scripts/gmgame.h source/scripts/gmgame.h --- sourceold/scripts/gmgame.h 2019-06-22 07:43:44.231400000 +1000 +++ source/scripts/gmgame.h 2022-05-16 09:59:28.972712500 +1000 @@ -38,6 +38,7 @@ static void ThinkHook(); static bool StockDamageHook(PhysicalGameObj* damager, PhysicalGameObj* target, float damage, uint warheadId); static bool TtDamageHook(PhysicalGameObj* damager, PhysicalGameObj* target, const AmmoDefinitionClass* ammo, const char* bone); + static void DialogHook(int PlayerID, int DialogID, int ControlID, DialogMessageType MessageType); }; class SSGM_Random_Weather : public ScriptImpClass { diff -urN sourceold/scripts/gmplugin.h source/scripts/gmplugin.h --- sourceold/scripts/gmplugin.h 2020-04-02 12:02:44.438361500 +1000 +++ source/scripts/gmplugin.h 2022-05-16 09:59:28.973709600 +1000 @@ -33,6 +33,7 @@ EVENT_STOCK_DAMAGE_HOOK, EVENT_TT_DAMAGE_HOOK, EVENT_PRE_LOAD_LEVEL_HOOK, + EVENT_DIALOG_HOOK, EVENT_COUNT }; @@ -59,6 +60,7 @@ virtual bool OnStockDamage(PhysicalGameObj* damager, PhysicalGameObj* target, float damage, uint warheadId) { return true; } //called on damage from clients with version <4.0 virtual bool OnTtDamage(PhysicalGameObj* damager, PhysicalGameObj* target, const AmmoDefinitionClass* ammo, const char* bone) { return true; } //called on damage from clients with version >=4.0 virtual void OnPreLoadLevel() {}; //called on level load but before the client is sent any network updates + virtual void OnDialog(int PlayerID, int DialogID, int ControlID, DialogMessageType MessageType) {}; //called on a dialog notification from client }; typedef Plugin *(*Plugin_Init_Type) (); diff -urN sourceold/scripts/jmgUtility.cpp source/scripts/jmgUtility.cpp --- sourceold/scripts/jmgUtility.cpp 2022-02-13 10:20:09.868724900 +1000 +++ source/scripts/jmgUtility.cpp 2022-05-16 09:59:28.975704300 +1000 @@ -16604,7 +16604,7 @@ int count = 0; sprintf(delim,"%s",Get_Parameter("Delim")); char *token = strtok(completedObjectives, delim); - while( token != NULL ) + while(token != NULL) { objectiveIds[count] = atoi(token); token = strtok(NULL,delim); @@ -17328,6 +17328,116 @@ Destroy_Script(); } } +void JMG_Utility_Custom_Send_Shuffled_Customs::Created(GameObject *obj) +{ + recieveMessage = Get_Int_Parameter("Custom"); + id = Get_Int_Parameter("ID"); + Param = Get_Int_Parameter("Param"); + delay = Get_Float_Parameter("Delay"); + char sendCustomsStr[256]; + sprintf(sendCustomsStr,"%s",Get_Parameter("SendCustoms")); + char delim[2]; + sprintf(delim,"%s",Get_Parameter("Delim")); + char *token = strtok(sendCustomsStr, delim); + while(token != NULL) + { + customs.Add_Tail(new int(atoi(token))); + token = strtok(NULL,delim); + } +} +void JMG_Utility_Custom_Send_Shuffled_Customs::Custom(GameObject *obj,int message,int param,GameObject *sender) +{ + if (message == recieveMessage) + { + if (customs.Get_Count() <= 0) + { + Console_Input("msg JMG_Utility_Custom_Send_Shuffled_Customs ERROR: All customs have already been sent!"); + Destroy_Script(); + return; + } + int random = customs.Get_Count() > 0 ? Commands->Get_Random_Int(0,customs.Get_Count()) : customs.Get_Count(); + int randomCustom = -1; + for (SLNode *current = customs.Head();current;current = current->Next()) + { + if (!random) + { + randomCustom = *current->Data(); + customs.Remove(current->Data()); + break; + } + random--; + } + GameObject *object = id ? (id == -1 ? sender : Commands->Find_Object(id)) : obj; + Commands->Send_Custom_Event(obj,object,randomCustom,Param == -1 ? param : Param,delay); + } +} +void JMG_Utility_Custom_Send_Shuffled_Customs_And_Ids::Created(GameObject *obj) +{ + recieveMessage = Get_Int_Parameter("Custom"); + Param = Get_Int_Parameter("Param"); + delay = Get_Float_Parameter("Delay"); + char sendCustomsStr[256]; + sprintf(sendCustomsStr,"%s",Get_Parameter("SendCustoms")); + char delim[2]; + sprintf(delim,"%s",Get_Parameter("Delim")); + char *token = strtok(sendCustomsStr, delim); + while(token != NULL) + { + customs.Add_Tail(new int(atoi(token))); + token = strtok(NULL,delim); + } + char sendIdsStr[256]; + sprintf(sendIdsStr,"%s",Get_Parameter("IDs")); + token = strtok(sendIdsStr, delim); + while(token != NULL) + { + ids.Add_Tail(new int(atoi(token))); + token = strtok(NULL,delim); + } + if (customs.Get_Count() != ids.Get_Count()) + { + Console_Input("msg JMG_Utility_Custom_Send_Shuffled_Customs_And_Ids ERROR: IDs and Customs must have the same count!"); + Destroy_Script(); + return; + } +} +void JMG_Utility_Custom_Send_Shuffled_Customs_And_Ids::Custom(GameObject *obj,int message,int param,GameObject *sender) +{ + if (message == recieveMessage) + { + if (customs.Get_Count() <= 0) + { + Console_Input("msg JMG_Utility_Custom_Send_Shuffled_Customs_And_Ids ERROR: All customs/IDs have already been sent!"); + Destroy_Script(); + return; + } + int random = customs.Get_Count() > 0 ? Commands->Get_Random_Int(0,customs.Get_Count()) : customs.Get_Count(); + int randomCustom = -1; + for (SLNode *current = customs.Head();current;current = current->Next()) + { + if (!random) + { + randomCustom = *current->Data(); + customs.Remove(current->Data()); + break; + } + random--; + } + random = ids.Get_Count() > 0 ? Commands->Get_Random_Int(0,ids.Get_Count()) : ids.Get_Count(); + int randomId = -1; + for (SLNode *current = ids.Head();current;current = current->Next()) + { + if (!random) + { + randomId = *current->Data(); + ids.Remove(current->Data()); + break; + } + random--; + } + Commands->Send_Custom_Event(obj,Commands->Find_Object(randomId),randomCustom,Param == -1 ? param : Param,delay); + } +} ScriptRegistrant JMG_Utility_Check_If_Script_Is_In_Library_Registrant("JMG_Utility_Check_If_Script_Is_In_Library","ScriptName:string,CppName:string"); ScriptRegistrant JMG_Send_Custom_When_Custom_Sequence_Matched_Registrant("JMG_Send_Custom_When_Custom_Sequence_Matched","Success_Custom=0:int,Correct_Step_Custom=0:int,Partial_Failure_Custom=0:int,Failure_Custom=0:int,Send_To_ID=0:int,Custom_0=0:int,Custom_1=0:int,Custom_2=0:int,Custom_3=0:int,Custom_4=0:int,Custom_5=0:int,Custom_6=0:int,Custom_7=0:int,Custom_8=0:int,Custom_9=0:int,Disable_On_Success=1:int,Disable_On_Failure=0:int,Starts_Enabled=1:int,Enable_Custom=0:int,Correct_Step_Saftey=0:int,Failure_Saftey=1:int,Max_Failures=1:int"); ScriptRegistrant JMG_Utility_Change_Model_On_Timer_Registrant("JMG_Utility_Change_Model_On_Timer","Model=null:string,Time=0:float"); @@ -17740,3 +17850,5 @@ ScriptRegistrant JMG_Utility_Custom_Create_Object_At_Bone_Registrant("JMG_Utility_Custom_Create_Object_At_Bone","Custom:int,Preset:string,Bone:string,MaxDistance=1.5:float,Repeat=0:int"); ScriptRegistrant JMG_Utility_Killed_Send_Custom_When_Killed_By_Nothing_Registrant("JMG_Utility_Killed_Send_Custom_When_Killed_By_Nothing","ID:int,Custom:int,Param:int,Delay:float"); ScriptRegistrant JMG_Utility_Custom_Drop_Corpse_Registrant("JMG_Utility_Custom_Drop_Corpse","Custom:int,PowerupName:string,Repeat=0:int"); +ScriptRegistrant JMG_Utility_Custom_Send_Shuffled_Customs_Registrant("JMG_Utility_Custom_Send_Shuffled_Customs","Custom:int,ID=0:int,SendCustoms:string,Delim=@:string,Param:int,Delay=0.0:float"); +ScriptRegistrant JMG_Utility_Custom_Send_Shuffled_Customs_And_Ids_Registrant("JMG_Utility_Custom_Send_Shuffled_Customs_And_Ids","Custom:int,IDs=0:string,SendCustoms:string,Delim=@:string,Param:int,Delay=0.0:float"); diff -urN sourceold/scripts/jmgUtility.h source/scripts/jmgUtility.h --- sourceold/scripts/jmgUtility.h 2022-02-13 10:20:09.872310800 +1000 +++ source/scripts/jmgUtility.h 2022-05-16 09:59:28.977699300 +1000 @@ -11572,4 +11572,46 @@ void Created(GameObject *obj); void Custom(GameObject *obj,int message,int param,GameObject *sender); void Timer_Expired(GameObject *obj,int number); +}; + +/*! +* \brief Sends a random custom on a custom, each time the custom is received a custom is sent and removed from the list, error message will be thrown when list is empty +* \Custom - Custom to watch for +* \ID - ID to send to, 0 sends to self, -1 sends to sender +* \SendCustoms - list of customs that can be sent at random, the delim separates them +* \Delim - special character used to separate the list IE: @ = 1@3@54545@3 +* \Param - param to send (-1 sends the param that was received) +* \Delay - delay to add +* \author jgray +* \ingroup JmgUtility +*/ +class JMG_Utility_Custom_Send_Shuffled_Customs : public ScriptImpClass { + int recieveMessage; + int id; + SList customs; + int Param; + float delay; + void Created(GameObject *obj); + void Custom(GameObject *obj,int message,int param,GameObject *sender); +}; + +/*! +* \brief Sends a random custom to a random id on a custom, each time the custom is received a custom and id is sent to and removed from the lists, error message will be thrown when the lists are empty +* \Custom - Custom to watch for +* \IDs - list of IDs that can be sent at random, the delim separates them +* \SendCustoms - list of customs that can be sent at random, the delim separates them +* \Delim - special character used to separate the list IE: @ = 1@3@54545@3 +* \Param - param to send (-1 sends the param that was received) +* \Delay - delay to add +* \author jgray +* \ingroup JmgUtility +*/ +class JMG_Utility_Custom_Send_Shuffled_Customs_And_Ids : public ScriptImpClass { + int recieveMessage; + SList ids; + SList customs; + int Param; + float delay; + void Created(GameObject *obj); + void Custom(GameObject *obj,int message,int param,GameObject *sender); }; \ No newline at end of file diff -urN sourceold/scripts/scripts.vcxproj source/scripts/scripts.vcxproj --- sourceold/scripts/scripts.vcxproj 2022-02-13 10:20:09.876262200 +1000 +++ source/scripts/scripts.vcxproj 2022-05-16 09:59:28.979693700 +1000 @@ -410,6 +410,7 @@ + @@ -605,6 +606,7 @@ + @@ -733,6 +735,9 @@ + + + diff -urN sourceold/scripts/scripts.vcxproj.filters source/scripts/scripts.vcxproj.filters --- sourceold/scripts/scripts.vcxproj.filters 2022-02-13 10:20:09.878324600 +1000 +++ source/scripts/scripts.vcxproj.filters 2022-05-16 09:59:28.979693700 +1000 @@ -389,6 +389,9 @@ 01. Sources + + 01. Sources + @@ -1300,6 +1303,18 @@ 02. Headers + + 02. Headers + + + 02. Headers + + + 02. Headers + + + 02. Headers + diff -urN sourceold/scripts/unstoppable.cpp source/scripts/unstoppable.cpp --- sourceold/scripts/unstoppable.cpp 2022-02-13 10:20:09.879323500 +1000 +++ source/scripts/unstoppable.cpp 2022-05-16 09:59:28.980691000 +1000 @@ -14,7 +14,6 @@ #include "engine.h" #include "engine_common.h" #include "engine_def.h" -#include "engine_game.h" #include "engine_player.h" #include "engine_tt.h" #include "engine_script.h" @@ -1345,3 +1344,47 @@ ScriptRegistrant UP_Disable_Weapon_For_Driver_Registrant("UP_Disable_Weapon_For_Driver", ""); /******************************************************************************************************/ + +void UP_Set_Bot_Tag::Created(GameObject* obj) +{ + if (obj->As_SoldierGameObj()) + { + obj->As_SoldierGameObj()->Set_Bot_Tag(Get_Parameter("Tag")); + } + + Destroy_Script(); +} + +ScriptRegistrant UP_Set_Bot_Tag_Registrant("UP_Set_Bot_Tag", "Tag:string"); + +/******************************************************************************************************/ + +void UP_Set_Bot_Tag_MultiLine::Created(GameObject* obj) +{ + if (obj->As_SoldierGameObj()) + { + StringClass tag; + tag.Format("%s\n%s\n%s\n%s\n%s", Get_Parameter("Tag1"), Get_Parameter("Tag2"), Get_Parameter("Tag3"), Get_Parameter("Tag4"), Get_Parameter("Tag5")); + obj->As_SoldierGameObj()->Set_Bot_Tag(tag); + } + + Destroy_Script(); +} + +ScriptRegistrant UP_Set_Bot_Tag_MultiLine_Registrant("UP_Set_Bot_Tag_MultiLine", "Tag1:string,Tag2:string,Tag3:string,Tag4:string,Tag5:string"); + +/******************************************************************************************************/ + +void UP_Remove_Bot_Tag::Created(GameObject* obj) +{ + if (obj->As_SoldierGameObj()) + { + obj->As_SoldierGameObj()->Set_Bot_Tag("\0"); + } + + Destroy_Script(); +} + +ScriptRegistrant UP_Remove_Bot_Tag_Registrant("UP_Remove_Bot_Tag", ""); + +/******************************************************************************************************/ \ No newline at end of file diff -urN sourceold/scripts/unstoppable.h source/scripts/unstoppable.h --- sourceold/scripts/unstoppable.h 2022-02-13 10:20:09.879323500 +1000 +++ source/scripts/unstoppable.h 2022-05-16 09:59:28.981689100 +1000 @@ -849,3 +849,42 @@ void Created(GameObject* obj); void Custom(GameObject* obj, int type, int param, GameObject* sender); }; + +/*! + * \brief Set Bot Tag + * \author Unstoppable + * \ingroup UnstoppableScripts + * + * Sets the bot tag of attached soldier object, then detaches. + */ +class UP_Set_Bot_Tag : public ScriptImpClass +{ +public: + void Created(GameObject* obj); +}; + +/*! + * \brief Set Bot Tag Multiple Lines + * \author Unstoppable + * \ingroup UnstoppableScripts + * + * Sets the bot tag of attached soldier object with multiple lines, then detaches. + */ +class UP_Set_Bot_Tag_MultiLine : public ScriptImpClass +{ +public: + void Created(GameObject* obj); +}; + +/*! + * \brief Remove Bot Tag + * \author Unstoppable + * \ingroup UnstoppableScripts + * + * Removes the bot tag of attached soldier object, then detaches. + */ +class UP_Remove_Bot_Tag : public ScriptImpClass +{ +public: + void Created(GameObject* obj); +}; \ No newline at end of file