Jump to content

Recommended Posts

On 8/14/2019 at 11:04 AM, Rydygier said:

 

- added new user variable (cannot be changed on-the-fly - attempt will be futile) RYD_HAS_addJIPs = true;//if true, JIP-ing players will automatically get access to HAS calls without necessity of manual calling RYD_HAS_newUnit function for them. (not tested, can't test on my own anyway - testing requires two players);

 

 

Hi Rydygier

 

Tested this for you - not good news alas.  First, maybe the code ought to be

	if (RYD_HAS_addJIPs) then
		{
		RYD_HAS_JIPEH = addMissionEventHandler ["PlayerConnected",
			{
			params ["_id", "_uid", "_name", "_jip", "_owner", "_idstr"];
			
			if (_jip) then
				{
					{
					if (((owner _x) isEqualTo _owner) and {not ((_x getVariable ["RYD_HAS_Access",false]))}) exitWith
						{
						[_x] call RYD_HAS_NewUnits; // *** Replaced _unit with _x - _unit not a param in the Event Handler ?
						}
					}
				foreach (allPlayers - (entities "HeadlessClient_F"))
				};
			}];
		};

But even with that change it still didn't work. Having dropped lots of diag_log lines into the code to see what is going on it seemed that the problem is with the content of the AllPlayers array. The EventHandler seems to be firing before the JIP player has been added into the array. The RPT output shows the Eventhandler firing twice, once for each player. When JIP is true for the second player it then dumps the content of AllPlayers and then monitors the tests in the foreach loop,  but that only runs once.

19:28:28 "PlayerConnected missionEventHandler with JIP = false, Name = Dev01, Owner = 2" 	// Mission starting - host player starts the mission
19:28:28  Mission id: 634c322b881a6ee0e95c8ba4ba2b4763072e0507
19:29:07 "PlayerConnected missionEventHandler with JIP = true, Name = Dev02, Owner = 11" 	// Player 2 - JIP
19:29:07 "JIP = true, allplayers = [unit1]"							// Player 2 still not in the AllPlayers array
19:29:07 "Comparing owner 2 to 11, and getVariable [""RYD_HAS_Access""] = true"			// The loop does not test Player 2

 

Share this post


Link to post
Share on other sites
Quote

Tested this for you

 

Thanks. 

 

Since in this case I can't test my own code, it is tough one to implement. Especially, so far I never touched anything around JIP, so not sure, what to expect here. 

 

Quote

Replaced _unit with _x

 

Good. It's within foreach loop anyway, definitelly should be _x there. 

 

Quote

But even with that change it still didn't work. Having dropped lots of diag_log lines into the code to see what is going on it seemed that the problem is with the content of the AllPlayers array. The EventHandler seems to be firing before the JIP player has been added into the array. 

 

That explanation makes sense. It seems weird to me, that EH doesn't provide actual unit object, player is JIPing into, that would make everything much simplier. But it is "PlayerConnected" event that probably not necessarily imply "incarnation" into certain unit object and indeed may happen before such incarnation. I'll think, how to solve that. Thanks again for helpful input. 

 

 

Share this post


Link to post
Share on other sites

One way, I do not like, would be grabbing allPlayers into variable at first, then waitUntil in allPlayers appear a unit, that isn't in that variable and then run foreach loop. That could work assuming, always and for sure at first new player is not inside allPlayers when this EH kicks in. And as for MP many things aren't certain nor guaranteed...

 

Second way would be not using EH at all, just some permanent loop with a 1 sec sleep or so, that would cyclically compare previous allPlayers with new. This way:

 

Spoiler

	if (RYD_HAS_addJIPs) then
		{
		/*RYD_HAS_JIPEH = addMissionEventHandler ["PlayerConnected",
			{
			params ["_id", "_uid", "_name", "_jip", "_owner", "_idstr"];
			
			
			
			if (_jip) then
				{
					{
					if (((owner _x) isEqualTo _owner) and {not ((_x getVariable ["RYD_HAS_Access",false]))}) exitWith
						{
						[_x] call RYD_HAS_NewUnits;
						}
					}
				foreach (allPlayers - (entities "HeadlessClient_F"))
				};
			}];*/
			
		RYD_HAS_JIPLoop = [] spawn
			{
			sleep 5;//just in case
			
			while {true} do
				{
				_allPlayers = (allPlayers - (entities "HeadlessClient_F"));
				sleep 1;
				
				if not ((allPlayers - (entities "HeadlessClient_F")) isEqualTo _allPlayers) then
					{
						{
						if not (_x getVariable ["RYD_HAS_Access",false]) then
							{
							[_x] call RYD_HAS_NewUnits;
							}
						}
					foreach _allPlayers					
					}
				}
			}
		};

 

 

