/
repetitive_cleanup.sqf
252 lines (205 loc) · 8.26 KB
/
repetitive_cleanup.sqf
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
/*
AUTHOR: aeroson
NAME: repetitive_cleanup.sqf
VERSION: 2.2.1
CONTRIBUTE: https://github.com/aeroson/a3-misc
DESCRIPTION:
Custom made, used and tested garbage collector.
Improves performance for everyone by deleting things that are not seen by players.
Can delete everything that is not really needed.
By default: dead bodies, dropped items, smokes, chemlights, explosives, times and classes can be specified
You can add your own classes to delete and or change times.
Beware: if weapons on ground is intentional e.g. fancy weapons stack, it will delete them too.
Beware: if dead bodies are intentional it will delete them too.
Beware: if destroyed vehicles intentional it will delete them too.
Uses allMissionObjects "" to iterate over all objects, so it is fast.
Adds objects for deletion only if players are specified distance away from them.
Never again it will happen that vehicle, item or body is delete in front of players' eyes.
If you want something to withstand the clean up, paste this into it's init:
this setVariable["persistent",true];
USAGE:
paste into init
[] execVM 'repetitive_cleanup.sqf';
then open the script and adjust values in CNFIGURATION section
You might also need to disable Bohemia's garbage collector, seems it's enabled by default despite wiki saying otherwise.
Source: https://community.bistudio.com/wiki/Description.ext
Add the following into your description.ext:
corpseManagerMode = 0;
wreckManagerMode = 0;
*/
if (!isServer) exitWith {}; // run only on server
#define COMPONENT repetitiveCleanup
#define DOUBLES(A,B) ##A##_##B
#define TRIPLES(A,B,C) ##A##_##B##_##C
#define QUOTE(A) #A
#define GVAR(A) DOUBLES(COMPONENT,A)
#define QGVAR(A) QUOTE(GVAR(A))
if (!isNil{GVAR(isRunning)} && {GVAR(isRunning)}) then { // if already running, request stop and wait until it stops
GVAR(isRunning)=false;
waitUntil{isNil{GVAR(isRunning)}};
};
GVAR(isRunning)=true;
//==================================================================================//
//=============================== CNFIGURATION start ===============================//
//==================================================================================//
#define M 1 // multiplier for times for debuging purposes
private _ttdBodies = M* 1*60; // seconds to delete dead bodies (0 means don't delete)
private _ttdVehiclesDead = M* 5*60; // seconds to delete dead vehicles (0 means don't delete)
private _ttdVehiclesImmobile = M* 10*60; // seconds to delete immobile vehicles (0 means don't delete)
GVAR(deleteClassesConfig) = [
// player placed or created objects that you probably want to delete once they are far enough
[M* 30*60, ["ACE_Explosives_Place","ACE_DefuseObject","TimeBombCore"]],
[M* 10*60, ["BagFence_base_F","CraterLong_small","CraterLong","SmokeShell"]],
[M* 5*60, ["AGM_FastRoping_Helper","#dynamicsound","#destructioneffects","#track","#particlesource"]],
[M* 60, ["WeaponHolder","GroundWeaponHolder","WeaponHolderSimulated"]]
];
GVAR(resetTimeIfPlayerIsWithin) = 300; // how far away from object player needs to be so it can delete
//==================================================================================//
//=============================== CNFIGURATION end =================================//
//==================================================================================//
private _excludedMissionObjects = allMissionObjects ""; // those objects were placed thru editor you probably don't want to remove those
GVAR(objectsToCleanup)=[];
GVAR(timesWhenToCleanup)=[];
GVAR(originalCleanupDelays)=[];
GVAR(resetTimeIfPlayerNearby)=[]; // might want to do it on my own in more effective way
GVAR(deleteThoseIndexes)=[];
private ["_markArraysForCleanupAt", "_deleteMarkedIndexes"];
#define IS_SANE(OBJECT) ((!isNil{OBJECT}) && ({!isNull(OBJECT)}))
_markArraysForCleanupAt = {
params [
"_index"
];
GVAR(deleteThoseIndexes) pushBack _index;
};
_deleteMarkedIndexes = {
GVAR(deleteThoseIndexes) sort false; // delete indexes from end to start of the array
{
GVAR(objectsToCleanup) deleteAt _x;
GVAR(timesWhenToCleanup) deleteAt _x;
GVAR(originalCleanupDelays) deleteAt _x;
GVAR(resetTimeIfPlayerNearby) deleteAt _x;
} forEach GVAR(deleteThoseIndexes);
GVAR(deleteThoseIndexes) = [];
};
GVAR(addToCleanup) = {
params [
"_object",
["_delay", 60, [0]],
["_resetTimerIfPlayerNearby", true, [true,false]],
["_resetValuesIfObjectAlreadyPresent", false, [true,false]]
];
private ["_newTime", "_index", "_currentTime"];
if(IS_SANE(_object) && {!(_object getVariable["persistent",false])}) then {
_newTime = _delay + time;
_index = GVAR(objectsToCleanup) find _object;
if(_index == -1) then {
GVAR(objectsToCleanup) pushBack _object;
GVAR(timesWhenToCleanup) pushBack _newTime;
GVAR(originalCleanupDelays) pushBack _delay;
GVAR(resetTimeIfPlayerNearby) pushBack _resetTimerIfPlayerNearby;
} else {
if(_resetValuesIfObjectAlreadyPresent) then {
GVAR(timesWhenToCleanup) set[_index, _newTime];
GVAR(originalCleanupDelays) set[_index, _delay];
GVAR(resetTimeIfPlayerNearby) set[_index, _resetTimerIfPlayerNearby];
};
};
};
};
GVAR(removeFromCleanup) = {
params [
"_object"
];
if(IS_SANE(_object)) then {
_index = GVAR(objectsToCleanup) find _object;
if(_index!=-1) then {
[_index] call _markArraysForCleanupAt;
};
};
};
private ["_playerPositions", "_unit", "_myPos", "_delay", "_newTime", "_object", "_objectIndex"];
while{GVAR(isRunning)} do {
sleep 10;
// if there is still alot of object to delete, slowly decrease the required distance from player
if(count(GVAR(objectsToCleanup)) > 200) then {
GVAR(resetTimeIfPlayerIsWithin_multiplicator) = GVAR(resetTimeIfPlayerIsWithin_multiplicator) - 0.01;
if(GVAR(resetTimeIfPlayerIsWithin_multiplicator) < 0.1) then {
GVAR(resetTimeIfPlayerIsWithin_multiplicator) = 0.1;
};
} else {
GVAR(resetTimeIfPlayerIsWithin_multiplicator) = 1;
};
{
_object = _x;
{
_timeToDelete = _x select 0;
_clasesToDelete = _x select 1;
if(_timeToDelete>0) then {
{
if( (typeof _object == _x) || {(_object isKindOf _x)} ) then {
[_object, _timeToDelete, true, false] call GVAR(addToCleanup);
};
} forEach _clasesToDelete;
};
} forEach GVAR(deleteClassesConfig);
} forEach (allMissionObjects "" - _excludedMissionObjects);
/*
// deleteGroup requires the group to be local
{
if ((count units _x)==0) then {
deleteGroup _x;
};
} forEach allGroups;
*/
if (_ttdBodies>0) then {
{
[_x, _ttdBodies, true, false] call GVAR(addToCleanup);
} forEach (allDeadMen - _excludedMissionObjects);
};
if (_ttdVehiclesDead>0) then {
{
if(_x == vehicle _x) then { // make sure its vehicle
[_x, _ttdVehiclesDead, true, false] call GVAR(addToCleanup);
};
} forEach (allDead - allDeadMen - _excludedMissionObjects); // all dead without dead men == mostly dead vehicles
};
if (_ttdVehiclesImmobile>0) then {
{
if(!canMove _x && {alive _x} count crew _x==0) then {
[_x, _ttdVehiclesImmobile, true, false] call GVAR(addToCleanup);
} else {
[_x] call GVAR(removeFromCleanup);
};
} forEach (vehicles - _excludedMissionObjects);
};
_playerPositions = [];
{
_playerPositions pushBack (getPosATL _x);
} forEach allPlayers;
GVAR(resetTimeIfPlayerIsWithin)Sqr = GVAR(resetTimeIfPlayerIsWithin) * GVAR(resetTimeIfPlayerIsWithin) * GVAR(resetTimeIfPlayerIsWithin_multiplicator);
call _deleteMarkedIndexes;
{
_object = _x;
_objectIndex = _forEachIndex;
if(IS_SANE(_object)) then {
if(GVAR(resetTimeIfPlayerNearby) select _objectIndex) then {
_myPos = getPosATL _object;
{
if(GVAR(resetTimeIfPlayerIsWithin)Sqr == 0 || {(_myPos distanceSqr _x) < GVAR(resetTimeIfPlayerIsWithin)Sqr}) exitWith {
_delay = GVAR(originalCleanupDelays) select _objectIndex;
_newTime = _delay + time;
GVAR(timesWhenToCleanup) set[_objectIndex, _newTime];
};
} forEach _playerPositions;
};
if((GVAR(timesWhenToCleanup) select _objectIndex) < time) then {
[_objectIndex] call _markArraysForCleanupAt;
deleteVehicle _object; // hideBody _object; sometimes doesn't work while deleteVehicle works always (yes even on corpses)
};
} else {
[_objectIndex] call _markArraysForCleanupAt;
};
} forEach GVAR(objectsToCleanup);
call _deleteMarkedIndexes;
};
GVAR(isRunning) = nil;