Jump to content
  • 0

Attachto and detach


Schultz

Question

Hello,

 

I'm testing a script that lets you detain other players, and it also has an option for escorting them. Basically it puts the target into a standing tied animation and it attaches it in front of you.

 

Everything works, except for releasing them. All other parts of the script work (removal of walk limitation etc) but sometimes the target stays attached to you

 

This is the code for the stop_escort.sqf

player removeAction act4;
player forceWalk false;
_newCiv = cursorTarget;
_dist = player distance _newCiv;
_newCiv setVariable ["Detain",0,true];
sleep 1;
detach _newCiv;
_newCiv setVariable ["Detain",1,true];
PVDZ_ply_Arrst = _newCiv;
publicVariable "PVDZ_ply_Arrst";
[objNull, _newCiv, rswitchmove ,"ActsPsitMstpSnonWunaDnon_sceneNikitinDisloyalty_Sykes"] call RE;
[objNull, _newCiv, rDisableuserinput,true] call RE;

I am really banging my head against this, but maybe another fresh point of view will help me!

 

The problem is that my cursor is slightly to the right of the guy who's attached to me, hence if I don't manually aim it's not gonna be detached.

 

Is there a way to define instead of cursorTarget something like the closest player to me?

 

Any ideas?

Link to comment
Share on other sites

Recommended Posts

  • 0

CursorTarget is probably unreliable, pass the attached object in a variable. I would suggest a global variable, or an non-networked setvar.

 

in detainPlayer.sqf (or whatever the name is)

