Jump to content
Sign in to follow this  
CarlGustaffa

Script for getting equipment lost in water back.

Recommended Posts

Here is my humble attempt on a script that will get back equipment that was dropped while taking a swim.

It differs from the other approaches I've seen in the following ways:

1) No surfaceIsWater checks, instead it deals with animation checks. Not tested, but should work also with ponds.

2) Slightly different approach for AI and human players. AI will use the normal array method, but for human players the dropped equipment will appear 3 meters in front of them when they stop swimming. That means that no magazines are magically refilled for players - I hate such exploits. For human players, consider it having to spend a little extra time cleaning up the equipment after it got wet.

3) You can define areas where this will take place, such as near the coast or at certain lakes, by placing triggers. Use "anybody" if you want everyone to get their equipment back, or enemy side if you only want to help the AI in a coop (which have serious issues near water).

4) There is only one master script that is looping at any time, reducing overhead when there are no units swimming. And due to the trigger approach, there is not much done in that script (it just waits and restarts itself) while the triggers are empty. Each unit does suffer his own spawned script, but it shouldn't be a problem unless there is a serious amount of units swimming.

5) Backpacks are handled; players get their old backpack placed in the heap of equipment, and AI gets their old backpack back but with fresh ammo.

Sorry, I wasn't able to make use of actions "TakeMagazine" and "TakeWeapon" in a good enough fashion. Feel free to improve.

Known bugs:

1) Sometimes the script doesn't figure out that someone dropped his weapon. I find that very odd. When you run with debug, you'll notice that when the dropped weapon message kicks in, the unit will get it back. But some times it just won't happen. Feel free to fix, I don't have more time for this one.

I called the script "w.sqf". If you rename it, update the execVM's in the script.

The triggers to check are defined at the top.

Ok, the script, which wasn't really tested much. It was just an experiment on what could be done. I left in the qq handles which I only used for manual termination while debugging. They are not needed. Could possibly use a touchup from a professional :p