Here is new version:

 

HAS 1.9 wip2

Share this post


Link to post
Share on other sites
9 hours ago, Rydygier said:

One way, I do not like, would be grabbing allPlayers into variable at first, then waitUntil in allPlayers appear a unit, that isn't in that variable and then run foreach loop. That could work assuming, always and for sure at first new player is not inside allPlayers when this EH kicks in. And as for MP many things aren't certain nor guaranteed...

 

Hi Rydygier

 

I'll do more testing for you.

 

At work today, in the less busy moments, I was wondering how to get past the AllPlayers issue. Maybe the eventHandler would work with a 'sleep' of a few seconds so as to give the engine time to create the actual player object, and put it into allPlayers? Then when the loop runs all will be well. The chances of the JIP player wanting to call for a chopper in the first few seconds of joining a mission have got to be slim. 

 

So the eventhandler feels like the right solution to me. I share your views on watching for the index count of allPlayers changing, that feels like it will be inefficient. Likewise a 1 second perpetual loop running all the time.

 

I'll try to report back later this evening (UK time).

Share this post


Link to post
Share on other sites

Rydygier

 

Sorry but i think I am making things worse not better! I'll start with Version 2, and return to Version 1 lower down - but they have one issue in common

 

Version 2 - your code with my debug lines

		RYD_HAS_JIPLoop = [] spawn
			{
			sleep 5;//just in case
			
			while {true} do
				{
				_allPlayers = (allPlayers - (entities "HeadlessClient_F"));
				sleep 1;
				
				if not ((allPlayers - (entities "HeadlessClient_F")) isEqualTo _allPlayers) then
					{
						systemchat "allPlayers not same as _allplayers";
						diag_log "allPlayers not same as _allplayers";
						{
						systemchat format ["Unit %1 - GetVariable %1 is %2",_x,_x getVariable ["RYD_HAS_Access",false]];
						diag_log format ["Unit %1 - GetVariable %1 is %2",_x,_x getVariable ["RYD_HAS_Access",false]];
						if not (_x getVariable ["RYD_HAS_Access",false]) then
							{
							systemchat "GetVariable false - calling RYD_HAS_NewUnits";
							diag_log "GetVariable false - calling RYD_HAS_NewUnits";
							[_x] call RYD_HAS_NewUnits;
							}
						}
					foreach _allPlayers					
					}
				}
			}

resulted in the code not testing the JIP unit - "unit2"

20:36:17 "allPlayers not same as _allplayers"
20:36:17 "Unit unit1 - GetVariable unit1 is true"

So changed "foreach _allPlayers" to "foreach allPlayers" and got

20:37:43 "allPlayers not same as _allplayers"
20:37:43 "Unit unit2 - GetVariable unit2 is true"
20:37:43 "Unit unit1 - GetVariable unit1 is true"

The JIP unit - "unit2" - seems to have "RYD_HAS_Access" as True on connecting. Therefore the "if not (_x getVariable ["RYD_HAS_Access",false]) then" never called RYD_HAS_NewUnits. I cannot work out why this is or where else might be setting RYD_HAS_Access. Sorry.

 

