Jump to content

sarogahtyp

Member
  • Content Count

    2494
  • Joined

  • Last visited

  • Medals

Posts posted by sarogahtyp


  1. Closing the complete menu can be done this way:
     

    MenuBase teleportMenu = GetGame().GetMenuManager().GetOwnerMenu(widgetRoot);
    GetGame().GetMenuManager().CloseMenu(teleportMenu);

    My complete class with 2 working buttons, one button hints something, the second closes the menu:
     

    Spoiler
    
    modded enum ChimeraMenuPreset
    {
    	SARO_MHQMenuGUIEnumerator
    }
    
    class SARO_MHQMenuGUI: ChimeraMenuBase
    {
    	
    	protected Widget widgetRoot;
    	protected SCR_ButtonTextComponent buttonTeleport, buttonCancel;
    	
    	IEntity myCallerEntity; // this variable will be used only to show how to transfer parameters to the GUI. 
    
    	override void OnMenuOpen() 
    	{ 
    		widgetRoot = GetRootWidget();
          
    		// SendHint 
    		buttonTeleport = SCR_ButtonTextComponent.GetButtonText("Teleport", widgetRoot);
    		buttonCancel = SCR_ButtonTextComponent.GetButtonText("Cancel", widgetRoot);
          
    		if (buttonTeleport) 
    		{
    			GetGame().GetWorkspace().SetFocusedWidget(buttonTeleport.GetRootWidget()); 
    			buttonTeleport.m_OnClicked.Insert(DoTeleport); 
    		} 
    
    		if (buttonCancel)
    		{
    			GetGame().GetWorkspace().SetFocusedWidget(buttonCancel.GetRootWidget()); 
    			buttonCancel.m_OnClicked.Insert(DoCancel); 
    		}
    	} 
     
    	// myCustomFunction called when SendHint Button is pressed 
    	void DoTeleport() 
    	{ 
    		SCR_HintManagerComponent.GetInstance().ShowCustomHint("This executes when pressing Teleport Button (Using OnClick)", "MY GUI", 3.0);
        }
    
    	void DoCancel() 
    	{ 
    		MenuBase teleportMenu = GetGame().GetMenuManager().GetOwnerMenu(widgetRoot);
    		GetGame().GetMenuManager().CloseMenu(teleportMenu);  
        } 
    	
    };

     

     


  2. Then a wreck seems not to be a "house".

    The other way is to finding out which classname the wreck has by pointing on the wrecked tower and doing this in debug console:

    copyToClipBoard typeOf cursorObject;

    now you can use the copied classname and exchange the _wreck= ... line with the following:

     

    private _wreck = nearestObject [_towerPos, "COPIED_CLASSNAME"];

    Edit: variable name corrected to _towerPos

    • Like 2

  3. 5 hours ago, Northup said:

    Is there a way to reference the swapped model after an object is destroyed? I want the tower collapse animation to play, but want it to never replace the top tower with the damaged model (or delete it immediately). 

    this addEventHandler ["Killed", 
    {
      upperTower setDamage 1;
      
      [position upperTower] spawn
      {
        params ["_towerPos"];
        
        sleep 3; //until animation finished (correct value is up to you)
        
        private _wreck = nearestObjects [_towerPos, ["house"], 2] select 0;
        
        deleteVehicle _wreck;
      };
    }];

    idk if the wreck of a house fits as "house" with nearestObjects but I guess it does...

     

    I don't like this solution because its dirty.

    better would be a proper eventhandler which gives you the wreck objects reference. Maybe the respawn event handler does but this has to be tested and I guess it does not...

    • Like 1

  4. Idk if u understand what a triggers condition is or a condition in general is.

    A condition to live is breathable air around you.

    This condition is true as long u have that air around you. A teleport into space will set that condition to false and you die.

     

    No sqf file needed for this just the condition...


  5. On Discord there are some Infos bout GUI creation. I just post it here to have it spread for Non-Discorders (Discord-Link to this post)

     

    Spyke — 15.06.2022

    I made this little tutorial it will be useful fore someone else

     

    How to create a ListBox in GUI - Layout

     

    0. Place an OverlayWidget and resize it as you wish.

    1. Search the ArmaReforger Prefab: ArmaReforger:UI/layouts/ListBox/ListBox.layout

    2. Place the prefab inside the OverlayWidget created at Step 0 and change the Horizontal and Vertical Align to the 4th option.

    3. Get sure that the new created ListBox0 (by default) has the component SCR_ListBoxComponent.

    4. Get sure that the new created ListBox0 has a ScrollLayoutWidget ("ScrollLayout0" doesn't mater) and a VerticalLayoutWidget ("List" as name, required) created.

    5. Steps 3 and 4 should be fine by default if you have used the ListBox Prefab. How to create a ListBox in GUI - Fill and GetIndex

    6. Create a menu class script with the following:

    class SPK_myMenuUI: ChimeraMenuBase 
    { 
    	protected Widget m_wRoot;
      
      	//... 
      
    	OverlayWidget m_ListBoxOverlay;
      	SCR_ListBoxComponent m_ListBoxComponent;
      
      	//...
      
      	//------------------------------------------------------------------------------------------------
      
      	override void OnMenuOpen() 
        { 
        	m_wRoot = GetRootWidget();
          
          	//... 
          
          	// MyList
          	m_ListBoxOverlay = OverlayWidget.Cast(m_wRoot.FindAnyWidget("ListBox0"));
          	m_ListBoxComponent = SCR_ListBoxComponent.Cast(m_ListBoxOverlay.FindHandler(SCR_ListBoxComponent));
          
          	if (m_ListBoxComponent) 
            { 
              	m_ListBoxComponent.AddItem("MyItem0"); 
              	m_ListBoxComponent.AddItem("MyItem1"); 
              	m_ListBoxComponent.AddItem("MyItem2"); 
            } 
          
          	//... 
          
        } 
      
      	//...
    
    };

    7. In order to get the ListBox Index you can use this: m_ListBoxComponent.GetSelectedItem();


  6. On Discord there are some Infos bout GUI creation. I just post it here to have it spread for Non-Discorders (Discord-Link to this post)

     

    Spyke — 29.05.2022

    GUI Setup

    1. Create the following folders in your project: UI/layouts/Modded

    2. Create some layout inside the created Modded folder: myNewLayout.layout

    3. Create the following folders: Scripts/Game/UI/Modded

    4. Create a .c file inside the created Modded folder: myScriptedUI.c

    5. Go to ArmaReforge/Configs/System/chimeraMenus.conf and rightclick/override in yourAddon

    6. Go to your automatically created path Configs/System/chimeraMenus.conf and add your new GUI at the end with some ID name (myTestGui_ID).

    7. Assign the Layout (myNewLayout.layout)

    8. Assign the Class (myNewLayoutClass)

    9. Return to the previously created: myScriptedUI.c

    10. Add this:

    modded enum ChimeraMenuPreset 
    { 
      myTestGui_ID 
    }

    11. In the same file you can add your class to (I will put the code later to make it more clear):

    class myNewLayoutClass: ChimeraMenuBase 
    {
      //your GUI code ... 
    }

    12. With this done you will be able to Open the GUI using this code somewhere:

    GetGame().GetMenuManager().OpenMenu(ChimeraMenuPreset.myTestGui_ID);

     

    Adding functionality to your new created GUI (Hint on Button Click):

    13. Go to your layout: myNewLayout.layout

    14. Add one ButtonWidget and rename it to: SendHint

    15. In SendHint/Script add one component called: SCR_ButtonTextComponent (and leave it with his default values for now)

    16. Return to your previously created class: myNewLayoutClass and do the following code magic:

    class SPK_myMenuUI: ChimeraMenuBase 
    {
    	protected Widget m_wRoot;
    	protected SCR_ButtonTextComponent comp;
    	IEntity myCallerEntity; // (Added) this variable will be used only to show how to transfer parameters to the GUI. 
    	//------------------------------------------------------------------------------------------------
    	override void OnMenuOpen() 
    	{ 
    		m_wRoot = GetRootWidget();
          
    		// SendHint 
    		comp = SCR_ButtonTextComponent.GetButtonText("SendHint", m_wRoot);
          
    		if (comp) 
    		{
    			GetGame().GetWorkspace().SetFocusedWidget(comp.GetRootWidget()); 
    			comp.m_OnClicked.Insert(myCustomFunction); 
    		} 
    	} 
     
    	// myCustomFunction called when SendHint Button is pressed 
    	void myCustomFunction() 
    	{ 
    		SCR_HintManagerComponent.GetInstance().ShowCustomHint("This executes when pressing SendHint Button (Using OnClick)", "MY GUI", 3.0);
        } 
    };

    17. (Added) You will need to change the code in step 12 if you want to be able to pass some variables to the GUI:

    MenuBase myMenu = GetGame().GetMenuManager().OpenMenu(ChimeraMenuPreset.SPK_myTestGui);
    SPK_myMenuUI myMenuUI = SPK_myMenuUI.Cast(myMenu);
    myMenuUI.myCallerEntity = pOwnerEntity; // pOwnerEntity is the variable we want to be able to use in the GUI on this example.

     


  7. when I was fighting with action menus I had a problem which little solution I want to share here fo people not such involved in classes and OOP.

     

    I ll post a part of the code out of the biki to explain the problem I had:

     

    class MyScriptedUserAction : ScriptedUserAction
    {
    	//------------------------------------------------------------------------------------------------
    	override void PerformAction(IEntity pOwnerEntity, IEntity pUserEntity)
    	{
    		Print("MyScriptedUserAction.PerformAction() method reached");
    		SCR_HintManagerComponent.GetInstance().ShowCustomHint("My test ground world - DONE", "TEST GROUND", 3.0);
    	}
    
    	//------------------------------------------------------------------------------------------------
    	override bool CanBeShownScript(IEntity user)
    	{
    		return true;
    	}
    };

     

    As you can see the method PerformAction (which is executed when pressing F key on this entry in game) has 2 paramaeters. First one is pOwnerEntity which is the entity of where you added the action menu to.

    The second (pUserEntity) is just the character entity of the player who is watching and using the action menu.

     

    The problem:

    Now there is the method CanBeShownScript which boolean return value determines if this action menu entry is shown to the user or not.

    And there is the problem. This method has only one parameter, the object where the action is applied to is missing. This can be a problem if you have a "Unflip Vehicle"-menu entry which should get shown only if the vehicle is flipped.

    But you don't have the vehicle as a parameter of the method here. Therefore you can't check if it is flipped.

     

    The solution:

    What you have to know bout classes here is that in many classes you do not see all methods available in it. The reason for this is Inheritance. Most classes are inherited multiple times out of other (their parent-) classes. This means you can mostly find more methods available by viewing the declaration of those parent classes.
    In this case I viewed some forefathers of the class MyScriptedUserAction.

    These forefathers in this case were the classes: ScriptedUserAction and BaseUserAction

    In BaseUserAction I found the desired GetOwner() method which gives you the object which is the menu applied to.

    Here I show the start of that class. The last method of that part is the desired method:

    class BaseUserAction: ScriptAndConfig
    {
    	// Injects
    	//! The reason why action cannot be performed.
    	//! Should be set in CanBePerformed check
    	protected string m_sCannotPerformReason;
    	
    	//! Sets the reason why action couldn't be performed.
    	//! Should be done in CanBePerformed check
    	void SetCannotPerformReason(string reason)
    	{
    		m_sCannotPerformReason = reason;
    	}
    	
    	//! Returns the reason why action couldn't be performed.
    	//! It is valid only within and after CanBePerformed is called
    	string GetCannotPerformReason()
    	{
    		return m_sCannotPerformReason;
    	}
    	
    	//! Can be filled in scripts to be used as params when name is being formatted when displayed in UI
    	string ActionNameParams[9];
    	
    	bool IsUserActionConsumable() { return false; }
    	
    	//! Returns the index of the context this action is registered in as or -1 if none
    	proto external int GetContextIndex(string sContextName);
    	//! Can this action be performed by the user?
    	proto external bool CanBePerformed(IEntity user);
    	//! Can this action be shown in the UI for the user?
    	proto external bool CanBeShown(IEntity user);
    	//! Does this action only have client side effect?
    	proto external bool HasLocalEffectOnly();
    	//! If HasLocalEffectOnly() is true this method tells if the server is supposed to broadcast this action to clients.
    	proto external bool CanBroadcast();
    	//! Should this action be performed every frame the input action is triggered?
    	proto external bool ShouldPerformPerFrame();
    	//! Return the name of this action.
    	//! By default returns the value in UIInfo or empty string if UIInfo doesn't exist.
    	proto external string GetActionName();
    	//! Return the description of this action.
    	//! By default returns the value in UIInfo or empty string if UIInfo doesn't exist.
    	proto external string GetActionDescription();
    	//! Returns the visibility range of this action in metres.
    	proto external float GetVisibilityRange();
    	//! Returns the duration of this action in seconds.
    	proto external float GetActionDuration();
    	//! Returns the progress of this action in seconds.
    	proto external float GetActionProgress();
    	//! Returns the UIInfo set for this user action or null if none.
    	proto external UIInfo GetUIInfo();
    	//! Returns the parent entity of this action.
    	proto external IEntity GetOwner();                       // THIS IS THE DESIRED METHOD



     

    No I know that I can just do this:

    class MyScriptedUserAction : ScriptedUserAction
    {
    	//------------------------------------------------------------------------------------------------
    	override void PerformAction(IEntity pOwnerEntity, IEntity pUserEntity)
    	{
    		Print("MyScriptedUserAction.PerformAction() method reached");
    		SCR_HintManagerComponent.GetInstance().ShowCustomHint("My test ground world - DONE", "TEST GROUND", 3.0);
    	}
    
    	//------------------------------------------------------------------------------------------------
    	override bool CanBeShownScript(IEntity user)
    	{
            IEntity menuOwner = GetOwner();   // THIS IS THE SOLUTION
    		return true;
    	}
    };

    Now I can use menuOwner to determine if the menu should be shown. I could check if the vehicle is flipped for example.

    Generally watching the parent declarations of classes is essential!

    In script editor double click the parent class to mark it and then right click and then click "Goto Declaration".

    • Like 2

  8. If you want to make changes to things which determine the game behavior then you should watch some videos on howto set up a basic mission first. There you will learn which game objects hold which components where you can adjust what properties.

    You just dont have one menu or one set of menus where you are able to adjust the basic things. Or better to say you have that but it is spread a bit more.

     

    Here you ll find a bunch of those tuts:

     

     

    • Thanks 1

  9. 9 hours ago, bent.toe said:

    How is it possible to sneak up on A.I in this game?

    No problem driving a jeep full speed in to their base..3 or 4 of them firing in another direction while at least one is running straight in to the headlights like a deer.

     

    Yes.. A.I (among other things) need some rework.

     

    On 6/13/2022 at 6:35 PM, sarogahtyp said:

    U just cant take AI serious currently. BI included some example behavior trees to have them fight somehow and thats it.

    But I guess modders are now much better able to enhance AI behavior. Its all about those behavior trees i think...

     

    Here is an example for what some modders are trying an achieveing currently:

     


  10. 9 minutes ago, Northup said:

    Error type bool, expected number. Line 23.

    this does not tell anything.

     

    https://community.bistudio.com/wiki/Crash_Files#Location

     

    and don't post the complete file. the lines related to the error only pls.

     

    Edit:

    Also post the script YOU executed. Not just quoting mine!

     

    To make it short: Provide accurate and complete information that is as short as possible!


  11. getting all markers in a trigger area:

    _all_markers_in_trigger_area = allMapMarkers select { getMarkerPos _x inArea triggerArea YOURTRIGGERNAME };

     

    getting all markers which have tower in marker name and  which are in area of trigger:

    _all_tower_markers_in_trigger_area = allMapMarkers select { getMarkerPos _x inArea triggerArea YOURTRIGGERNAME && "tower" in _x};

     

    repeating your script for all tower markers in trigger zone:

    [] spawn
    {
     waitUntil{!isNull findDisplay 12}; 
    
     { 
      findDisplay 12 displayCtrl 51  ctrlAddEventHandler ["Draw",{  
        (_this select 0) drawIcon [ 
        getMissionPath "\images\tower1_ca.paa",  
        [1,1,1,1], 
      getMarkerPos _x,
        20, 
        20, 
        0, 
        "", 
        false, 
        0.03, 
        "TahomaB", 
        "right"]; 
        }];   
      
     } forEach ( allMapMarkers select { getMarkerPos _x inArea triggerArea YOURTRIGGERNAME && "tower" in _x } );
    };

    Nothing tested!


  12. 48 minutes ago, Boerstil said:

    My question is how do I load the functions so i can use them in triggers and onGamestart etc. ?

     

    48 minutes ago, Boerstil said:

    How do i get my functions into the functionlibrary so i can use them?

    No need to load anything into some library. If you crete a .c file with a class in it then this is just enough.

    After clicking "Compile and Reload Scripts" in Script Editors "Build"-menu everything is in place and can be used.

×