_detainee = cursorTarget;
if ((isPlayer _detainee) && ((player distance _detainee) <= 2) then { //or whatever your conditions are
_detainee attachTo [player]; //if you want to get fancy you can use the player's hands memory point
_detainee setDir (getDir player);
player setVariable ["Detainee", _detainee, false];
};

in stop_escort.sqf

_detainee = player getVariable ["Detainee", false];

if (!isNil "_detainee") then {
detach _detainee;
};
Link to comment
Share on other sites

  • 0

i doubt that will work, i mean you cant detach yourself and why set a variable within the player?

 

if you want to make you can detach you need to save the variable within the detainees, but tbh i dont see the need for this ... just detach everything within certain range (or just man objects/playableunits if you have towing and you dont want it to interfere) ...

 

you could also take a look at life mod and see how they do it for police.

 

edit:

also that script is not the original ... the one you have, has been messed up by someone that has no clue what he was doing

{detach _x}forEach allunits;

^^this would theoreticly work, but i did not test it

Link to comment
Share on other sites

  • 0

i doubt that will work, i mean you cant detach yourself and why set a variable within the player?

 

if you want to make you can detach you need to save the variable within the detainees, but tbh i dont see the need for this ... just detach everything within certain range (or just man objects/playableunits if you have towing and you dont want it to interfere) ...

 

you could also take a look at life mod and see how they do it for police.

I'm well aware of how it's done, thanks. Don't be so defensive I'm trying to offer some suggestions in the form of prototyped code.

 

The detainee is the person that is being attached to the player, it's not attaching the player to the player... Also, like I said, I wouldn't rely on cursor target for things like this, which is why you would store the player object of the person being bound/detained in a NON-networked setvariable (it's a suggestion, if you need to use it on the remote player, then network it) you can change it to networked by changing false to true in setVariable.

 

I would also never detach anything within a certain distance of a player. Also, it's important to note that engine-built arrays/commands like allMissionObjects (AVOID THIS AT ALL COSTS, SERVER FPS DROPS TO 0 WHEN THIS IS RUN) and playableunits need to be recompiled every single time they are run, resulting in pretty massive overhead depending on how many players/objects are in the server and near the player.

 

If you insist on doing things by location rather than player objects/stored variables I'd recommend doing it like the following example.

_objsNear = player nearEntities [["Man"], 5];
_i = 0;
While {(count _objsNear) > _i} do { //would work better as a for loop, but fuck it.
	_entityI = _objsNear select _i;
	if (isPlayer _entityI) then {
		_attachObj = attachedObject (getPosATL player);
		_i = (count _objsNear) + 1; //exit loop
	};
	_i = _i + 1;
//DO NOT SLEEP IN THIS! it needs to be run as quickly as possible.
};
if (!isNil "_attachObj") then {
	detach _attachObj;
};
Link to comment
Share on other sites

  • 0

 

I'm well aware of how it's done, thanks. Don't be so defensive I'm trying to offer some suggestions in the form of prototyped code.

 

The detainee is the person that is being attached to the player, it's not attaching the player to the player... Also, like I said, I wouldn't rely on cursor target for things like this, which is why you would store the player object of the person being bound/detained in a NON-networked setvariable (it's a suggestion, if you need to use it on the remote player, then network it) you can change it to networked by changing false to true in setVariable.

 

I would also never detach anything within a certain distance of a player. Also, it's important to note that engine-built arrays/commands like allMissionObjects (AVOID THIS AT ALL COSTS, SERVER FPS DROPS TO 0 WHEN THIS IS RUN) and playableunits need to be recompiled every single time they are run, resulting in pretty massive overhead depending on how many players/objects are in the server and near the player.

 

If you insist on doing things by location rather than player objects/stored variables I'd recommend doing it like the following example.

_objsNear = player nearEntities [["Man"], 5];
_i = 0;
While {(count _objsNear) > _i} do { //would work better as a for loop, but fuck it.
	_entityI = _objsNear select _i;
	if (isPlayer _entityI) then {
		_attachObj = attachedObject (getPosATL player);
		_i = (count _objsNear) + 1; //exit loop
	};
	_i = _i + 1;
//DO NOT SLEEP IN THIS! it needs to be run as quickly as possible.
};
if (!isNil "_attachObj") then {
	detach _attachObj;
};

 

thanks for the lesson

 

now if you would look back at my code i posted, this will most likely work for what he wants to do, compared to youres wich will most likely just return objnull

 

reason i choose allunits is cause so many ppl has ai on their server, it would amaze me if someone did not attach an ai at some point and else use playableunits

 

if this causes issues on your server id suggest you get a better host

Link to comment
Share on other sites

  • 0

thanks for the lesson

 

now if you would look back at my code i posted, this will most likely work for what he wants to do, compared to youres wich will most likely just return objnull

 

reason i choose allunits is cause so many ppl has ai on their server, it would amaze me if someone did not attach an ai at some point and else use playableunits

 

if this causes issues on your server id suggest you get a better host

it's not an issue with any hardware, the engine literally freezes simulation in order to run allMissionObjects, as for allUnits, playableUnits it's run on the client not related to server performance.

 

If you need to include AI as well, you can just remove the isPlayer check. Also, the return of any command will never equal objNull, objNull is not even equal to itself (see the biki). The result of the nearestEntities command is an Array, which can never equal something other than an empty array, which will certainly not be null.

 

If you use the code you posted , it will detach an attached object. meaning if the player tries to detach the detainee it will detach every detainee.This is why the loop previously posted by me contains a limit of 5 meters away (it can be changed) and I would assume that you would only be able to detain a player so there's the isPlayer check as well.

 

Again, I suggest you use none of these and just use a setvar/global to store the original cursorTarget option returned by the addAction command. This way if it changes you will have the original reference, it may or may not help but it's more reliable then assuming the cursor target is unchanged.

Link to comment
Share on other sites

  • 0

it's not an issue with any hardware, the engine literally freezes simulation in order to run allMissionObjects, as for allUnits, playableUnits it's run on the client not related to server performance.

 

If you need to include AI as well, you can just remove the isPlayer check. Also, the return of any command will never equal objNull, objNull is not even equal to itself (see the biki). The result of the nearestEntities command is an Array, which can never equal something other than an empty array, which will certainly not be null.

 

If you use the code you posted , it will detach an attached object. meaning if the player tries to detach the detainee it will detach every detainee.This is why the loop previously posted by me contains a limit of 5 meters away (it can be changed) and I would assume that you would only be able to detain a player so there's the isPlayer check as well.

 

Again, I suggest you use none of these and just use a setvar/global to store the original cursorTarget option returned by the addAction command. This way if it changes you will have the original reference, it may or may not help but it's more reliable then assuming the cursor target is unchanged.

 

when did i say or refer to using allMissionObjects?

 

now if you can read the wiki about the code you posted, attachedObject returns the object a location is attached to. If the location is unattached, then objNull is returned.

 

afaik a player is not a location.

 

now for detaching all detainees i doubt that will be a problem, since your cursortarget is blocked anyway when you attach the first person in this range.

 

so if we can move along here i belive the simple one line of code i posted, will work for this, compared to your complicated attempt to do ... idk what you are trying to do really?

 

 

i can understand if you want to check if something is attached by setting a variable in the player and i cold have understood if you detached every man object within the radius, but this makes no sense.

Link to comment
Share on other sites

  • 0

when did i say or refer to using allMissionObjects?

 

now if you can read the wiki about the code you posted, attachedObject returns the object a location is attached to. If the location is unattached, then objNull is returned.

 

afaik a player is not a location.

 

now for detaching all detainees i doubt that will be a problem, since your cursortarget is blocked anyway when you attach the first person in this range.

 

so if we can move along here i belive the simple one line of code i posted, will work for this, compared to your complicated attempt to do ... idk what you are trying to do really?

 

 

i can understand if you want to check if something is attached by setting a variable in the player and i cold have understood if you detached every man object within the radius, but this makes no sense.

Imagine allUnits as an array of every single unit on the server (zombies, players, AI), that array is pretty damn big. Not only that if you itterate detach through every single one of them, you are creating network overhead as that command is networked, you will also detach every single unit from everything. Also, I simply provided allMissionObjects as an example of why you should refrain from using large arrays, I know it doesn't apply to this example but still it's related to allunits etc.

 

Yeah, my bad on the attachedObject command, thought it simply used location as a reference. But the cod I posted (is pretty simple), all it does is build a list of entities close enough to the player to be attached to him, not every single unit on the server. If you want, you could just change the attachedObject to detach and it would work.

 

Ex.

_objsNear = player nearEntities [["Man"], 5];
_i = 0;
While {(count _objsNear) > _i} do {
	_entityI = _objsNear select _i;
	if ((isPlayer _entityI) && (_newCiv getVariable ["Detain",0] == 1)) then {
		detach _entityI;
	};
	_i = _i + 1;
};

Edit: Here's a performance analysis of the differences in commands

{if(player distance _x < 5) then {}} forEach playableUnits => 0.01 s
{if(player distance _x < 5) then {}} forEach allUnits => 0.13 s
player nearEntities ['Man', 5] => 0.007 s

But again, it would be quicker and simpler to simple set a variable equal to the original player object of the detained player. As in the first reply by me. (before this thread got derailed)

Link to comment
Share on other sites

  • 0

i just love how you are telling me about using slow methods and then you go ahead and use a "while {expression} do" loop as example ... rofl

 

and for the record, allunits does not include agents ...

 

also, if you want to seperate them in my loop with distance, it would be very easy:

_pos=getposATL player;
{if(_x distance _pos < 6)then{detach _x};}forEach allunits;

or if you dont like the forEach loop and wants to use nearentities, you can do:

_manNear = player nearEntities [["CAManBase"], 5];
_cnt = (count _manNear);
for "_i" from 0 to _cnt do {
	_man = _manNear select _i;
	detach _man;
};
Link to comment
Share on other sites

  • 0

 

i just love how you are telling me about using slow methods and then you go ahead and use a "while {expression} do" loop as example ... rofl

 

and for the record, allunits does not include agents ...

 

also, if you want to seperate them in my loop with distance, it would be very easy:

_pos=getposATL player;
{if(_x distance _pos < 6)then{detach _x};}forEach allunits;

or if you dont like the forEach loop and wants to use nearentities, you can do:

_manNear = player nearEntities [["CAManBase"], 5];
_cnt = (count _manNear);
for "_i" from 0 to _cnt do {
	_man = _manNear select _i;
	detach _man;
};

I am and was well aware of the flaws of using binary addition to count in a while loop and its performance impact. I even stated that I was too lazy to change it, but for an example it would be fine. I am also aware that allUnits does not record agents, I forgot that zombies are agents; regardless nearEntities is still quicker.

 

Again, in both examples you are just detaching everything in a given distance; in the second example you will also run into a generic error since if the array is 5 items long you will only be able to use (_array select 4). In other words you would need to use _cnt = ((count _manNear) - 1);

 

Here's my example with a for loop...

_objsNear = player nearEntities [["Man"], 5];
for "_i" from 0 to (count _objsNear) do {
	_entityI = _objsNear select _i;
	if ((isPlayer _entityI) && (_newCiv getVariable ["Detain",0] == 1)) then {
		detach _entityI;
	};
};
Link to comment
Share on other sites

  • 0

lol ... in his eager to proove i made a mistake, he actually repeated the mistake himself in his copy paste of my example

 

edit:

and his ninja edit is also invalid for many obvius reasons

 

I didn't want to ingnite a fight here! 

 

Btw, this method:

{detach _x}forEach allunits;

works pretty well. Thanks!

I'm going to leave you with this offer, if you want a proper fix and approach upload your files, and I will fix them for you. If you want to completely mess the game up for people use Halvhjearne's code...

Link to comment
Share on other sites

  • 0

I didn't want to ingnite a fight here! 

 

Btw, this method:

{detach _x}forEach allunits;

works pretty well. Thanks!

 

he does have a valid point tho, that i did not think of.

better do this:

_pos=getposATL player;
{if(_x distance _pos < 5)then{detach _x};}forEach allunits;

or you might detach players parachuting aswell,

Link to comment
Share on other sites

  • 0

Oh ya you're right!

 

Let's do a thing, let's stop fighting and let's release a working version of this script.

 

One more problem: I want to be able to enter vehicles and move away with the detainee.

 

Right now at this point, the detainee stands on the ground when I get into a vehicle and he's teleported when I get out of the vehicle (still being attached to me).

 

Do you think there's a way to "attach" him to the vehicle I enter?

Link to comment
Share on other sites

  • 0

Oh ya you're right!

 

Let's do a thing, let's stop fighting and let's release a working version of this script.

 

One more problem: I want to be able to enter vehicles and move away with the detainee.

 

Right now at this point, the detainee stands on the ground when I get into a vehicle and he's teleported when I get out of the vehicle (still being attached to me).

 

Do you think there's a way to "attach" him to the vehicle I enter?

 

You can order the detainee to getinto the veichle like this.

//you'll need to use an addAction if you want to manually load the person, otherwise just make him get in when you do
[_newCiv] spawn { //NOTE: userInput must be disabled for the detainee in order for him to not be able to get out!
	_detainee = _this select 0;
	waitUntil {(vehicle player != player) || (_detainee getVariable ["Detain", 0] == 0) || (!alive player)}; //Wait for detained player to be released or local player to get into vehicle.
	_vehicle = vehicle player;
	_detained = _detainee getVariable ["Detain", 0];
	if (_detained == 1) then {
		_detainee action ["getInCargo", _vehicle];
	};
	waitUntil {(vehicle player == player) || (_detainee getVariable ["Detain", 0] == 0) || (!alive player)};
	_detained = _detainee getVariable ["Detain", 0]; //getVariable again, if it changed.
	if ((_detained == 1) && (alive player)) then {
		_detainee action ["getOut", _vehicle];
		[objNull, _detainee, rswitchmove ,"ActsPsitMstpSnonWunaDnon_sceneNikitinDisloyalty_Sykes"] call RE;
	} else {
		_detainee switchMove "": //reset anim state
		[objNull, _detainee, rDisableuserinput, false] call RE;
	};
}; 

Note: this will probably work, but no guarantees :)

This will also handle if the person detaining the detainee dies.

Link to comment
Share on other sites

  • 0

Let's do a thing: I'm gonna upload the whole script on github so we can work on it together. When it's done, we will release it in the correct section.

 

https://github.com/epochrp/detainsearchescortDZE

 

this isnt the original scripts ... some dude on opendayz.net has messed up some parts that will need to be removed

 

an idea i had before was to change _newciv to a global var and just check if its nil before adding a new target, then destroy the variable again when you detach

 

this will obviusly only allow to detain one guy at a time, but its a simple and easy sollution

and do you actually need to detain more at a time?

tbh i dont think it should be possible to handle more than one guy at a time anyway

Link to comment
Share on other sites

  • 0

this isnt the original scripts ... some dude on opendayz.net has messed up some parts that will need to be removed

 

an idea i had before was to change _newciv to a global var and just check if its nil before adding a new target, then destroy the variable again when you detach

 

this will obviusly only allow to detain one guy at a time, but its a simple and easy sollution

and do you actually need to detain more at a time?

tbh i dont think it should be possible to handle more than one guy at a time anyway

 

No there's no need for multiple detainees.

Link to comment
Share on other sites

  • 0

its not something i think i will be using so i cba to do this sorry, but something simple like changing _newciv to the_newciv and do like this could solve it:

if(isnil "the_newciv")then{
do some code block here to attach
}else{
do some text here about already a person attached
};

in the release script you dont need to change much but the variable and removing refrence to cursortarget so variable is not changed there, you can also do some text that no player is attached.

if there is a player attached just detach the_newciv and then the_newciv=nil; to kill the variable when you are done and you have released the other player

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Advertisement
  • Discord

×
×
  • Create New...