Version 1 code has the same issue. I changed the code to include a sleep. Adding a 'spawn' to the eventHandler that would then sleep for a bit before running the foreach loop

		if (_jip) then
			{
				[4,_owner] spawn {
					params ["_delay","_theOwner"];
					sleep _delay;
					{
					if (((owner _x) isEqualTo _theOwner) and {not ((_x getVariable ["RYD_HAS_Access",false]))}) exitWith

That worked and the JIP player was included in allPlayers, but it ran into the same issue with the getVariable being true :-(

20:46:09 "PlayerConnected missionEventHandler with JIP = false, Name = Dev01, Owner = 2"
20:46:09  Mission id: d6658cdcbd067c2cf4620cbf8fe3110f500e7f21
20:46:33 "PlayerConnected missionEventHandler with JIP = true, Name = Dev02, Owner = 7"
20:46:37 "Comparing owner 7 to 7, and getVariable [""RYD_HAS_Access""] = true"
20:46:37 "Comparing owner 2 to 7, and getVariable [""RYD_HAS_Access""] = true"

Thomas Edison would say that finding more and more things that don't work is a form of progress, so I hope all this is helpful to you in some way.

Share this post


Link to post
Share on other sites

 

Quote

So changed "foreach _allPlayers" to "foreach allPlayers"

 

Ah, yes, indeed, otherwise we go through old array, before updating it with new players which leads us nowhere. To be 100% OK, it should be: foreach (allPlayers - (entities "HeadlessClient_F"));

 

Quote

Thomas Edison would say that finding more and more things that don't work is a form of progress, so I hope all this is helpful to you in some way.

 

In this case he would be right. 🙂 We are going through rather typical debugging process, only this time I can't perform this myself. Thanks again, your help is very appreciated. So it seems, we overcomed the problem of new player not present in allPlayers for both variants. That's the progress. Now appeared, somewhere before this JIPing player gets his "access" variable true. This happens in three places in the code:

 

1. At the init, for the units initially included into RYD_HAS_STT array by hand or preliminary syncing with the RYD_HAS_Base object in EDEN:

		{
		_x setVariable ["RYD_HAS_Access",true,true];
		_x addMPEventHandler ["MPRespawn", RYD_HAS_atRespawn];
		}
	foreach RYD_HAS_STT;

2. Inside RYD_HAS_NewUnits function;

 

3. Inside RYD_HAS_atRespawn function, which is added as MPRespawn EH code as shown in p. 1. and inside RYD_HAS_NewUnits, in the same manner. 

 

Therefore unit can return true for _x getVariable ["RYD_HAS_Access",false] if it was already added into RYD_HAS_STT at init or if it was already added by hand via RYD_HAS_NewUnits. 

 

So it's a mystery. 😶

 

...unless the player JIPs into AI unit, that was synced initially or added via RYD_HAS_NewUnits before. I would suspect the first case.

 

(which BTW leads to the valid question: why even I bother with this feautre if all, what user needs in order to get same result is just initial syncing all playable units? Well, why not. it was requested, easy to do (not much code) and perhaps someone will want to keep playable units not synced for any mysterious reason. Still, it is kinda redundant...)

 

Technically I could just not using "RYD_HAS_Access" check but instead do foreach ((allPlayers - (entities "HeadlessClient_F")) - _allPlayers) to run through all new players but that would be giving up on solving the mystery, which I don't like at all. And I'm not sure, if that would be 100% reliable (depending, what HAS user would do with some new players in other code before new loop cycle). 

 

Share this post


Link to post
Share on other sites
12 hours ago, Rydygier said:

So it's a mystery. 😶

 

 

With more debug code I got this right at the start of the mission loading for the server player

19:34:07 "After RYD_HAS_FC_submenu - Adding RYD_HAS_Access true for unit2"
19:34:07 "After RYD_HAS_FC_submenu - Adding RYD_HAS_Access true for unit3"
19:34:07 "After RYD_HAS_FC_submenu - Adding RYD_HAS_Access true for unit4"
19:34:07 "After RYD_HAS_FC_submenu - Adding RYD_HAS_Access true for unit5"
19:34:07 "After RYD_HAS_FC_submenu - Adding RYD_HAS_Access true for unit6"
19:34:07 "After RYD_HAS_FC_submenu - Adding RYD_HAS_Access true for unit1"

So all the playable units are having RYD_HAS_Access set to true at lines 170 to 174 as part of RYD_HAS_Init. So when one of them is taken over as a JIP player it is already True.

 

To quote Henry Kissinger this time "Each success only buys an admission ticket to a more difficult problem."

 

I went back to my version of version 1 - and implemented your suggestion to " I could just not using RYD_HAS_Access check"  to give

			if (_jip) then
				{
					[4,_owner] spawn {
						params ["_delay","_theOwner"];
						sleep _delay;
						{
						if ((owner _x) isEqualTo _theOwner) exitWith
							{
							[_x] call RYD_HAS_NewUnits;
							}
						}
					foreach (allPlayers - (entities "HeadlessClient_F"))
					};
				};

and that worked, but it didn't. It called RYD_HAS_NewUnits as it should. The code in that function would not call RYD_HAS_GiveActions for the JIP unit, so they did not get the menu options showing.  I can see that RYD_HAS_UseSupportsMenu is set to True in the UserConfig file. 

	if not (RYD_HAS_UseSupportsMenu) then
		{
		_this call RYD_HAS_GiveActions;
		};

BUT! When I ran the mission with AI disabled everything worked perfectly!. So the fact that the JIP unit is not getting the support menu options added is in some way related to it being in the mission as an AI unit before it is taken over by a player. When it is not in the mission until it is a player unit then the code is working perfectly.

 

And that is true of Version 1 with the the sleep and the RYD_HAS_Access check restored. When AI is disabled the original version 1 [with this tweak] works as you had intended.

	if (RYD_HAS_addJIPs) then
		{
		RYD_HAS_JIPEH = addMissionEventHandler ["PlayerConnected",
			{
			params ["_id", "_uid", "_name", "_jip", "_owner", "_idstr"];
			
			if (_jip) then
				{
				[4,_owner] spawn {
						params ["_delay","_theOwner"];
						sleep _delay;
						{
						if (((owner _x) isEqualTo _theOwner) and {not ((_x getVariable ["RYD_HAS_Access",false]))}) exitWith
							{
							[_x] call RYD_HAS_NewUnits;
							}
						}
					foreach (allPlayers - (entities "HeadlessClient_F"))
					};
				};
			}];
		};

And that is where I will leave off this evening's investigations, I'm afraid.  I have not looked to see where the difference arises in the code between enabled and disabled AI units. But that seems to be the new problem where admission has been bought.

Share this post


Link to post
Share on other sites

Figured, I can run Arma twice, where one instance hosts the server, and second JIPs in. So after all I can test this... No idea, what mess is going on about playable units in MP, it seems, if you tag a playable unit with setVariable then add to it some mouse actions or 0-8 options (that's the case for JIPable units synced with Base object), and after that JIP into it, the variable stays, but options/actions are gone (not a problem with AI disabled in the lobby, in such case perhaps actual new unit is spawned in at JIP, so have no variable tag yet and thus passes the check). Or is this something in my code causing this after all? I'll investigate this further, thank you for the assistance. 🙂 BTW found some stuff, I probably need to correct anyway, so that's a good thing. 

Share this post


Link to post
Share on other sites

Meanwhile I just removed RYD_HAS_Access check, so regardless of this var, newly JIPed unit will get actions. In my tests it does the job - now that unit has options, that was lacking previously. Still need to be tested for possible side effects (+ few minor backstage corrections):

 

HAS 1.9 wip3

 

PS Oh, it's today! 8th anniversary of my presence here (and, de facto, 8 years of my scripting journey). :wine:

Edited by Rydygier
  • Like 2

Share this post


Link to post
Share on other sites

Happy Anniversary!  That is an impressive record. 

 

I am sure you know this already but version 3 works flawlessly. I tried four different test situations: AI Enabled / AI Disabled - RYD_HAS_UseSupportsMenu True / False. Worked like a dream every time.

 

Bravo Zulu.

 

And, just to add, I was well impressed with how it handled the JIP player joining the mission, calling for support, then disconnecting. Brilliant stuff.

 

11 hours ago, Rydygier said:

No idea, what mess is going on about playable units in MP, it seems, if you tag a playable unit with setVariable then add to it some mouse actions or 0-8 options (that's the case for JIPable units synced with Base object), and after that JIP into it, the variable stays, but options/actions are gone (not a problem with AI disabled in the lobby, in such case perhaps actual new unit is spawned in at JIP, so have no variable tag yet and thus passes the check).

 

I'm really just guessing here but maybe it's to do with the 'ownership' of the unit object being transferred from the server to the client. If AI is disabled the object will be 'owned' by the client PC right from instantiation. But when AI is enabled the object will start life on the server and then need to be transferred to the client PC when a player JIP's into that object. Maybe some stuff survives that transfer and some stuff doesn't?  As I say, just a guess, and whatever it is you have overcome it. Nice one.

 

PS It's a holiday weekend in the UK this weekend so I'm AFK. No responses for a while is not from a loss of interest, but the loss of access to the PC.

  • Like 1

Share this post


Link to post
Share on other sites
Quote

 I was well impressed with how it handled the JIP player joining the mission, calling for support, then disconnecting. 

 

Hm. In fact, there's a problem, I need to deal with. If some player call the transport, his unit is designated as caller unit. Only this unit chooses flight destination etc. If that unit is killed, HAS handles that and another HAS-enabled unit becomes the caller. But apparently if the caller disconnects, his unit stays the caller, thus no one can choose the destination etc. So it seems, I need to add a code similar to one, that handles caller's death also for his disconnection. 

Share this post


Link to post
Share on other sites

And here's yet another reason to "love" MP scripting:

 

There's "PlayerDisconnected" event handler. When it kicks in, you cannot check, if current caller unit is no longer player-controlled, because at this point code still returns true for (isPlayer RYD_HAS_Caller) while it already returns different unit's owner (so we can't compare by owner, if that unit is a caller). LIke someone designed this in purpose this way... I can only put waituntil waiting, till caller unit will be no longer "isPlayer". But this EH kicks in for every disconnection, not only for caller unit, so this is hardly the solution. 

 

Luckilly, there's also "HandleDisconnect" event handler, that supposed to leave trace, what unit actually was abandoned by the player. Let's hope so...

Share this post


Link to post
Share on other sites

HAS 1.9 wip4

 

Mentioned disconnection of the caller should trigger transfering caller's privileges to another player same, as for killed caller event (good way to test: have two players, make JIP player to call transport, after it is confirmed - disconnect, switch to server player, wait for heli and see, if there are mouse actions appearing for destination/way of disembark choice). With hint message pointing new caller, but not sure, if it shows up. 

Share this post


Link to post
Share on other sites

HAS 1.9 wip5

 

Added new variable: 

 

RYD_HAS_RespawnHelis = 1;//if positive, destroyed/immobilized HAS helicopter will be after 60 seconds replaced by new one, placed, where destroyed was placed when was added to HAS. Old one will be deleted along with the crew (to avoid potentially unlimited objects accumulation). Value represents number of respawns. 0 - disabled, -1 - unlimited

 

It is now set to 1, but by default will be 0. "Immobilized" means grounded due to damage, without the pilot or fuel. This value can be changed on the fly, but it's not recommended. Helis added to HAS when it is equal to 0, will be ignored, also those destroyed when 0, may be not respawned, if later variable changed to other value. 

 

Let me know, if that's useful and if it works in various circumstancies. 

 

NOTE: although vanilla createVehicle supposedly tries to spawn a vehicle at some safe place near, if exact spot is blocked, from own experience I would recommend to avoid placing initial helis or adding new later, that at adding them to HAS moment are located in some weird/risky as for collisions places (or mid air...). Also better do not block such position with any objects later. But if anyone will do some tests, please, try thses things, I do not recommend to let us know the actual fate of spawned helis in such cases. 

 

To do: if CAS heli is destroyed during firing at the area, CAS task map markers seem to stay, should be deleted. 

  • Like 1

Share this post


Link to post
Share on other sites
7 hours ago, Rydygier said:

where destroyed was placed when was added to HAS.

So basically if the heli was placed at a base in the editor like at a base on a helipad then thats where it will respawn at correct?

This would also still reduce the call by 1 correct?

 

So if you had a limit of 4 calls, 4 times you can call a transport or cas, then if the heli was shot down and then respawned that would still

be counted as using 1 of the 4 calls leaving only 3, so then if you were at lets say the last call, and the heli got shot down, then it wouldn't respawn

as your out of calls is that how it works?

Share this post


Link to post
Share on other sites
Quote

So basically if the heli was placed at a base in the editor like at a base on a helipad then thats where it will respawn at correct?

 

Correct.

 

Quote

This would also still reduce the call by 1 correct?

 

Not the call limit, but will reduce RYD_HAS_RespawnHelis value (it defines separate limit for respawns). Unless RYD_HAS_RespawnHelis  = -1; (any negative number to be exact), in that case there's no respawn limit. Call limit is decreased by 1 every time, a call is initiated and only then. So there are two independent limits: for calls and for respawns. 

 

To clarify: newly spawned heli will not automatically pick up a call, that was interrupted due to previous heli destruction in the middle of it. 

 

Quote

so then if you were at lets say the last call, and the heli got shot down, then it wouldn't respawn

as your out of calls is that how it works?

 

Helis will keep respawning when destroyed regardless of call limit, as long respawn limit is not equal to 0. Unless you have RYD_HAS_RemoveAtLimit = true;. In this case, whole HAS script will exit, when call limit down to 0. Respawns included. 

  • Thanks 1

Share this post


Link to post
Share on other sites

HAS 1.9 wip6

 

Requested: optional feature to speed up heli's availability after task completion:

 

RYD_HAS_FastReady = true;//if true, helicopter will be ready for another task at the begining of his RTB, not at the end of it. 

 

So, player should be able to call the same heli again just after disembark at destination/just after cargo drop/CAS provided. Of course in case of cargo, heli must anyway return to the base to pick up another container. That's the idea. Thing is, these parts of logic complex and easier to break than improve. This was tested in SP for troops transport only with few basic situations. That's not enough. If anyone interested in helping - much more tests in all three types of tasks SP/MP with/without middle waypoints feature enabled/disabled would be appreciated. 

  • Like 1

Share this post


Link to post
Share on other sites

Tested the HAS v1.9 wip6

In Sp and Mp lan and had no issues with anything, tested the new call back function making sure to call the same heli that i had called for transport,

and was headed back to base after he dropped us off he turned right around, i threw my smoke, the heli landed and picked us up.

 

  Also tested the respawn function, i added some enemy to the demo mission where they would engage the enemy and shoot it down,

which they did,  i went to camera and seen the heli respawn, works.

    Nice work Rydygier!

  • Like 1
  • Thanks 1

Share this post


Link to post
Share on other sites

Update

Version 1.9

 

Changelog:

  • Fixed: units added via RYD_HAS_newUnit mid-game should get back HAS calls after respawn;
  • Fixed: if CAS heli is destroyed during firing at the area, CAS task map markers should be deleted; 
  • Added new user variable (cannot be changed on-the-fly - attempt will be futile) - RYD_HAS_addJIPs = true;//if true, JIP-ing players will automatically get access to HAS calls;
  • Provided global and "per unit" switches for selective enabling/disabling access to each type of support;
  • Added new variable: RYD_HAS_RespawnHelis = 0;//if positive, destroyed/immobilized HAS helicopter will be after 60 seconds replaced by new one, placed, where destroyed was placed when was added to HAS. Old one will be deleted along with the crew (to avoid potentially unlimited objects accumulation). Value represents number of respawns. 0 - disabled, -1 - unlimited
  • Optional feature that speeds up heli's availability after task completion: RYD_HAS_FastReady = false;//if true, helicopter will be ready for another task at the beginning of his RTB, not at the end of it.   

Notes:

  • Armaholic module and script version
  • Steam workshop version for module
  • Google drive download
  • PDF manual
  • 1st post updated features, links, and changelog

All linked on the OP (1st post).

=========

Thank you to those who had questions, tested and provided feedback for us to improve, fix, and add some great new functions to the script and module!

 

I want to thank Rydygier for his incredible continuous work on the script and module, and for providing the community with an exceptional module

and script for us to enhance and make our games so much more enjoyable!

Cheers!

  • Like 2
  • Thanks 1

Share this post


Link to post
Share on other sites

Update

Changelog

9-23-19

Update v1.91

  • Fixed game freeze at respawn. 

This update fixes the respawn issue, when using the module, and you had respawned the game would freeze and eventually crashed

see my post here for details.

 

Rydygier had fixed the code,

heres what he figured out if anyone was curious as to what was going on:

From his pm:

Quote

I think, I found the cause. At respawn my Respawn Event Handler code "adds itself" to the unit, so the same code should be executed on newly respawned unit after each consequtive respawn too. What I didn't expected is,

that code gets executed right after it's added, like currently pending Respawn already triggers newly added during that respawn new "Respawn" EH. In the result we have executed code stacking ad infinitum, which causes observed freeze. 

i had done several tests on the new version to confirm that its fixed.

     1st post updated with new links, armaholic has new files too, and steamworkshop is updated as well.

  • Like 2
  • Thanks 1

Share this post


Link to post
Share on other sites

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now

×