#ifndef __chat
#define __chat(what) (player globalChat format ["--:" + what])
#endif
private ["_i", "_triggers", "_units", "_unit", "_intrig","_magsorg", "_wepsorg", "_magsnow", "_wepsnow", "_anim", "_debug"];
_triggers = [watertrigger1, watertrigger2, watertrigger3];
_debug = true;
_units = [];
{
for "_i" from 0 to count _triggers - 1 do {
	if (_x == vehicle _x && _x isKindOf "man" && _x in list (_triggers select _i)) then {
		if !(_x in _units) then {
			_units set [count _units, _x];
		};
	};
};
} forEach allUnits;
if (count _units == 0) exitWith {
sleep 5;
qq = execVM "w.sqf";
};
{
_swimming = _x getVariable "swimming";
if (isNil "_swimming") then {
	_x setVariable ["swimming", false];
};
} forEach _units;
if (_debug) then {_str = format ["Restart at %1", floor time]; __chat(_str)};
for "_i" from 0 to count _units - 1 do {
_unit = _units select _i;
_anim = animationState _unit; _anim = toArray _anim; _anim resize 4; _anim = toString _anim;
if (_anim == "aswm") then { //Avoid surfaceIsWater check which fails for ponds.
	_magsorg = magazines _unit; _unit setVariable ["magsorg", _magsorg];
	_wepsorg = weapons _unit; _unit setVariable ["wepsorg", _wepsorg];
	_swimming = _unit getVariable "swimming";
	if (!_swimming) then {
//BEGIN SPAWN
		[_unit, _debug] spawn {
			_unit = _this select 0;
			_debug = _this select 1;
			_unit setVariable ["swimming", true];
			if (!isPlayer _unit && !isNull unitBackpack _unit) then {
				_unit setVariable ["backpack", typeOf unitBackpack _unit];
				_unit setVariable ["backpackmags", getMagazineCargo unitBackpack _unit];
				_unit setVariable ["backpackweps", getWeaponCargo unitBackpack _unit];
				removeBackpack _unit;
			};
			_repeat = true;
			while {_unit getVariable "swimming" && alive _unit && _repeat} do {
if(_debug) then {_str = format ["%1 (%2) is swimming.", name _unit, typeOf _unit]; __chat(_str)};
				_droppedequipment = _unit getVariable "droppedequipment";
				if (primaryWeapon _unit == "") then {
if(_debug) then {_str = format ["%1 (%2) lost his equipment.", name _unit, typeOf _unit]; __chat(_str)};
					_droppedequipment = [];
					_containers = nearestObjects [_unit, ["WeaponHolder", "Bag_Base_EP1"], 10]; //Sometimes more than one WeaponHolder is dropped. Christ!!!
					for "_i" from 0 to count _containers - 1 do {
						_owner = (_containers select _i) getVariable "owner";
						if (isNil "_owner") then {
							(_containers select _i) setVariable ["owner", _unit, true]; //needs to be broadcast
							_droppedequipment set [count _droppedequipment, _containers select _i];
						};
					};
					_unit setVariable ["droppedequipment", _droppedequipment];
					_repeat = false;
				};
				sleep 1;
			};
			if !(_unit getVariable "swimming") exitWith {
				_unit setVariable ["swimming", false];
if(_debug) then {_str = format ["%1 (%2) made it to shore without dropping equipment.", name _unit, typeOf _unit]; __chat(_str)};
			};
			waitUntil {!(alive _unit) || !(_unit getVariable "swimming")};
			if (!alive _unit) exitWith {
				_droppedequipment = _unit getVariable "droppedequipment";
				if (!isNil "_droppedequipment") then {
					{
						deleteVehicle _x;
					} forEach _droppedequipment;
				};
			};
if(debug) then {_str = format ["%1 (%2) is back on shore, restoring equipment.", name _unit, typeOf _unit]; __chat(_str)};
			_backpack = _unit getVariable "backpack";
			if (!isNil "_backpack" && !isPlayer _unit) then {
				_unit addBackpack _backpack;
				clearMagazineCargo (unitBackpack _unit);
				clearWeaponCargo (unitBackpack _unit);
				_backpackmags = _unit getVariable "backpackmags";
				_backpackweps = _unit getVariable "backpackweps";
				for "_i" from 0 to count (_backpackmags select 0) - 1 do {
					(unitBackpack _unit) addMagazineCargo [(_backpackmags select 0) select _i, (_backpackmags select 1) select _i];
				};
				for "_i" from 0 to count (_backpackweps select 0) - 1 do {
					(unitBackpack _p) addWeaponCargo [(_backpackmags select 0) select _i, (_backpackweps select 1) select _i];
				};
				_unit setVariable ["backpack", nil];
				_unit setVariable ["backpackmags", nil];
				_unit setVariable ["backpackweps", nil];
			};
			_containers = _unit getVariable "droppedequipment";
			{
				if (isPlayer _unit) then { //Players have to pickup their weapons themselves, simulate "cleaning". No support for volatiles without remove***Cargo commands.
					_x setPos [_unit modelToWorld [0,3,0] select 0, _unit modelToWorld [0,3,0] select 1, 0]; //It takes longer time, but it prevents the refilling of magazines exploit.
				} else { //AI will get it automatically but will get full clips, couldn't get "TakeMagazine" and "TakeWeapon" actions work.
					_magscontainer = getMagazineCargo _x;
					_wepscontainer = getWeaponCargo _x;
					for "_i" from 0 to count (_magscontainer select 0) - 1 do {
						for "_j" from 1 to ((_magscontainer select 1) select _i) do {
							_unit addMagazine ((_magscontainer select 0) select _i);
						};
					};
					for "_i" from 0 to count (_wepscontainer select 0) - 1 do {
						for "_j" from 1 to ((_wepscontainer select 1) select _i) do {
							_unit addWeapon ((_wepscontainer select 0) select _i);
						};
					};
					deleteVehicle _x;
				};
			} forEach _containers;
			_primw = primaryWeapon _unit;
			if (_primw != "") then {
				_unit selectWeapon _primw;
				_unit selectWeapon ((getArray(configFile >> "cfgWeapons" >> _primw >> "muzzles")) select 0);
			};
		};
//END SPAWN
	};
} else {
	sleep 3;
	_unit setVariable ["swimming", false];
};
};
sleep 2;
qq = execVM "w.sqf";

Share this post


Link to post
Share on other sites

AHHA! Just what I needed... thanks mate. I'll try to get it to work and test it out, because it will be very useful for me. Personally, I don't care if player looses his equipment in water (players should be smart enough not to cross long ponds!), but its a real pain in the ass for the AI.

Anyway, thanks again. I've been looking for something like this for ages. Its good to see someone has finally made it (I was trying to do it myself, but I'm still learning how to script :))

Share this post


Link to post
Share on other sites

If it doesn't work, and only need it for a few AIs, you might consider the script posted in post #28 of this thread. Mine was specifically made with players in mind, and that I could define certain locations via triggers where it would kick in. For AI's, you might want to include the muzzle fix and select weapon though.

Share this post


Link to post
Share on other sites

Whats the best way to run this script? Also does it run for a trigger area, or whole map???

Cheers

GC

Share this post


Link to post
Share on other sites

You only need to run it once, then it reruns itself. You can define problematic areas by setting the triggers you want at the top _triggers = ... statement. Haven't worked on this in ages, it was mostly a thought experiment. Note that since then we have some new commands addXXXCargoGlobal which are much less buggy to work with, so you might want to change those.

Edited by CarlGustaffa

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
Sign in to follow this  

×