Merge branch 'master' into medical-rewrite

Conflicts:
	addons/medical_blood/XEH_postInit.sqf
This commit is contained in:
PabstMirror 2016-10-30 20:38:30 -05:00
commit 866612b974
87 changed files with 2662 additions and 867 deletions

View File

@ -29,6 +29,7 @@ Walter Pearce <jaynus@gmail.com>
# CONTRIBUTORS
[BIG]Bull
11RDP-LoupVert <loupvert@11rdp.fr>
654wak654 <ozanegitmen@gmail.com>
ACCtomeek <tomeek99@gmail.com>
adam3adam <br.ada@seznam.cz>
Adanteh

View File

@ -4,7 +4,7 @@
<p align="center">
<a href="https://github.com/acemod/ACE3/releases/latest">
<img src="https://img.shields.io/badge/Version-3.8.0-blue.svg?style=flat-square" alt="ACE3 Version">
<img src="https://img.shields.io/badge/Version-3.8.1-blue.svg?style=flat-square" alt="ACE3 Version">
</a>
<a href="https://github.com/acemod/ACE3/issues">
<img src="https://img.shields.io/github/issues-raw/acemod/ACE3.svg?style=flat-square&label=Issues" alt="ACE3 Issues">

View File

@ -142,6 +142,7 @@ PREP(setHearingCapability);
PREP(setName);
PREP(setParameter);
PREP(setPitchBankYaw);
PREP(setPlayerOwner);
PREP(setProne);
PREP(setSetting);
PREP(setSettingFromConfig);

View File

@ -0,0 +1,54 @@
/*
* Author: PabstMirror
* Sets the player's owner id as a variable on his player ojbect.
* Should be called on all machines (including server)
* Note: Needs to wait for CBA_clientID to be recieved from server.
*
* Arguments:
* None
*
* Return Value:
* None
*
* Example:
* [] call ace_common_fnc_setPlayerOwner
*
* Public: No
*/
// #define DEBUG_MODE_FULL
#include "script_component.hpp"
if (missionNameSpace getVariable [QGVAR(setPlayerOwnerRunning), false]) exitWith {};
GVAR(setPlayerOwnerRunning) = true;
if (isServer) then {
addMissionEventHandler ["HandleDisconnect", {
params ["_dcPlayer"];
TRACE_1("HandleDisconnect eh",_dcPlayer);
if (!isNil {_dcPlayer getVariable QGVAR(playerOwner)}) then {
_dcPlayer setVariable [QGVAR(playerOwner), nil, true];
};
}];
};
if (hasInterface) then {
[{
(!isNil "CBA_clientID") && {CBA_clientID > -1}
}, {
TRACE_1("CBA_clientID ready",CBA_clientID);
["unit", {
params ["_newUnit", "_oldUnit"];
TRACE_2("unit changed",_newUnit,_oldUnit);
if ((_oldUnit getVariable [QGVAR(playerOwner), -1]) == CBA_clientID) then {
_oldUnit setVariable [QGVAR(playerOwner), nil, true];
};
if (alive _newUnit) then {
_newUnit setVariable [QGVAR(playerOwner), CBA_clientID, true];
};
}, true] call CBA_fnc_addPlayerEventHandler;
}, []] call CBA_fnc_waitUntilAndExecute;
};

View File

@ -28,20 +28,16 @@ class CfgVehicles {
class Tank;
class Tank_F: Tank {
GVAR(ammoLocation) = "HitTurret";
GVAR(ammoLocation) = "HitHull";
GVAR(cookoffSelections)[] = {"poklop_gunner","poklop_commander"};
};
class MBT_01_base_F: Tank_F {
GVAR(ammoLocation) = "HitHull";
};
class APC_Tracked_01_base_F: Tank_F {
GVAR(ammoLocation) = "HitHull";
class MBT_02_base_F: Tank_F {
GVAR(ammoLocation) = "HitTurret";
};
class Car_F;
class Wheeled_APC_F: Car_F {
GVAR(ammoLocation) = "HitTurret";
GVAR(ammoLocation) = "HitHull";
GVAR(cookoffSelections)[] = {"poklop_gunner","poklop_commander"};
// big explosions for wheeled APCs (same as for tanks)

View File

@ -36,6 +36,22 @@ GVAR(cacheTankDuplicates) = call CBA_fnc_createNamespace;
["Wheeled_APC_F", "init", {
params ["_vehicle"];
private _typeOf = typeOf _vehicle;
if (isNil {GVAR(cacheTankDuplicates) getVariable _typeOf}) then {
private _hitpoints = (getAllHitPointsDamage _vehicle param [0, []]) apply {toLower _x};
private _duplicateHitpoints = [];
{
if ((_x != "") && {_x in (_hitpoints select [0,_forEachIndex])}) then {
_duplicateHitpoints pushBack _forEachIndex;
};
} forEach _hitpoints;
TRACE_2("dupes",_typeOf,_duplicateHitpoints);
GVAR(cacheTankDuplicates) setVariable [_typeOf, _duplicateHitpoints];
};
_vehicle addEventHandler ["HandleDamage", {
if ((_this select 0) getVariable [QGVAR(enable), GVAR(enable)]) then {
["tank", _this] call FUNC(handleDamage);

View File

@ -9,7 +9,7 @@
* None
*
* Example:
* (vehicle player) call ace_cookoff_fnc_cookOff
* [(vehicle player)] call ace_cookoff_fnc_cookOff
*
* Public: No
*/
@ -113,9 +113,12 @@ if (local _vehicle) then {
[_vehicle, _fnc_FlameEffect, 12] call _fnc_FlameEffect; // recursive function
private _randomPosition = _vehicle getPos [100, random 360];
{
if (local _x && {!(_x call EFUNC(common,isPlayer))}) then {
_x action ["Eject", _vehicle];
_x leaveVehicle _vehicle;
_x doMove _randomPosition;
};
} forEach crew _vehicle;

View File

@ -34,6 +34,7 @@ class CfgVehicles {
displayName = CSTRING(checkItem);
condition = "true";
statement = "";
exceptions[] = {"isNotInside", "isNotSitting"};
insertChildren = QUOTE(_this call DFUNC(addDogtagActions));
};
};

View File

@ -32,7 +32,7 @@ private _unitDogtagIDs = [];
//Create action children for all dogtags
private _actions = [];
{
private _displayName = format ["%1", getText (configFile >> "CfgWeapons" >> _x >> "displayName")];
private _displayName = getText (configFile >> "CfgWeapons" >> _x >> "displayName");
private _picture = getText (configFile >> "CfgWeapons" >> _x >> "picture");
private _action = [_x, _displayName, _picture, {_this call FUNC(checkDogtagItem)}, {true}, {}, _x] call EFUNC(interact_menu,createAction);

View File

@ -1 +1 @@
z\ace\addons\frag
z\ace\addons\frag

View File

@ -34,7 +34,6 @@ class ACE_Settings {
typeName = "SCALAR";
value = 50;
};
class GVAR(enableDebugTrace) {
category = CSTRING(Module_DisplayName);
displayName = CSTRING(EnableDebugTrace);

View File

@ -1,6 +1,6 @@
#define BASE_DRAG -0.01
#define HD_MULT 5
#define BASE_DRAG_HD (BASE_DRAG*HD_MULT)
#define BASE_DRAG -0.01
#define HD_MULT 5
#define BASE_DRAG_HD (BASE_DRAG * HD_MULT)
class CfgAmmo {
//class ace_arty_105mm_m1_m782_time;
@ -104,10 +104,8 @@ class CfgAmmo {
GVAR(gurney_k) = 1/2;
};
class ACE_G_40mm_HEDP: G_40mm_HEDP {
};
class ACE_G_40mm_HE: G_40mm_HE {
};
class ACE_G_40mm_HEDP: G_40mm_HEDP {};
class ACE_G_40mm_HE: G_40mm_HE {};
class ACE_G_40mm_Practice: ACE_G_40mm_HE {
GVAR(skip) = 1;
GVAR(force) = 0;
@ -438,8 +436,6 @@ class CfgAmmo {
indirectHitRange = 0.25;
airFriction = BASE_DRAG_HD*0.65;
caliber = 2;
};
class GVAR(huge): GVAR(large) {

View File

@ -1,5 +1,3 @@
//CfgAmmoReflections.hpp
#define ACE_EXPLOSION_REFLECTION(range, hit)\
class ace_explosion_reflection_##range##_##hit : ace_explosion_reflection_base {\
indirectHitRange = range;\

View File

@ -1,4 +1,3 @@
class Extended_PreStart_EventHandlers {
class ADDON {
init = QUOTE(call COMPILE_FILE(XEH_preStart));

View File

@ -22,7 +22,6 @@ PREP(addPfhRound);
PREP(removePfhRound); // THIS SHOULD ABE USED SPARINGLY
// Explosive Reflection
GVAR(replacedBisArtyWrapper) = true;
PREP(findReflections);
PREP(doExplosions);
PREP(doReflections);

View File

@ -1,16 +1,15 @@
#include "script_component.hpp"
if(GVAR(EnableDebugTrace) && !isMultiplayer) then {
if (GVAR(EnableDebugTrace) && {!isMultiplayer}) then {
GVAR(traceFrags) = true;
GVAR(autoTrace) = true;
};
if(isServer) then {
[QGVAR(frag_eh), { _this call FUNC(frago); }] call CBA_fnc_addEventHandler;
if (isServer) then {
[QGVAR(frag_eh), {_this call FUNC(frago);}] call CBA_fnc_addEventHandler;
};
["ace_settingsInitialized", {
//If not enabled, exit
if (!GVAR(enabled)) exitWith {};
// Register fire event handler
@ -20,9 +19,8 @@ if(isServer) then {
["ace_firedNonPlayerVehicle", DFUNC(fired)] call CBA_fnc_addEventHandler;
[FUNC(masterPFH), 0, []] call CBA_fnc_addPerFrameHandler;
}] call CBA_fnc_addEventHandler;
//Cache for ammo type configs
GVAR(cacheRoundsTypesToTrack) = createLocation ["ACE_HashLocation", [-10000,-10000,-10000], 0, 0];
// Cache for ammo type configs
GVAR(cacheRoundsTypesToTrack) = createLocation ["ACE_HashLocation", [-10000, -10000, -10000], 0, 0];
GVAR(cacheRoundsTypesToTrack) setText QGVAR(cacheRoundsTypesToTrack);

View File

@ -4,10 +4,11 @@ ADDON = false;
#include "XEH_PREP.hpp"
GVAR(replacedBisArtyWrapper) = true;
GVAR(blackList) = [];
GVAR(traceFrags) = false;
GVAR(TOTALFRAGS) = 0;
GVAR(totalFrags) = 0;
GVAR(spallHPData) = [];
GVAR(spallIsTrackingCount) = 0;

View File

@ -1,4 +1,5 @@
#include "script_component.hpp"
class CfgPatches {
class ADDON {
name = COMPONENT_NAME;

View File

@ -1,3 +1,5 @@
#include "script_component.hpp"
params ["_round"];
GVAR(blackList) set [(count GVAR(blackList)), _round];
GVAR(blackList) pushBack _round;

View File

@ -1,73 +1,67 @@
//#define DEBUG_MODE_FULL
#include "script_component.hpp"
private ["_enabled", "_doSpall", "_spallTrack", "_spallTrackID"];
PARAMS_3(_gun,_type,_round);
DEFAULT_PARAM(3,_doFragTrack,false);
params ["_gun", "_type", "_round", ["_doFragTrack", false]];
if (!GVAR(enabled)) exitWith {};
//_enabled = getNumber (configFile >> "CfgAmmo" >> _type >> QGVAR(enabled));
//if(_enabled < 1) exitWith {};
//if (_enabled < 1) exitWith {};
if(_round in GVAR(blackList)) exitWith {
GVAR(blackList) = GVAR(blackList) - [_round];
if (_round in GVAR(blackList)) exitWith {
REM(GVAR(blackList),_round);
};
// Exit on max track
if( (count GVAR(objects)) > GVAR(MaxTrack)) exitWith { };
if ((count GVAR(objects)) > GVAR(MaxTrack)) exitWith {};
if(_gun == ACE_player) then {
if (
_gun == ACE_player ||
{(gunner _gun) == ACE_player} ||
{local _gun && {!(isPlayer (gunner _gun))} && {!(isPlayer _gun)}}
) then {
_doFragTrack = true;
} else {
if((gunner _gun) == ACE_player) then {
_doFragTrack = true;
} else {
if(local _gun && {!(isPlayer (gunner _gun))} && {!(isPlayer _gun)}) then {
_doFragTrack = true;
};
};
};
_doSpall = false;
if(GVAR(SpallEnabled)) then {
if(GVAR(spallIsTrackingCount) <= 0) then {
private _doSpall = false;
if (GVAR(SpallEnabled)) then {
if (GVAR(spallIsTrackingCount) <= 0) then {
GVAR(spallHPData) = [];
};
if(GVAR(spallIsTrackingCount) > 5) then {
if (GVAR(spallIsTrackingCount) > 5) then {
// ACE_player sideChat "LIMT!";
} else {
_doSpall = true;
GVAR(spallIsTrackingCount) = GVAR(spallIsTrackingCount) + 1;
INC(GVAR(spallIsTrackingCount));
};
};
// ACE_player sideChat format["c: %1", GVAR(spallIsTrackingCount)];
// ACE_player sideChat format ["c: %1", GVAR(spallIsTrackingCount)];
if(GVAR(autoTrace)) then {
[ACE_player, _round, [1,0,0,1]] call FUNC(addTrack);
if (GVAR(autoTrace)) then {
[ACE_player, _round, [1, 0, 0, 1]] call FUNC(addTrack);
};
// We only do the single track object check here.
// We should do an {!(_round in GVAR(objects))}
// But we leave that out here for optimization. So this cannot be a framework function
// Otherwise, it should only be added once and from the FiredEH
if(_doFragTrack && {alive _round}) then {
_spallTrack = [];
_spallTrackID = [];
if (_doFragTrack && {alive _round}) then {
private _spallTrack = [];
private _spallTrackID = [];
private ["_args"];
_args = [_round, (getPosASL _round), (velocity _round), _type, diag_frameno, _gun, _doSpall, _spallTrack, _spallTrackID,
(getNumber (configFile >> "CfgAmmo" >> _type >> QGVAR(skip))),
(getNumber (configFile >> "CfgAmmo" >> _type >> "explosive")),
(getNumber (configFile >> "CfgAmmo" >> _type >> "indirectHitRange")),
(getNumber (configFile >> "CfgAmmo" >> _type >> QGVAR(force))),
(getNumber(configFile >> "CfgAmmo" >> _type >> "indirecthit")*(sqrt((getNumber (configFile >> "CfgAmmo" >> _type >> "indirectHitRange")))))
private _args = [
_round, getPosASL _round, velocity _round, _type, diag_frameno, _gun, _doSpall, _spallTrack, _spallTrackID,
getNumber (configFile >> "CfgAmmo" >> _type >> QGVAR(skip)),
getNumber (configFile >> "CfgAmmo" >> _type >> "explosive"),
getNumber (configFile >> "CfgAmmo" >> _type >> "indirectHitRange"),
getNumber (configFile >> "CfgAmmo" >> _type >> QGVAR(force)),
getNumber (configFile >> "CfgAmmo" >> _type >> "indirecthit") * (sqrt (getNumber (configFile >> "CfgAmmo" >> _type >> "indirectHitRange")))
];
TRACE_1("Initializing track", _round);
GVAR(objects) pushBack _round;
GVAR(arguments) pushBack _args;
if(_doSpall) then {
if (_doSpall) then {
[_round, 1, _spallTrack, _spallTrackID] call FUNC(spallTrack);
};
// ACE_player sideChat "WTF2";

View File

@ -5,16 +5,12 @@ if (GVAR(autoTrace)) then {
};
// setAccTime 0.05;
private _index = count GVAR(traces);
params ["_origin", "_obj"];
private _color = [1,0,0,1];
if((count _this) > 2) then {
_color = _this select 2;
};
params ["_origin", "_obj", ["_color", [1, 0, 0, 1]]];
private _positions = [];
private _objSpd = vectorMagnitude (velocity _obj);
_positions set[(count _positions), [(getPos _obj), _objSpd]];
_positions pushBack [getPos _obj, _objSpd];
private _data = [_origin, typeOf _origin, typeOf _obj, _objSpd, _positions, _color];
GVAR(traces) set[_index, _data];
private _index = GVAR(traces) pushBack _data;
[DFUNC(trackTrace), 0, [_obj, _index, CBA_missionTime]] call CBA_fnc_addPerFrameHandler;

View File

@ -1,7 +1,11 @@
#define DEBUG_MODE_FULL
#include "script_component.hpp"
params [["_debugMissing", true, [false]], ["_debugForce", false, [false]], ["_debugNonFrag", false, [false]]];
params [
["_debugMissing", true, [false]],
["_debugForce", false, [false]],
["_debugNonFrag", false, [false]]
];
diag_log text format ["~~~~~~~~~~~~~Start [%1]~~~~~~~~~~~~~", _this];
@ -10,7 +14,7 @@ private _processedCfgAmmos = [];
{
private _ammo = toLower getText (_x >> "ammo");
if ((_ammo != "") && {!(_ammo in _processedCfgAmmos)}) then {
if (_ammo != "" && {!(_ammo in _processedCfgAmmos)}) then {
_processedCfgAmmos pushBack _ammo;
//Ignore mines/bombs
@ -23,37 +27,37 @@ private _processedCfgAmmos = [];
private _explosive = getNumber (_ammoConfig >> "explosive");
private _indirectRange = getNumber (_ammoConfig >> "indirectHitRange");
private _force = getNumber (_ammoConfig >> QGVAR(force));
private _fragPower = getNumber(_ammoConfig >> "indirecthit")*(sqrt((getNumber (_ammoConfig >> "indirectHitRange"))));
private _fragPower = getNumber (_ammoConfig >> "indirecthit") * (sqrt ((getNumber (_ammoConfig >> "indirectHitRange"))));
private _shouldAdd = (_skip == 0) && {(_force == 1) || {_explosive > 0.5 && {_indirectRange >= 4.5} && {_fragPower >= 35}}};
if (_shouldAdd) then {
if (_debugForce && {((getNumber(_ammoConfig >> "hit")) < 5) || {_fragPower < 10}}) then {
diag_log text format ["Ammo [%1] from Mag [%2] - Weak but will still frag!",_ammo,configName _x];
diag_log text format [" - _force=%1,_fragPower=%2",_force,_fragPower];
diag_log text format ["Ammo [%1] from Mag [%2] - Weak but will still frag!", _ammo, configName _x];
diag_log text format [" - _force=%1,_fragPower=%2", _force, _fragPower];
};
_warn = false;
private _warn = false;
_fragTypes = getArray (_ammoConfig >> QGVAR(CLASSES));
if(_fragTypes isEqualTo []) then {_warn = true;};
if (_fragTypes isEqualTo []) then {_warn = true;};
_c = getNumber(_ammoConfig >> QGVAR(CHARGE));
if(_c == 0) then {_warn = true;};
if (_c == 0) then {_warn = true;};
_m = getNumber(_ammoConfig >> QGVAR(METAL));
if(_m == 0) then {_warn = true;};
if (_m == 0) then {_warn = true;};
_k = getNumber(_ammoConfig >> QGVAR(GURNEY_K));
if(_k == 0) then {_warn = true;};
if (_k == 0) then {_warn = true;};
_gC = getNumber(_ammoConfig >> QGVAR(GURNEY_C));
if(_gC == 0) then { _warn = true;};
if (_gC == 0) then {_warn = true;};
if(_debugMissing && _warn) then {
diag_log text format ["Ammo [%1] from Mag [%2] MISSING frag configs:",_ammo,configName _x];
diag_log text format [" - _c=%1,_m=%2,_k=%3,_gC=%4,_fragTypes=%5",_c,_m,_k,_gC,_fragTypes];
if (_debugMissing && {_warn}) then {
diag_log text format ["Ammo [%1] from Mag [%2] MISSING frag configs:", _ammo, configName _x];
diag_log text format [" - _c=%1,_m=%2,_k=%3,_gC=%4,_fragTypes=%5", _c, _m, _k, _gC, _fragTypes];
};
} else {
if (_debugNonFrag && {isArray (_ammoConfig >> QGVAR(CLASSES))}) then {
diag_log text format ["Ammo [%1] from Mag [%2] has frag configs but will NOT frag:",_ammo,configName _x];
diag_log text format ["- skip=%1,explosive=%2,indirectHitRange=%3,force=%4,fragPower=%5",_skip,_explosive,_indirectRange,_force,_fragPower];
diag_log text format ["Ammo [%1] from Mag [%2] has frag configs but will NOT frag:", _ammo, configName _x];
diag_log text format ["- skip=%1,explosive=%2,indirectHitRange=%3,force=%4,fragPower=%5", _skip, _explosive, _indirectRange, _force, _fragPower];
};
};
};

View File

@ -1,20 +1,22 @@
//fnc_doExplosions.sqf
#include "script_component.hpp"
params ["_args"];
params ["_args", "_pfhID"];
_args params ["_explosions", "_index"];
for "_i" from _index to ((_index+2) min (count _explosions)) do {
for "_i" from _index to ((_index + 2) min (count _explosions)) do {
private _exp = _explosions select _i;
_exp params ["_refExp", "_bpos", "_hit", "_distance", "_indirectHitRange", "_depth"];
_refExp createVehicle (ASLtoATL _bpos);
// if(_hit >= 150 && _distance > _indirectHitRange) then {
// if (_hit >= 150 && _distance > _indirectHitRange) then {
// [_bpos, _refExp, _depth] call FUNC(doReflections);
// };
};
_index = _index + 2;
if(_index >= (count _explosions)) then {
[(_this select 1)] call CBA_fnc_removePerFrameHandler;
ADD(_index,2);
if (_index >= count _explosions) then {
[_pfhID] call CBA_fnc_removePerFrameHandler;
} else {
_params set[1, _index];
_args set [1, _index];
};

View File

@ -1,14 +1,10 @@
//fnc_doReflections.sqf
#include "script_component.hpp"
params ["_pos", "_ammo"];
params ["_pos", "_ammo", ["_depth", 1]];
private _depth = 1;
if(count _this > 2) then {
_depth = _this select 2;
};
// TEST_ICONS pushBack [_pos, format["EXP!", _hit, _range, _hitFactor]];
if(_depth <= 2) then {
// TEST_ICONS pushBack [_pos, format ["EXP!", _hit, _range, _hitFactor]];
if (_depth <= 2) then {
private _indirectHitRange = getNumber(configFile >> "CfgAmmo" >> _ammo >> "indirectHitRange");
private _indirectHit = getNumber(configFile >> "CfgAmmo" >> _ammo >> "indirectHit");
private _testParams = [_pos, [_indirectHitRange, _indirectHit], [], [], -4, _depth, 0];

View File

@ -2,145 +2,126 @@
#include "script_component.hpp"
// ACE_player sideChat "WAAAAAAAAAAAAAAAAAAAAA";
params ["_hitData"];
params ["_hitData", "_hitPartDataIndex"];
private _initialData = GVAR(spallHPData) select (_hitData select 0);
private _hpData = (_hitData select 1) select (_this select 1);
_initialData params ["_hpId", "_object", "_roundType", "_round", "_curPos", "_velocity"];
_hpData params ["_object"];
_object removeEventHandler ["hitPart", _initialData select 0];
private _foundObjects = _initialData select 7;
private _index = _foundObjects find _object;
if(_index != -1) then {
_foundObjects set[_index, nil];
};
private _hpData = (_hitData select 1) select _hitPartDataIndex;
(_hpData select 0) removeEventHandler ["hitPart", _hpId];
_initialData params ["", "_object", "_roundType", "_round"];
private _caliber = getNumber (configFile >> "CfgAmmo" >> _roundType >> "caliber");
private _explosive = getNumber (configFile >> "CfgAmmo" >> _roundType >> "explosive");
private _idh = getNumber (configFile >> "CfgAmmo" >> _roundType >> "indirectHitRange");
private _caliber = getNumber(configFile >> "CfgAmmo" >> _roundType >> "caliber");
private _explosive = getNumber(configFile >> "CfgAmmo" >> _roundType >> "explosive");
private _idh = getNumber(configFile >> "CfgAmmo" >> _roundType >> "indirectHitRange");
if !(_caliber >= 2.5 || {(_explosive > 0 && {_idh >= 1})}) exitWith {};
// ACE_player sideChat format ["BBBB"];
private _exit = false;
private _vm = 1;
private _alive = true;
if(!alive _round && (_initialData select 6) isEqualTo 1) then {
_alive = false;
};
private _oldVelocity = vectorMagnitude _velocity;
private _curVelocity = vectorMagnitude (velocity _round);
if(_alive || {_caliber >= 2.5} || {(_explosive > 0 && {_idh >= 1})}) then {
// ACE_player sideChat format["BBBB"];
private _exit = false;
private _vm = 1;
private _velocity = _initialData select 5;
private _oldVelocity = vectorMagnitude _velocity;
private _curVelocity = vectorMagnitude (velocity _round);
if(alive _round) then {
private _diff = _velocity vectorDiff (velocity _round);
private _polar = _diff call CBA_fnc_vect2polar;
// ACE_player sideChat format["polar: %1", _polar];
if((abs(_polar select 1) > 45 || abs(_polar select 2) > 45)) then {
if(_caliber < 2.5) then {
// ACE_player sideChat format["exit!"];
_exit = true;
} else {
_vm = 1-(_curVelocity/_oldVelocity);
};
};
};
if(!_exit) then {
private _unitDir = vectorNormalized _velocity;
private _pos = _hpData select 3;
private _spallPos = nil;
for "_i" from 0 to 100 do {
private _pos1 = _pos vectorAdd (_unitDir vectorMultiply (0.01 * _i));
private _pos2 = _pos vectorAdd (_unitDir vectorMultiply (0.01 * (_i + 1)));
// _blah = [_object, "FIRE"] intersect [_object worldToModel (ASLtoATL _pos1), _object worldToModel (ASLtoATL _pos2)];
// diag_log text format["b: %1", _blah];
// _data = [nil, nil, nil, 1, [[ASLtoATL _pos1, 1], [ASLtoATL _pos2, 1]]];
// NOU_TRACES set[(count NOU_TRACES), _data];
if(!lineIntersects [_pos1, _pos2]) exitWith {
// ACE_player sideChat format["FOUND!"];
_spallPos = _pos2;
};
};
if(!isNil "_spallPos") then {
private _spallPolar = _velocity call CBA_fnc_vect2polar;
if(_explosive > 0) then {
// ACE_player sideChat format["EXPLOSIVE!"];
private _warn = false;
private _c = getNumber(configFile >> "CfgAmmo" >> _roundType >> QGVAR(CHARGE));
if(_c == 0) then { _c = 1; _warn = true;};
private _m = getNumber(configFile >> "CfgAmmo" >> _roundType >> QGVAR(METAL));
if(_m == 0) then { _m = 2; _warn = true;};
private _k = getNumber(configFile >> "CfgAmmo" >> _roundType >> QGVAR(GURNEY_K));
if(_k == 0) then { _k = 1/2; _warn = true;};
private _gC = getNumber(configFile >> "CfgAmmo" >> _roundType >> QGVAR(GURNEY_C));
if(_gC == 0) then { _gC = 2440; _warn = true;};
if(_warn) then {
WARNING_1("Ammo class %1 lacks proper explosive properties definitions for frag!",_roundType); //TODO: turn this off when we get closer to release
};
private _fragPower = (((_m/_c)+_k)^-(1/2))*_gC;
_spallPolar set[0, _fragPower*0.66];
};
private _fragTypes = [
QGVAR(spall_small), QGVAR(spall_small), QGVAR(spall_small),
QGVAR(spall_small),QGVAR(spall_medium),QGVAR(spall_medium),QGVAR(spall_medium),
QGVAR(spall_medium), QGVAR(spall_large), QGVAR(spall_large), QGVAR(spall_huge),
QGVAR(spall_huge)
];
// diag_log text format["SPALL POWER: %1", _spallPolar select 0];
private _spread = 15+(random 25);
private _spallCount = 5+(random 10);
for "_i" from 1 to _spallCount do {
private _elev = ((_spallPolar select 2)-_spread)+(random (_spread*2));
private _dir = ((_spallPolar select 1)-_spread)+(random (_spread*2));
if(abs _elev > 90) then {
_dir = _dir + 180;
};
_dir = _dir % 360;
private _vel = (_spallPolar select 0)*0.33*_vm;
_vel = (_vel-(_vel*0.25))+(random (_vel*0.5));
private _spallFragVect = [_vel, _dir, _elev] call CBA_fnc_polar2vect;
private _fragType = round (random ((count _fragTypes)-1));
private _fragment = (_fragTypes select _fragType) createVehicleLocal [0,0,10000];
_fragment setPosASL _spallPos;
_fragment setVelocity _spallFragVect;
if(GVAR(traceFrags)) then {
[ACE_player, _fragment, [1,0.5,0,1]] call FUNC(addTrack);
};
};
_spread = 5+(random 5);
_spallCount = 3+(random 5);
for "_i" from 1 to _spallCount do {
private _elev = ((_spallPolar select 2)-_spread)+(random (_spread*2));
private _dir = ((_spallPolar select 1)-_spread)+(random (_spread*2));
if(abs _elev > 90) then {
_dir = _dir + 180;
};
_dir = _dir % 360;
private _vel = (_spallPolar select 0)*0.55*_vm;
_vel = (_vel-(_vel*0.25))+(random (_vel*0.5));
private _spallFragVect = [_vel, _dir, _elev] call CBA_fnc_polar2vect;
private _fragType = round (random ((count _fragTypes)-1));
private _fragment = (_fragTypes select _fragType) createVehicleLocal [0,0,10000];
_fragment setPosASL _spallPos;
_fragment setVelocity _spallFragVect;
if(GVAR(traceFrags)) then {
[ACE_player, _fragment, [1,0,0,1]] call FUNC(addTrack);
};
};
if (alive _round) then {
private _diff = _velocity vectorDiff (velocity _round);
private _polar = _diff call CBA_fnc_vect2polar;
// ACE_player sideChat format ["polar: %1", _polar];
if (abs (_polar select 1) > 45 || {abs (_polar select 2) > 45}) then {
if (_caliber < 2.5) then {
// ACE_player sideChat format ["exit!"];
_exit = true;
} else {
SUB(_vm,_curVelocity / _oldVelocity);
};
};
};
if (_exit) exitWith {};
private _unitDir = vectorNormalized _velocity;
private _pos = _hpData select 3;
private _spallPos = [];
for "_i" from 0 to 100 do {
private _pos1 = _pos vectorAdd (_unitDir vectorMultiply (0.01 * _i));
private _pos2 = _pos vectorAdd (_unitDir vectorMultiply (0.01 * (_i + 1)));
// _data = [nil, nil, nil, 1, [[ASLtoATL _pos1, 1], [ASLtoATL _pos2, 1]]];
// NOU_TRACES pushBack _data;
if (!lineIntersects [_pos1, _pos2]) exitWith {
// ACE_player sideChat format ["FOUND!"];
_spallPos = _pos2;
};
};
if (_spallPos isEqualTo []) exitWith {};
private _spallPolar = _velocity call CBA_fnc_vect2polar;
if (_explosive > 0) then {
// ACE_player sideChat format ["EXPLOSIVE!"];
private _warn = false;
private _c = getNumber (configFile >> "CfgAmmo" >> _roundType >> QGVAR(CHARGE));
if (_c == 0) then {_c = 1; _warn = true;};
private _m = getNumber (configFile >> "CfgAmmo" >> _roundType >> QGVAR(METAL));
if (_m == 0) then {_m = 2; _warn = true;};
private _k = getNumber (configFile >> "CfgAmmo" >> _roundType >> QGVAR(GURNEY_K));
if (_k == 0) then {_k = 1 / 2; _warn = true;};
private _gC = getNumber (configFile >> "CfgAmmo" >> _roundType >> QGVAR(GURNEY_C));
if (_gC == 0) then {_gC = 2440; _warn = true;};
if (_warn) then {
WARNING_1("Ammo class %1 lacks proper explosive properties definitions for frag!",_roundType); //TODO: turn this off when we get closer to release
};
private _fragPower = (((_m / _c) + _k) ^ - (1 / 2)) * _gC;
_spallPolar set [0, _fragPower * 0.66];
};
private _fragTypes = [
QGVAR(spall_small), QGVAR(spall_small), QGVAR(spall_small),
QGVAR(spall_small),QGVAR(spall_medium),QGVAR(spall_medium),QGVAR(spall_medium),
QGVAR(spall_medium), QGVAR(spall_large), QGVAR(spall_large), QGVAR(spall_huge),
QGVAR(spall_huge)
];
// diag_log text format ["SPALL POWER: %1", _spallPolar select 0];
private _spread = 15 + (random 25);
private _spallCount = 5 + (random 10);
for "_i" from 1 to _spallCount do {
private _elev = ((_spallPolar select 2) - _spread) + (random (_spread * 2));
private _dir = ((_spallPolar select 1) - _spread) + (random (_spread * 2));
if (abs _elev > 90) then {
ADD(_dir,180);
};
_dir = _dir % 360;
private _vel = (_spallPolar select 0) * 0.33 * _vm;
_vel = (_vel - (_vel * 0.25)) + (random (_vel * 0.5));
private _spallFragVect = [_vel, _dir, _elev] call CBA_fnc_polar2vect;
private _fragType = round (random ((count _fragTypes) - 1));
private _fragment = (_fragTypes select _fragType) createVehicleLocal [0,0,10000];
_fragment setPosASL _spallPos;
_fragment setVelocity _spallFragVect;
if (GVAR(traceFrags)) then {
[ACE_player, _fragment, [1, 0.5, 0, 1]] call FUNC(addTrack);
};
};
_spread = 5 + (random 5);
_spallCount = 3 + (random 5);
for "_i" from 1 to _spallCount do {
private _elev = ((_spallPolar select 2) - _spread) + (random (_spread * 2));
private _dir = ((_spallPolar select 1) - _spread) + (random (_spread * 2));
if (abs _elev > 90) then {
ADD(_dir,180);
};
_dir = _dir % 360;
private _vel = (_spallPolar select 0) * 0.55 * _vm;
_vel = (_vel - (_vel * 0.25)) + (random (_vel * 0.5));
private _spallFragVect = [_vel, _dir, _elev] call CBA_fnc_polar2vect;
private _fragType = round (random ((count _fragTypes) - 1));
private _fragment = (_fragTypes select _fragType) createVehicleLocal [0, 0, 10000];
_fragment setPosASL _spallPos;
_fragment setVelocity _spallFragVect;
if (GVAR(traceFrags)) then {
[ACE_player, _fragment, [1, 0, 0, 1]] call FUNC(addTrack);
};
};

View File

@ -1,31 +1,23 @@
#include "script_component.hpp"
private ["_color", "_index", "_lastPos", "_lastSpd", "_max", "_positions", "_startSpeed"];
{
_positions = _x select 4;
_color = _x select 5;
_index = 0;
_max = count _positions;
_startSpeed = 0.01 max ((_positions select 0) select 1);
_lastSpd = [];
_lastPos = [];
private _positions = _x select 4;
private _color = _x select 5;
private _index = 0;
private _max = count _positions;
private _lastSpd = [];
private _lastPos = [];
while {_index < _max} do {
_data1 = _positions select _index;
_data2 = nil;
if(_index + ACE_TRACE_DRAW_INC >= _max) then {
_data2 = _positions select (_max - 1);
} else {
_data2 = _positions select (_index + ACE_TRACE_DRAW_INC);
};
_data2 = _positions select ([_index + ACE_TRACE_DRAW_INC, _max - 1] select (_index + ACE_TRACE_DRAW_INC >= _max));
_pos1 = _data1 select 0;
_pos2 = _data2 select 0;
_index = _index + ACE_TRACE_DRAW_INC;
ADD(_index,ACE_TRACE_DRAW_INC);
drawLine3D [_pos1, _pos2, _color];
_lastPos = _pos2;
_lastSpd = _data1 select 1;
};
// drawIcon3D ["", [1,0,0,1], _lastPos, 0, 0, 0, format["%1m/s", _lastSpd], 1, 0.05, "RobotoCondensed"];
// drawIcon3D ["", [1,0,0,1], _lastPos, 0, 0, 0, format ["%1m/s", _lastSpd], 1, 0.05, "RobotoCondensed"];
} forEach GVAR(traces);

View File

@ -1,61 +1,58 @@
//fnc_findReflections.sqf
#include "script_component.hpp"
private ["_lastPos", "_test", "_vec", "_testPos", "_buckets", "_excludes", "_bucketIndex", "_bucketPos", "_bucketList", "_c", "_index", "_blist", "_avgX", "_avgY", "_avgZ", "_bpos", "_distance", "_hitFactor", "_hit", "_range", "_refExp", "_i", "_x", "_res", "_forEachIndex", "_explosions", "_can", "_dirvec", "_zAng"];
BEGIN_COUNTER(fnc_findReflections);
params ["_args"];
params ["_args", "_pfhID"];
_args params ["_pos", "_explosiveInfo", "_los", "_nlos", "_zIndex", "_depth", "_rand"];
private _split = 15;
private _radi = (360/_split*_depth);
private _radi = 360 / _split * _depth;
// player sideChat format["p: %1", _explosiveInfo];
// player sideChat format ["p: %1", _explosiveInfo];
_explosiveInfo params ["_indirectHitRange", "_indirectHit"];
private _distanceCount = (floor _indirectHitRange*4) min 100;
private _distanceCount = (floor _indirectHitRange * 4) min 100;
if(_zIndex < 5) then {
_lastPos = _pos;
_zAng = _zIndex*20+2;
if(_zAng > 80) then {
if (_zIndex < 5) then {
private _lastPos = _pos;
private _zAng = _zIndex * 20 + 2;
if (_zAng > 80) then {
_radi = 1;
_zAng = 90;
};
for "_i" from 0 to _radi do {
_test = true;
_vec = [1, ((_i*_split)+_rand) mod 360, _zAng] call CBA_fnc_polar2vect;
private _test = true;
private _vec = [1, ((_i * _split) + _rand) % 360, _zAng] call CBA_fnc_polar2vect;
for "_x" from 1 to _distanceCount do {
_testPos = _pos vectorAdd (_vec vectorMultiply _x);
private _testPos = _pos vectorAdd (_vec vectorMultiply _x);
// drop ["\a3\data_f\Cl_basic","","Billboard",1,15,ASLtoATL _testPos,[0,0,0],1,1.275,1.0,0.0,[1],[[1,0,0,1]],[0],0.0,2.0,"","",""];
_res = lineIntersectsWith [_pos, _testPos];
if(count _res > 0) exitWith {
private _res = lineIntersectsWith [_pos, _testPos];
if (count _res > 0) exitWith {
_test = false;
_nlos pushBack _lastPos;
// {
// _x addEventHandler ["HandleDamage", { diag_log text format["this: %1", _this]; }];
// _x addEventHandler ["HandleDamage", { diag_log text format ["this: %1", _this]; }];
// } forEach _res;
// drop ["\a3\data_f\Cl_basic","","Billboard",1,15,ASLtoATL _testPos,[0,0,0],1,1.275,1.0,0.0,[1],[[1,0,0,1]],[0],0.0,2.0,"","",""];
// TEST_PAIRS pushBack [_pos, _lastPos, [1,0,0,1]];
};
// if(terrainIntersectASL [_pos, _testPos]) exitWith {};
// if (terrainIntersectASL [_pos, _testPos]) exitWith {};
_lastPos = _testPos;
};
};
_args set[4, _zIndex+1];
_args set [4, _zIndex + 1];
} else {
_depth = _depth + 1;
_buckets = [];
_excludes = [];
_bucketIndex = 0;
_bucketPos = nil;
_bucketList = nil;
_c = 0;
while { count(_nlos) != count(_excludes) && _c < (count _nlos) } do {
INC(_depth);
private _buckets = [];
private _excludes = [];
private _bucketPos = nil;
private _bucketList = nil;
private _c = 0;
while {count _nlos != count _excludes && {_c < (count _nlos)}} do {
scopeName "mainSearch";
{
if(!(_forEachIndex in _excludes)) then {
_index = _buckets pushBack [_x, [_x]];
if (!(_forEachIndex in _excludes)) then {
private _index = _buckets pushBack [_x, [_x]];
_excludes pushBack _forEachIndex;
_bucketPos = _x;
_bucketList = (_buckets select _index) select 1;
@ -63,59 +60,58 @@ if(_zIndex < 5) then {
};
} forEach _nlos;
{
if(!(_forEachIndex in _excludes)) then {
if (!(_forEachIndex in _excludes)) then {
_testPos = _x;
if(_testPos vectorDistanceSqr _bucketPos <= 30) then {
if (_testPos vectorDistanceSqr _bucketPos <= 30) then {
_bucketList pushBack _x;
_excludes pushBack _forEachIndex;
};
};
} forEach _nlos;
_c = _c + 1;
INC(_c);
};
// player sideChat format["c: %1", count _buckets];
_explosions = [];
// player sideChat format ["c: %1", count _buckets];
private _explosions = [];
{
_blist = _x select 1;
_avgX = 0;
_avgY = 0;
_avgZ = 0;
private _blist = _x select 1;
private _avgX = 0;
private _avgY = 0;
private _avgZ = 0;
{
_avgX = _avgX + (_x select 0);
_avgY = _avgY + (_x select 1);
_avgZ = _avgZ + (_x select 2);
ADD(_avgX,_x select 0);
ADD(_avgY,_x select 1);
ADD(_avgZ,_x select 2);
} forEach _blist;
_c = count _blist;
_bpos = [_avgX/_c, _avgY/_c, _avgZ/_c];
private _bpos = [_avgX / _c, _avgY / _c, _avgZ / _c];
_distance = _pos vectorDistance _bpos;
_hitFactor = 1-(((_distance/(_indirectHitRange*4)) min 1) max 0);
// _hitFactor = 1/(_distance^2);
_hit = _indirectHit*_hitFactor;
_hit = (floor (_hit/4)) min 500;
_hit = _hit - (_hit%10);
_range = (floor (_indirectHitRange-(_distance/4))) min 100;
_range = _range - (_range%2);
private _distance = _pos vectorDistance _bpos;
private _hitFactor = 1 - (((_distance / (_indirectHitRange * 4)) min 1) max 0);
// _hitFactor = 1 / (_distance ^ 2);
private _hit = _indirectHit * _hitFactor;
_hit = (floor (_hit / 4)) min 500;
SUB(_hit,_hit % 10);
private _range = (floor (_indirectHitRange - (_distance / 4))) min 100;
SUB(_range,_range % 2);
if(_hit >= 10 && _range > 0) then {
// TEST_ICONS pushBack [_bpos, format["h: %1, r: %2, hf: %3 d: %4 ihr: %5", _hit, _range, _hitFactor, _distance, _indirectHitRange*4]];
if (_hit >= 10 && {_range > 0}) then {
// TEST_ICONS pushBack [_bpos, format ["h: %1, r: %2, hf: %3 d: %4 ihr: %5", _hit, _range, _hitFactor, _distance, _indirectHitRange*4]];
// TEST_PAIRS pushBack [_pos, _bpos, [1,0,0,1]];
_refExp = format["ace_explosion_reflection_%1_%2", _range, _hit];
private _refExp = format ["ace_explosion_reflection_%1_%2", _range, _hit];
// _refExp createVehicle (ASLtoATL _bpos);
// drop ["\a3\data_f\Cl_basic","","Billboard",1,15,ASLtoATL _bpos,[0,0,0],1,1.275,1.0,0.0,[1],[[1,0,0,1]],[0],0.0,2.0,"","",""];
_explosions pushBack [_refExp, _bpos, _hit, _distance, _indirectHitRange/4, _depth];
_explosions pushBack [_refExp, _bpos, _hit, _distance, _indirectHitRange / 4, _depth];
};
if(count _explosions > (_radi*2)/_depth) exitWith {};
if (count _explosions > (_radi * 2) / _depth) exitWith {};
} forEach _buckets;
// _can = "Land_Bricks_V4_F" createVehicle (ASLtoATL _pos);
// _dirvec = _pos vectorFromTo ((ATLtoASL (player modelToWorldVisual (player selectionPosition "Spine3"))));
// _dirvec = _dirvec vectorMultiply 100;
// _can setVelocity _dirvec;
[DFUNC(doExplosions), 0, [_explosions, 0]] call CBA_fnc_addPerFrameHandler;
[(_this select 1)] call CBA_fnc_removePerFrameHandler;
[_pfhID] call CBA_fnc_removePerFrameHandler;
};
END_COUNTER(fnc_findReflections);

View File

@ -42,7 +42,7 @@ if (isNil "_shouldAdd") then {
private _explosive = getNumber (configFile >> "CfgAmmo" >> _ammo >> "explosive");
private _indirectRange = getNumber (configFile >> "CfgAmmo" >> _ammo >> "indirectHitRange");
private _force = getNumber (configFile >> "CfgAmmo" >> _ammo >> QGVAR(force));
private _fragPower = getNumber(configFile >> "CfgAmmo" >> _ammo >> "indirecthit")*(sqrt((getNumber (configFile >> "CfgAmmo" >> _ammo >> "indirectHitRange"))));
private _fragPower = getNumber (configFile >> "CfgAmmo" >> _ammo >> "indirecthit") * (sqrt (getNumber (configFile >> "CfgAmmo" >> _ammo >> "indirectHitRange")));
_shouldAdd = (_skip == 0) && {(_force == 1) || {_explosive > 0.5 && {_indirectRange >= 4.5} && {_fragPower >= 35}}};
TRACE_6("SettingCache[willFrag?]",_skip,_explosive,_indirectRange,_force,_fragPower,_shouldAdd);

View File

@ -6,44 +6,36 @@
#define MAX_FRAG_COUNT 50
if(!isServer) exitWith { };
if (!isServer) exitWith {};
BEGIN_COUNTER(frago);
// _startTime = diag_tickTime;
private ["_fuseDist", "_indirectHitRange", "_fragRange", "_c", "_m", "_k", "_gC", "_fragPower", "_fragPowerRandom", "_manObjects", "_objects", "_crew", "_fragCount", "_fragArcs", "_doRandom", "_boundingBox", "_targetPos", "_distance", "_add", "_bbX", "_bbY", "_bbZ", "_cubic", "_targetVel", "_baseVec", "_dir", "_currentCount", "_count", "_vecVar", "_vec", "_fp", "_vel", "_fragType", "_fragObj", "_randomCount", "_sectorSize", "_sectorOffset", "_i", "_randomDir", "_endTime", "_target"];
params ["_round", "_lastPos", "_lastVel", "_shellType"];
private _gun = nil;
if((count _this) > 5) then {
_gun = _this select 5;
};
params ["_round", "_lastPos", "_lastVel", "_shellType", "_firedFrame", "_gun"];
private _fragTypes = [
QGVAR(tiny), QGVAR(tiny), QGVAR(tiny),
QGVAR(tiny_HD), QGVAR(tiny_HD), QGVAR(tiny_HD),
QGVAR(small),QGVAR(small),QGVAR(small),QGVAR(small),
QGVAR(small_HD),QGVAR(small_HD),QGVAR(small_HD),QGVAR(small_HD),
QGVAR(small), QGVAR(small), QGVAR(small), QGVAR(small),
QGVAR(small_HD), QGVAR(small_HD), QGVAR(small_HD), QGVAR(small_HD),
QGVAR(medium_HD), QGVAR(medium_HD), QGVAR(medium_HD), QGVAR(medium_HD), QGVAR(medium_HD)
];
private _warn = false;
if(isArray (configFile >> "CfgAmmo" >> _shellType >> QGVAR(CLASSES))) then {
if (isArray (configFile >> "CfgAmmo" >> _shellType >> QGVAR(CLASSES))) then {
_fragTypes = getArray (configFile >> "CfgAmmo" >> _shellType >> QGVAR(CLASSES));
} else {
_warn = true;
};
private _atlPos = ASLtoATL _lastPos;
private _isArmed = true;
if(!isNil "_gun") then {
_fuseDist = getNumber(configFile >> "CfgAmmo" >> _shellType >> "fuseDistance");
if (!isNil "_gun") then {
private _fuseDist = getNumber(configFile >> "CfgAmmo" >> _shellType >> "fuseDistance");
_isArmed = ((getPosASL _gun) distance _lastPos > _fuseDist);
};
_indirectHitRange = getNumber(configFile >> "CfgAmmo" >> _shellType >> "indirecthitrange");
_fragRange = 20 * _indirectHitRange * 4;
private _indirectHitRange = getNumber(configFile >> "CfgAmmo" >> _shellType >> "indirecthitrange");
private _fragRange = 20 * _indirectHitRange * 4;
// _c = 185; // grams of comp-b
// _m = 210; // grams of fragmentating metal
// _k = 3/5; // spherical K factor
@ -54,26 +46,27 @@ _fragRange = 20 * _indirectHitRange * 4;
// _k = 1/2; // spherical K factor
// _gC = 2320; // Gurney constant of tritonal in /ms
private _c = getNumber (configFile >> "CfgAmmo" >> _shellType >> QGVAR(CHARGE));
if (_c == 0) then {_c = 1; _warn = true;};
private _m = getNumber (configFile >> "CfgAmmo" >> _shellType >> QGVAR(METAL));
if (_m == 0) then {_m = 2; _warn = true;};
private _k = getNumber (configFile >> "CfgAmmo" >> _shellType >> QGVAR(GURNEY_K));
if (_k == 0) then {_k = 0.5; _warn = true;};
private _gC = getNumber (configFile >> "CfgAmmo" >> _shellType >> QGVAR(GURNEY_C));
if (_gC == 0) then {_gC = 2440; _warn = true;};
_c = getNumber(configFile >> "CfgAmmo" >> _shellType >> QGVAR(CHARGE));
if(_c == 0) then { _c = 1; _warn = true;};
_m = getNumber(configFile >> "CfgAmmo" >> _shellType >> QGVAR(METAL));
if(_m == 0) then { _m = 2; _warn = true;};
_k = getNumber(configFile >> "CfgAmmo" >> _shellType >> QGVAR(GURNEY_K));
if(_k == 0) then { _k = 1/2; _warn = true;};
_gC = getNumber(configFile >> "CfgAmmo" >> _shellType >> QGVAR(GURNEY_C));
if(_gC == 0) then { _gC = 2440; _warn = true;};
if(_warn) then {
if (_warn) then {
WARNING_1("Ammo class %1 lacks proper explosive properties definitions for frag!",_shellType); //TODO: turn this off when we get closer to release
};
_fragPower = (((_m/_c)+_k)^-(1/2))*_gC;
private _fragPower = (((_m / _c) + _k) ^ - (1 / 2)) * _gC;
_fragPower = _fragPower * 0.8; // Gunery equation is for a non-fragmenting metal, imperical value of 80% represents fragmentation
_fragPowerRandom = _fragPower * 0.5;
if((_atlPos select 2) < 0.5) then {
_lastPos set[2, (_lastPos select 2)+0.5];
private _atlPos = ASLtoATL _lastPos;
private _fragPowerRandom = _fragPower * 0.5;
if ((_atlPos select 2) < 0.5) then {
_lastPos set [2, (_lastPos select 2) + 0.5];
};
// _manObjects = _atlPos nearEntities ["CaManBase", _fragRange];
@ -81,134 +74,130 @@ if((_atlPos select 2) < 0.5) then {
// setAccTime 0.01;
//_objects = nearestObjects [_atlPos, ["AllVehicles"], _fragRange]; // Not sure if tracking "ReammoBox" is required, if so revert this change for _objects
_objects = _atlPos nearEntities [["Car", "Motorcycle", "Tank", "StaticWeapon", "CAManBase", "Air", "Ship"], _fragRange];
private _objects = _atlPos nearEntities [["Car", "Motorcycle", "Tank", "StaticWeapon", "CAManBase", "Air", "Ship"], _fragRange];
// _objects = _manObjects;
// Target also people inside vehicles or manning weapons
_crew = [];
// Add unique crews in faster way
{
{
_crew set [count _crew,_x]
_objects pushBackUnique _x;
} forEach (crew _x);
} forEach _objects;
_objects = _objects - _crew;
_objects = _objects + _crew;
private _fragCount = 0;
_fragCount = 0;
_fragArcs = [];
_fragArcs set[360, 0];
private _fragArcs = [];
_fragArcs set [360, 0];
#ifdef DEBUG_MODE_FULL
ACE_player sideChat format["_fragRange: %1", _fragRange];
ACE_player sideChat format["_objects: %1", _objects];
ACE_player sideChat format ["_fragRange: %1", _fragRange];
ACE_player sideChat format ["_objects: %1", _objects];
#endif
_doRandom = true;
if(_isArmed && (count _objects) > 0) then {
private _doRandom = true;
if (_isArmed && {!(_objects isEqualTo [])}) then {
if (GVAR(ReflectionsEnabled)) then {
[_lastPos, _shellType] call FUNC(doReflections);
};
{
//if(random(1) > 0.5) then {
_target = _x;
if(alive _target) then {
_boundingBox = boundingBox _target;
_targetPos = (getPosASL _target);
_distance = _targetPos distance _lastPos;
_add = (((_boundingBox select 1) select 2)/2)+((((_distance-(_fragpower/8)) max 0)/_fragPower)*10);
_bbX = (abs((_boundingBox select 0) select 0))+((_boundingBox select 1) select 0);
_bbY = (abs((_boundingBox select 0) select 1))+((_boundingBox select 1) select 1);
_bbZ = (abs((_boundingBox select 0) select 2))+((_boundingBox select 1) select 2);
_cubic = _bbX * _bbY * _bbZ;
if(_cubic > 1) then {
//if (random(1) > 0.5) then {
private _target = _x;
if (alive _target) then {
private _boundingBox = boundingBox _target;
private _targetPos = getPosASL _target;
private _distance = _targetPos distance _lastPos;
private _add = (((_boundingBox select 1) select 2) / 2) + ((((_distance - (_fragpower / 8)) max 0) / _fragPower) * 10);
private _bbX = (abs ((_boundingBox select 0) select 0)) + ((_boundingBox select 1) select 0);
private _bbY = (abs ((_boundingBox select 0) select 1)) + ((_boundingBox select 1) select 1);
private _bbZ = (abs ((_boundingBox select 0) select 2)) + ((_boundingBox select 1) select 2);
private _cubic = _bbX * _bbY * _bbZ;
if (_cubic > 1) then {
_doRandom = true;
_targetVel = (velocity _target);
private _targetVel = velocity _target;
_targetPos = _targetPos vectorAdd [
(_targetVel select 0) * (_distance / _fragPower),
(_targetVel select 1) * (_distance / _fragPower),
_add
];
_targetPos set[0, (_targetPos select 0)+((_targetVel select 0)*(_distance/_fragPower))];
_targetPos set[1, (_targetPos select 1)+((_targetVel select 1)*(_distance/_fragPower))];
_targetPos set[2, (_targetPos select 2)+_add];
private _baseVec = _lastPos vectorFromTo _targetPos;
_baseVec = _lastPos vectorFromTo _targetPos;
_dir = floor(_baseVec call CBA_fnc_vectDir);
_currentCount = _fragArcs select _dir;
if(isNil "_currentCount") then {
_currentCount = 0;
};
if(_currentCount < 20) then {
_count = ceil(random(sqrt(_m/1000)));
_vecVar = FRAG_VEC_VAR;
if(!(_target isKindOf "Man")) then {
_vecVar = ((sqrt _cubic)/2000)+FRAG_VEC_VAR;
if((count (crew _target)) == 0 && _count > 0) then {
_count = 0 max (_count/2);
private _dir = floor (_baseVec call CBA_fnc_vectDir);
private _currentCount = _fragArcs select _dir;
ISNILS(_currentCount,0);
if (_currentCount < 20) then {
private _count = ceil (random (sqrt (_m / 1000)));
private _vecVar = FRAG_VEC_VAR;
if (!(_target isKindOf "Man")) then {
_vecVar = ((sqrt _cubic) / 2000) + FRAG_VEC_VAR;
if ((crew _target) isEqualTo [] && {_count > 0}) then {
_count = 0 max (_count / 2);
};
};
for "_i" from 1 to _count do {
_vec = +_baseVec;
private _vec = _baseVec vectorDiff [
(_vecVar / 2) + (random _vecVar),
(_vecVar / 2) + (random _vecVar),
(_vecVar / 2) + (random _vecVar)
];
_vec set[0, (_vec select 0)-(_vecVar/2)+(random _vecVar)];
_vec set[1, (_vec select 1)-(_vecVar/2)+(random _vecVar)];
_vec set[2, (_vec select 2)-(_vecVar/2)+(random _vecVar)];
private _fp = _fragPower - (random (_fragPowerRandom));
private _vel = _vec vectorMultiply _fp;
_fp = (_fragPower-(random (_fragPowerRandom)));
_vel = _vec vectorMultiply _fp;
_fragType = round (random ((count _fragTypes)-1));
_fragObj = (_fragTypes select _fragType) createVehicleLocal [0,0,10000];
// diag_log text format["fp: %1 %2", _fp, typeOf _fragObj];
private _fragType = round (random ((count _fragTypes) - 1));
private _fragObj = (_fragTypes select _fragType) createVehicleLocal [0,0,10000];
// diag_log text format ["fp: %1 %2", _fp, typeOf _fragObj];
_fragObj setPosASL _lastPos;
_fragObj setVectorDir _vec;
_fragObj setVelocity _vel;
if(GVAR(traceFrags)) then {
GVAR(TOTALFRAGS) = GVAR(TOTALFRAGS) + 1;
if (GVAR(traceFrags)) then {
INC(GVAR(totalFrags));
[ACE_player, _fragObj, [1,0,0,1]] call FUNC(addTrack);
};
_fragCount = _fragCount + 1;
_currentCount = _currentCount + 1;
INC(_fragCount);
INC(_currentCount);
};
_fragArcs set[_dir, _currentCount];
_fragArcs set [_dir, _currentCount];
};
};
};
//};
if(_fragCount > MAX_FRAG_COUNT) exitWith {};
if (_fragCount > MAX_FRAG_COUNT) exitWith {};
} forEach _objects;
if(_fragCount > MAX_FRAG_COUNT) exitWith {};
_randomCount = ((ceil((MAX_FRAG_COUNT - _fragCount)*0.1)) max 0)+20;
_sectorSize = 360 / (_randomCount max 1);
if (_fragCount > MAX_FRAG_COUNT) exitWith {};
private _randomCount = ((ceil ((MAX_FRAG_COUNT - _fragCount) * 0.1)) max 0) + 20;
private _sectorSize = 360 / (_randomCount max 1);
// _doRandom = false;
if(_doRandom) then {
if (_doRandom) then {
for "_i" from 1 to _randomCount do {
// Distribute evenly
_sectorOffset = 360 * (_i - 1) / (_randomCount max 1);
_randomDir = random(_sectorSize);
_vec = [cos(_sectorOffset + _randomDir), sin(_sectorOffset + _randomDir), sin(30 - (random 45))];
private _sectorOffset = 360 * (_i - 1) / (_randomCount max 1);
private _randomDir = random (_sectorSize);
_vec = [cos (_sectorOffset + _randomDir), sin (_sectorOffset + _randomDir), sin (30 - (random 45))];
_fp = (_fragPower-(random (_fragPowerRandom)));
_fp = (_fragPower - (random (_fragPowerRandom)));
_vel = _vec vectorMultiply _fp;
_fragType = round (random ((count _fragTypes)-1));
_fragObj = (_fragTypes select _fragType) createVehicleLocal [0,0,10000];
_fragType = round (random ((count _fragTypes) - 1));
_fragObj = (_fragTypes select _fragType) createVehicleLocal [0, 0, 10000];
_fragObj setPosASL _lastPos;
_fragObj setVectorDir _vec;
_fragObj setVelocity _vel;
if(GVAR(traceFrags)) then {
GVAR(TOTALFRAGS) = GVAR(TOTALFRAGS) + 1;
if (GVAR(traceFrags)) then {
INC(GVAR(totalFrags));
[ACE_player, _fragObj, [1,0.5,0,1]] call FUNC(addTrack);
};
_fragCount = _fragCount + 1;
INC(_fragCount);
};
};
};
// #ifdef DEBUG_MODE_FULL
// ACE_player sideChat format["total frags: %1", GVAR(TOTALFRAGS)];
// ACE_player sideChat format["total frags: %1", GVAR(totalFrags)];
// ACE_player sideChat format["tracks: %1", (count GVAR(trackedObjects))];
// #endif
// _endTime = diag_tickTime;

View File

@ -15,36 +15,35 @@
if (!GVAR(enabled)) exitWith {};
private ["_gcIndex", "_iter"];
_gcIndex = [];
private _gcIndex = [];
_iter = 0;
while { (count GVAR(objects)) > 0 && { _iter < (GVAR(MaxTrackPerFrame) min (count GVAR(objects))) } } do {
private ["_object", "_args"];
if(GVAR(lastIterationIndex) >= (count GVAR(objects))) then {
private _iter = 0;
private _objectCount = count GVAR(objects);
while {_objectCount > 0 && {_iter < (GVAR(MaxTrackPerFrame) min _objectCount)}} do {
if (GVAR(lastIterationIndex) >= _objectCount) then {
GVAR(lastIterationIndex) = 0;
};
_object = GVAR(objects) select GVAR(lastIterationIndex);
private _object = GVAR(objects) select GVAR(lastIterationIndex);
if(!isNil "_object") then {
_args = GVAR(arguments) select GVAR(lastIterationIndex);
if (!isNil "_object") then {
private _args = GVAR(arguments) select GVAR(lastIterationIndex);
if(!(_args call FUNC(pfhRound))) then {
_gcIndex pushBack GVAR(lastIterationIndex); // Add it to the GC if it returns false
if (!(_args call FUNC(pfhRound))) then {
_gcIndex pushBack GVAR(lastIterationIndex); // Add it to the GC if it returns false
};
};
_iter = _iter + 1;
GVAR(lastIterationIndex) = GVAR(lastIterationIndex) + 1;
INC(_iter);
INC(GVAR(lastIterationIndex));
};
// clean up dead object references
private ["_deletionCount", "_deleteIndex"];
_deletionCount = 0;
// Clean up dead object references
private _deletionCount = 0;
{
TRACE_1("GC Projectile", _x);
_deleteIndex = _x - _deletionCount;
private _deleteIndex = _x - _deletionCount;
GVAR(objects) deleteAt _deleteIndex;
GVAR(arguments) deleteAt _deleteIndex;
_deletionCount = _deletionCount + 1;
INC(_deletionCount);
} forEach _gcIndex;

View File

@ -1,26 +1,26 @@
#include "script_component.hpp"
params ["_round", "_lastPos", "_lastVel", "_type", "_firedFrame", "", "_doSpall", "_spallTrack", "_foundObjectHPIds", "_skip", "_explosive", "_indirectRange", "_force", "_fragPower"];
params ["_round", "_lastPos", "_lastVel", "_type", "_firedFrame", "_gun", "_doSpall", "_spallTrack", "_foundObjectHPIds", "_skip", "_explosive", "_indirectRange", "_force", "_fragPower"];
if(_round in GVAR(blackList)) exitWith {
if (_round in GVAR(blackList)) exitWith {
false
};
if (!alive _round) exitWith {
if((diag_frameno - _firedFrame) > 1) then { //skip if deleted within a single frame
if(_skip == 0) then {
if((_explosive > 0.5 && {_indirectRange >= 4.5} && {_fragPower >= 35}) || {_force == 1} ) then {
if ((diag_frameno - _firedFrame) > 1) then { //skip if deleted within a single frame
if (_skip == 0) then {
if ((_explosive > 0.5 && {_indirectRange >= 4.5} && {_fragPower >= 35}) || {_force == 1}) then {
// shotbullet, shotShell don't seem to explode when touching water, so don't create frags
if (((_lastPos select 2) < 0) && {(toLower getText (configFile >> "CfgAmmo" >> _type >> "simulation")) in ["shotbullet", "shotshell"]}) exitWith {};
[QGVAR(frag_eh), _this] call CBA_fnc_serverEvent;
};
};
};
if(_doSpall) then {
GVAR(spallIsTrackingCount) = GVAR(spallIsTrackingCount) - 1;
// diag_log text format["F: %1", _foundObjectHPIds];
if (_doSpall) then {
DEC(GVAR(spallIsTrackingCount));
// diag_log text format ["F: %1", _foundObjectHPIds];
{
if(!isNil "_x") then {
if (!isNil "_x") then {
_x removeEventHandler ["hitPart", _foundObjectHPIds select _forEachIndex];
};
} forEach _spallTrack;
@ -28,12 +28,12 @@ if (!alive _round) exitWith {
false
};
_this set[1, (getPosASL _round)];
_this set[2, (velocity _round)];
_this set [1, getPosASL _round];
_this set [2, velocity _round];
if(_doSpall) then {
if (_doSpall) then {
private ["_scale"];
_scale = ( (count GVAR(objects)) / GVAR(MaxTrackPerFrame) ) max 0.1;
_scale = ((count GVAR(objects)) / GVAR(MaxTrackPerFrame)) max 0.1;
[_round, _scale, _spallTrack, _foundObjectHPIds] call FUNC(spallTrack);
};

View File

@ -4,8 +4,8 @@
PARAMS_1(_round);
if(_round in GVAR(blackList)) then {
GVAR(blackList) = GVAR(blackList) - [_round];
if (_round in GVAR(blackList)) then {
REM(GVAR(blackList),_round);
};
GVAR(objects) = GVAR(objects) - [_round];
REM(GVAR(objects),_round);

View File

@ -1,12 +1,11 @@
#include "script_component.hpp"
private ["_ret"];
_ret = true;
if(IS_ARRAY((_this select 0))) then {
private _ret = true;
if (IS_ARRAY(_this select 0)) then {
_ret = false;
} else {
if((_this select 0) in GVAR(trackedObjects)) then {
GVAR(trackedObjects) = GVAR(trackedObjects) - [(_this select 0)];
if ((_this select 0) in GVAR(trackedObjects)) then {
REM(GVAR(trackedObjects),_this select 0);
} else {
_ret = false;
};

View File

@ -1,29 +1,27 @@
#include "script_component.hpp"
private ["_initialData", "_hpData", "_round", "_hpRound", "_hpDirect"];
//player sideChat format["f: %1 c: %2", (_this select 0), (count GVAR(spallHPData))];
//player sideChat format ["f: %1 c: %2", (_this select 0), (count GVAR(spallHPData))];
if ((_this select 0) <= (count GVAR(spallHPData))) then {
_initialData = GVAR(spallHPData) select (_this select 0);
if (!isNil "_initialData") then {
_hpRound = ((_this select 1) select 0) select 2;
_round = _initialData select 3;
_hpDirect = ((_this select 1) select 0) select 10;
if (_hpDirect && {_round == _hpRound}) then {
{
_hpData = _x;
_round = _initialData select 3;
// diag_log text format["HPDUMP-------------------------------------"];
// {
// _hp = _x;
// diag_log text format["%1 --", _forEachIndex];
// {
// diag_log text format["%1: %2", _forEachIndex, _x];
// } forEach _hp;
// } forEach (_this select 1);
[DFUNC(doSpall), [_this, _forEachIndex]] call CBA_fnc_execNextFrame;
// player sideChat "WEEE";
} forEach (_this select 1);
};
};
params ["_index", "_hitPartData"];
private _initialData = GVAR(spallHPData) param [_index, []];
if (_initialData isEqualTo []) exitWith {};
private _hpRound = (_hitPartData select 0) select 2;
private _round = _initialData select 3;
private _hpDirect = (_hitPartData select 0) select 10;
if (_hpDirect && {_round == _hpRound}) then {
{
// diag_log text format ["HPDUMP-------------------------------------"];
// {
// _hp = _x;
// diag_log text format ["%1 --", _forEachIndex];
// {
// diag_log text format ["%1: %2", _forEachIndex, _x];
// } forEach _hp;
// } forEach (_this select 1);
[DFUNC(doSpall), [_this, _forEachIndex]] call CBA_fnc_execNextFrame;
// player sideChat "WEEE";
} forEach _hitPartData;
};

View File

@ -3,7 +3,7 @@
params ["_round", "_multiplier", "_foundObjects", "_foundObjectHPIds"];
private _delta = (1/diag_fps) * _multiplier;
private _delta = (1 / diag_fps) * _multiplier;
private _curPos = getPosASL _round;
private _velocity = velocity _round;
@ -12,17 +12,15 @@ private _forwardPos = _curPos vectorAdd _velocityStep;
private _intersectsWith = lineIntersectsWith [_curPos, _forwardPos];
if (count _intersectsWith > 0) then {
// player sideChat format["inter: %1", _intersectsWith];
{
if(!(_x in _foundObjects)) then {
// diag_log text format["Adding HP: %1", _x];
private _index = count GVAR(spallHPData);
private _hpId = _x addEventHandler ["hitPart", compile format["[%1, _this] call " + QFUNC(spallHP), _index]];
_foundObjects set[(count _foundObjects), _x];
_foundObjectHPIds set[(count _foundObjectHPIds), _hpId];
private _data = [_hpId, _x, typeOf _round, _round, _curPos, _velocity, 0, _foundObjects, _foundObjectHPIds];
GVAR(spallHPData) set[_index, _data];
};
} forEach _intersectsWith;
};
if (_intersectsWith isEqualTo []) exitWith {};
// player sideChat format ["inter: %1", _intersectsWith];
{
// diag_log text format ["Adding HP: %1", _x];
private _index = count GVAR(spallHPData);
private _hpId = _x addEventHandler ["hitPart", compile format ["[%1, _this] call " + QFUNC(spallHP), _index]];
_foundObjects pushBack _x;
_foundObjectHPIds pushBack _hpId;
private _data = [_hpId, _x, typeOf _round, _round, _curPos, _velocity, 0, _foundObjects, _foundObjectHPIds];
GVAR(spallHPData) pushBack _data;
} forEach (_intersectsWith select {!(_x in _foundObjects)});

View File

@ -1,5 +1,5 @@
#include "script_component.hpp"
if(!GVAR(tracesStarted)) then {
GVAR(tracesStarted) = true;
GVAR(traceID) = [FUNC(drawTraces), 0, []] call CBA_fnc_addPerFrameHandler;
};
if (GVAR(tracesStarted)) exitWith {};
GVAR(tracesStarted) = true;
GVAR(traceID) = [FUNC(drawTraces)] call CBA_fnc_addPerFrameHandler;

View File

@ -1,5 +1,5 @@
#include "script_component.hpp"
if(GVAR(tracesStarted)) then {
GVAR(tracesStarted) = false;
[GVAR(traceID)] call CBA_fnc_removePerFrameHandler;
};
if (!GVAR(tracesStarted)) exitWith {};
GVAR(tracesStarted) = false;
[GVAR(traceID)] call CBA_fnc_removePerFrameHandler;

View File

@ -1,12 +1,12 @@
#include "script_component.hpp"
params ["_args"];
params ["_args", "_pfhID"];
_args params ["_tracerObj", "_index"];
if (alive _tracerObj && (count GVAR(traces)) > 0) then {
if (alive _tracerObj && {!(GVAR(traces) isEqualTo [])}) then {
private _data = GVAR(traces) select _index;
private _positions = _data select 4;
_positions pushBack [(getPos _tracerObj), vectorMagnitude (velocity _tracerObj)];
_positions pushBack [getPos _tracerObj, vectorMagnitude (velocity _tracerObj)];
} else {
[(_this select 1)] call CBA_fnc_removePerFrameHandler;
[_pfhID] call CBA_fnc_removePerFrameHandler;
};

View File

@ -1 +1 @@
#include "\z\ace\addons\frag\script_component.hpp"
#include "\z\ace\addons\frag\script_component.hpp"

View File

@ -17,4 +17,4 @@
#include "\z\ace\addons\main\script_macros.hpp"
#define ACE_TRACE_DRAW_INC 1
#define ACE_TRACE_DRAW_INC 1

View File

@ -167,4 +167,4 @@
<Japanese>(SP のみ) ミッションとエディタの再起動が必要です。有効化すると、シングルプレイでのみ破片と剥離の弾頭が見えるようになります。</Japanese>
</Key>
</Package>
</Project>
</Project>

View File

@ -23,6 +23,6 @@ if (_unit == ACE_player) then {
addCamShake [4, 0.5, 5];
};
[_unit, "PutDown"] call EFUNC(common,doGesture);
[_unit, "gesturePoint"] call EFUNC(common,doGesture);
[QGVAR(tapShoulder), [_target, _shoulderNum], [_target]] call CBA_fnc_targetEvent;

View File

@ -1,14 +1,11 @@
class RscOpticsValue;
class RscControlsGroup;
class RscControlsGroupNoScrollbars;
class RscPicture;
class RscMapControl;
class VScrollbar;
class HScrollbar;
class RscLine;
// Taken from AGM for optics management.
class RscInGameUI {
class ACE_RscOptics_javelin {
idd = 300;
@ -16,24 +13,13 @@ class RscInGameUI {
onLoad = QUOTE(_this call FUNC(onOpticLoad));
onUnload = QUOTE(_this call FUNC(onOpticUnload));
class GVAR(elements_group): RscControlsGroup
{
class GVAR(elements_group): RscControlsGroupNoScrollbars {
x = "SafezoneX";
y = "SafezoneY";
w = "SafezoneW";
h = "SafezoneH";
idc = 170;
class VScrollbar {
autoScrollSpeed = -1;
autoScrollDelay = 5;
autoScrollRewind = 0;
color[] = {1,1,1,0};
width = 0.001;
};
class HScrollbar {
color[] = {1,1,1,0};
height = 0.001;
};
class Controls {
class CA_Distance: RscOpticsValue {
idc = 151;
@ -63,23 +49,13 @@ class RscInGameUI {
x = "(SafezoneX+(SafezoneW -SafezoneH*3/4)/2)+ (0.307/4)*3*SafezoneH - SafezoneX";
text = "\A3\ui_f\data\igui\rscingameui\rscoptics_titan\wfov_co.paa";
};
class GVAR(WFOV_mode_group): RscControlsGroup {
class GVAR(WFOV_mode_group): RscControlsGroupNoScrollbars {
x = "SafezoneX";
y = "SafezoneY";
w = "SafezoneW";
h = "SafezoneH";
idc = 163;
class VScrollbar {
autoScrollSpeed = -1;
autoScrollDelay = 5;
autoScrollRewind = 0;
color[] = {1,1,1,0};
width = 0.001;
};
class HScrollbar {
color[] = {1,1,1,0};
height = 0.001;
};
class Controls {
class StadiaL: RscLine {
x = "0.4899*SafezoneW - SafezoneX";
@ -131,23 +107,13 @@ class RscInGameUI {
x = "(SafezoneX+(SafezoneW -SafezoneH*3/4)/2)+ (0.586/4)*3*SafezoneH - SafezoneX";
text = "\A3\ui_f\data\igui\rscingameui\rscoptics_titan\nfov_co.paa";
};
class GVAR(NFOV_mode_group): RscControlsGroup {
class GVAR(NFOV_mode_group): RscControlsGroupNoScrollbars {
x = "SafezoneX";
y = "SafezoneY";
w = "SafezoneW-SafezoneX";
h = "SafezoneH-SafezoneY";
idc = 162;
class VScrollbar {
autoScrollSpeed = -1;
autoScrollDelay = 5;
autoScrollRewind = 0;
color[] = {1,1,1,0};
width = 0.001;
};
class HScrollbar {
color[] = {1,1,1,0};
height = 0.001;
};
class Controls {
class StadiaL: RscLine {
x = "0.4788*SafezoneW - SafezoneX";
@ -251,7 +217,7 @@ class RscInGameUI {
};
};
};
class ACE_Targeting : RscControlsGroup {
class ACE_Targeting: RscControlsGroupNoScrollbars {
idc = 6999;
x = "SafezoneX";
@ -261,24 +227,14 @@ class RscInGameUI {
enabled = 0;
class Controls {
class ACE_TargetingConstrains: RscControlsGroup {
class ACE_TargetingConstrains: RscControlsGroupNoScrollbars {
x = "SafezoneX";
y = "SafezoneY";
w = "SafezoneW-SafezoneX";
h = "SafezoneH-SafezoneY";
enabled = 0;
class VScrollbar {
autoScrollSpeed = -1;
autoScrollDelay = 5;
autoScrollRewind = 0;
color[] = {1,1,1,0};
width = 0.001;
};
class HScrollbar {
color[] = {1,1,1,0};
height = 0.001;
};
class Controls {
class Top: RscPicture {
idc = 699101;

View File

@ -3,10 +3,7 @@
#define MAINPREFIX z
#define PREFIX ace
#define MAJOR 3
#define MINOR 8
#define PATCHLVL 0
#define BUILD 10
#include "script_version.hpp"
#define VERSION MAJOR.MINOR.PATCHLVL.BUILD
#define VERSION_AR MAJOR,MINOR,PATCHLVL,BUILD

View File

@ -0,0 +1,4 @@
#define MAJOR 3
#define MINOR 8
#define PATCHLVL 1
#define BUILD 11

View File

@ -44,18 +44,4 @@ class ACE_Settings {
typeName = "COLOR";
value[] = {1, 0.88, 0, 0.7};
};
class GVAR(groupColorConfigurations) {
displayName = CSTRING(groupColorConfigurations_displayName);
description = CSTRING(groupColorConfigurations_description);
category = CSTRING(mapGestures_category);
typeName = "ARRAY";
value[] = {};
};
class GVAR(groupColorConfigurationMapping) {
displayName = CSTRING(groupColorConfigurationMapping_displayName);
description = CSTRING(groupColorConfigurationMapping_description);
category = CSTRING(mapGestures_category);
typeName = "ARRAY";
value[] = {{}, {}};
};
};

View File

@ -14,6 +14,5 @@ class Extended_PreInit_EventHandlers {
class Extended_PostInit_EventHandlers {
class ADDON {
init = QUOTE(call COMPILE_FILE(XEH_postInit));
serverInit = QUOTE(call COMPILE_FILE(XEH_serverPostInit));
};
};

View File

@ -47,7 +47,7 @@ class CfgVehicles {
category = "ACE";
displayName = CSTRING(moduleGroupSettings_displayName);
function = QFUNC(moduleGroupSettings);
isGlobal = 0;
isGlobal = 2;
author = ECSTRING(common,ACETeam);
icon = QPATHTOF(ui\icon_module_map_gestures_ca.paa);
class Arguments {

View File

@ -1,5 +1,5 @@
PREP(assignClientIDOnServer);
PREP(addGroupColorMapping);
PREP(drawMapGestures);
PREP(endTransmit);
PREP(getProximityPlayers);

View File

@ -8,6 +8,17 @@ if (!hasInterface) exitWith {};
["ace_settingsInitialized", {
if (!GVAR(enabled)) exitWith {};
// This will set QEGVAR(common,playerOwner) var on player objects
[] call EFUNC(common,setPlayerOwner);
GVAR(pointPosition) = [0,0,0];
[QGVAR(syncPos), {
params ["_unit", "_pointPos"];
_unit setVariable [QGVAR(pointPosition), _pointPos];
}] call CBA_fnc_addEventHandler;
[{
if (isNull (findDisplay 12)) exitWith {};

View File

@ -4,4 +4,6 @@ ADDON = false;
#include "XEH_PREP.hpp"
GVAR(GroupColorCfgMappingNew) = call CBA_fnc_createNamespace;
ADDON = true;

View File

@ -1,3 +0,0 @@
#include "script_component.hpp"
[QGVAR(noOwnerID), FUNC(assignClientIDOnServer)] call CBA_fnc_addEventHandler;

View File

@ -0,0 +1,30 @@
/*
* Author: Dslyecxi, MikeMatrix, PabstMirror
* Adds a group id color mapping.
*
* Arguments:
* 0: Group ID or group <STRING><GROUP>
* 1: Leader color array (4 numbers including alpha) <ARRAY>
* 2: Unit (non-leader) color array (4 numbers including alpha) <ARRAY>
*
* Return Value:
* None
*
* Example:
* ["Alpha 1-1", [1,0,0,1], [0,1,0,1]] call ace_map_gestures_fnc_addGroupColorMapping
*
* Public: Yes
*/
#include "script_component.hpp"
if (!params [["_group", "", [grpNull, ""]], ["_leadColor", [1,1,1,1], [[]], 4], ["_unitColor", [1,1,1,1], [[]], 4]]) exitWith {
ERROR_1("Bad Params: %1",_this);
};
TRACE_3("params",_group,_leadColor,_unitColor);
if (_group isEqualType grpNull) then {_group = groupID _group};
if (!([_leadColor] call FUNC(isValidColorArray))) exitWith {ERROR("leadColor is not a valid color array.")};
if (!([_unitColor] call FUNC(isValidColorArray))) exitWith {ERROR("color is not a valid color array.")};
GVAR(GroupColorCfgMappingNew) setVariable [_group, [_leadColor, _unitColor]];

View File

@ -1,24 +0,0 @@
/*
* Author: Dslyecxi, MikeMatrix
* Assign readable client ID to unit on the server.
*
* Arguments:
* 0: Unit name <STRING>
*
* Return Value:
* None
*
* Example:
* ["MikeMatrix"] call ace_map_gestures_fnc_assignClientIDOnServer
*
* Public: No
*/
#include "script_component.hpp"
params ["_unitName"];
{
if (name _x == _unitName) exitWith {
_x setVariable [QGVAR(owner_id), owner _x, true];
};
} count playableUnits;

View File

@ -15,6 +15,8 @@
*/
#include "script_component.hpp"
BEGIN_COUNTER(draw);
#define ICON_RENDER_SIZE 55
#define ICON_TEXT_ALIGN "left"
#define ICON_ANGLE 0
@ -26,36 +28,34 @@
if (!GVAR(enabled) || !visibleMap) exitWith {};
private ["_color", "_drawPosVariableName", "_group", "_grpName", "_pos", "_unitUID"];
params ["_mapHandle"];
// Iterate over all nearby players and render their pointer if player is transmitting.
{
// Data variable name for unit
_unitUID = getPlayerUID _x;
_drawPosVariableName = if (!isNil "_unitUID" && _unitUID != "") then {format [QGVAR(%1_DrawPos), _unitUID]} else {nil};
if (!isNil "_drawPosVariableName") then {
if (isNil {missionNamespace getVariable _drawPosVariableName}) then {missionNamespace setVariable [_drawPosVariableName, [1, 1, 1]];};
_pos = missionNamespace getVariable _drawPosVariableName;
// Only render if the unit is alive and transmitting
if (alive _x && {_x getVariable [QGVAR(Transmit), false]}) then {
// Only render if the unit is alive and transmitting
if (alive _x && {_x getVariable QGVAR(Transmit)}) then {
_group = group _x;
_grpName = groupID _group;
private _pos = _x getVariable [QGVAR(pointPosition), [0,0,0]];
// If color settings for the group exist, then use those, otherwise fall back to the default colors
_color = if ([GVAR(GroupColorConfigurationMapping), _grpName] call CBA_fnc_hashHasKey) then {
(GVAR(GroupColorConfigurations) select ([GVAR(GroupColorConfigurationMapping), _grpName] call CBA_fnc_hashGet)) select (_x != leader _group)
} else {
if (_x == leader _group) then {GVAR(defaultLeadColor)} else {GVAR(defaultColor)};
};
private _group = group _x;
private _grpName = groupID _group;
// Render icon and player name
_mapHandle drawIcon ["\a3\ui_f\data\gui\cfg\Hints\icon_text\group_1_ca.paa", _color, _pos, ICON_RENDER_SIZE, ICON_RENDER_SIZE, ICON_ANGLE, "", ICON_SHADOW, TEXT_SIZE, TEXT_FONT, ICON_TEXT_ALIGN];
_mapHandle drawIcon ["#(argb,8,8,3)color(0,0,0,0)", GVAR(nameTextColor), _pos, TEXT_ICON_RENDER_SIZE, TEXT_ICON_RENDER_SIZE, ICON_ANGLE, name _x, TEXT_SHADOW, TEXT_SIZE, TEXT_FONT, ICON_TEXT_ALIGN];
// If color settings for the group exist, then use those, otherwise fall back to the default colors
private _colorMap = GVAR(GroupColorCfgMappingNew) getVariable _grpName;
private _color = if (isNil "_colorMap") then {
[GVAR(defaultLeadColor), GVAR(defaultColor)] select (_x != leader _group);
} else {
_colorMap select (_x != leader _group);
};
TRACE_2("",_colorMap,_color);
// Render icon and player name
_mapHandle drawIcon ["\a3\ui_f\data\gui\cfg\Hints\icon_text\group_1_ca.paa", _color, _pos, ICON_RENDER_SIZE, ICON_RENDER_SIZE, ICON_ANGLE, "", ICON_SHADOW, TEXT_SIZE, TEXT_FONT, ICON_TEXT_ALIGN];
_mapHandle drawIcon ["#(argb,8,8,3)color(0,0,0,0)", GVAR(nameTextColor), _pos, TEXT_ICON_RENDER_SIZE, TEXT_ICON_RENDER_SIZE, ICON_ANGLE, name _x, TEXT_SHADOW, TEXT_SIZE, TEXT_FONT, ICON_TEXT_ALIGN];
};
nil
} count ([ACE_player, GVAR(maxRange)] call FUNC(getProximityPlayers));
END_COUNTER(draw);

View File

@ -10,7 +10,7 @@
* All units in proximity <ARRAY>
*
* Example:
* ["example value"] call ace_module_fnc_functionName
* [player, 7] call ace_map_gestures_fnc_getProximityPlayers
*
* Public: No
*/
@ -21,4 +21,5 @@ params ["_unit", "_range"];
private _proximityPlayers = (getPos _unit) nearEntities [["CAMAnBase"], _range];
_proximityPlayers deleteAt (_proximityPlayers find _unit);
_proximityPlayers append (crew vehicle _unit);
_proximityPlayers
_proximityPlayers select {[_x, false] call EFUNC(common,isPlayer);}

View File

@ -17,29 +17,18 @@
*/
#include "script_component.hpp"
private ["_color", "_configurationGroupMappings", "_configurationIndex", "_configurations", "_leadColor"];
params ["_logic", "_units", "_activated"];
TRACE_3("params",_logic,_units,_activated);
if (!_activated || !isServer) exitWith {};
if (!_activated) exitWith {};
// Transcode string setting into usable array. Example: "1,1,1,1" -> [1, 1, 1, 1]
_leadColor = call compile ("[" + (_logic getVariable ["leadColor", ""]) + "]");
private _leadColor = call compile ("[" + (_logic getVariable ["leadColor", ""]) + "]");
if (!([_leadColor] call FUNC(isValidColorArray))) exitWith {ERROR("leadColor is not a valid color array.")};
_color = call compile ("[" + (_logic getVariable ["color", ""]) + "]");
private _color = call compile ("[" + (_logic getVariable ["color", ""]) + "]");
if (!([_color] call FUNC(isValidColorArray))) exitWith {ERROR("color is not a valid color array.")};
// If we already have color configurations from another source, use those, otherwise use default.
_configurations = if (isNil QGVAR(GroupColorConfigurations)) then { [] } else { +GVAR(GroupColorConfigurations) };
_configurationGroupMappings = if(isNil QGVAR(GroupColorConfigurationMapping)) then { [] call CBA_fnc_hashCreate } else { +GVAR(GroupColorConfigurationMapping) };
// Save custom color configuration and keep the index of the entry.
_configurationIndex = _configurations pushBack [_leadColor, _color];
// Add all synchronized groups and reference custom configuration for them
{
[_configurationGroupMappings, groupID group _x, _configurationIndex] call CBA_fnc_hashSet;
[group _x, _leadColor, _color] call FUNC(addGroupColorMapping);
} forEach _units;
[QGVAR(GroupColorConfigurations), _configurations, false, true] call EFUNC(common,setSetting);
[QGVAR(GroupColorConfigurationMapping), _configurationGroupMappings, false, true] call EFUNC(common,setSetting);

View File

@ -16,7 +16,7 @@
*/
#include "script_component.hpp"
private ["_ownerID", "_unitUID", "_drawPosVariableName", "_playerOwnerID"];
BEGIN_COUNTER(transmit);
params ["", "_pfhId"];
@ -29,17 +29,14 @@ if (!GVAR(EnableTransmit) || !visibleMap) exitWith {
};
{
_ownerID = _x getVariable QGVAR(owner_id);
if (isNil "_ownerID") then {
[QGVAR(noOwnerID), [name _x]] call CBA_fnc_serverEvent;
} else {
_playerOwnerID = ACE_player getVariable QGVAR(owner_id);
if (!isNil "_playerOwnerID" && _ownerID != _playerOwnerID) then {
_unitUID = getPlayerUID ACE_Player;
_drawPosVariableName = if (!isNil "_unitUID" && _unitUID != "") then {format [QGVAR(%1_DrawPos), _unitUID]} else {nil};
if (!isNil "_drawPosVariableName") then {
_ownerID publicVariableClient _drawPosVariableName;
};
private _owner = _x getVariable [QEGVAR(common,playerOwner), -1];
if (_owner > -1) then {
private _remotePos = _x getVariable [QGVAR(remotePos), [0,0,0]];
if ((_remotePos distance2d GVAR(pointPosition)) > 1) then { // Only transmit when actually moving
[QGVAR(syncPos), [ACE_Player, GVAR(pointPosition)], _owner] call CBA_fnc_ownerEvent;
_x setVariable [QGVAR(remotePos), GVAR(pointPosition)];
};
};
} count ([ACE_player, GVAR(maxRange)] call FUNC(getProximityPlayers));
END_COUNTER(transmit);

View File

@ -15,11 +15,9 @@
*/
#include "script_component.hpp"
private ["_mapCtrl", "_unitUID", "_drawPosVariableName"];
disableSerialization;
_mapCtrl = findDisplay 12 displayCtrl 51;
private _mapCtrl = findDisplay 12 displayCtrl 51;
// MouseMoving EH.
if (!isNil QGVAR(MouseMoveHandlerID)) then {
@ -36,11 +34,7 @@ GVAR(MouseMoveHandlerID) = _mapCtrl ctrlAddEventHandler ["MouseMoving", {
ACE_player setVariable [QGVAR(Transmit), true, true];
};
_unitUID = getPlayerUID ACE_player;
_drawPosVariableName = if (!isNil "_unitUID" && _unitUID != "") then {format [QGVAR(%1_DrawPos), _unitUID]} else {nil};
if (!isNil "_drawPosVariableName") then {
missionNamespace setVariable [_drawPosVariableName, _control ctrlMapScreenToWorld [_posX, _posY]];
};
GVAR(pointPosition) = _control ctrlMapScreenToWorld [_posX, _posY];
}];
// MouseDown EH

View File

@ -177,51 +177,6 @@
<French>Temps entre les actualisations de données</French>
<Japanese>データの更新間隔</Japanese>
</Key>
<Key ID="STR_ACE_map_gestures_GroupColorConfigurations_displayName">
<English>Group color configurations</English>
<Portuguese>Configurações de cores de grupo</Portuguese>
<Polish>Konf. koloru grup</Polish>
<Russian>Конфигурация цвета групп</Russian>
<Czech>Konfigurace barvy pro skupinu</Czech>
<Italian>Configurazioni colori dei gruppi</Italian>
<German>Konfiguration der Gruppenfarbe</German>
<Spanish>Configuración de color de grupo</Spanish>
<French>Configuration des couleurs de groupe</French>
<Japanese>グループで使う色の設定</Japanese>
</Key>
<Key ID="STR_ACE_map_gestures_GroupColorConfigurations_description">
<English>Group color configuration containing arrays of color pairs ([leadColor, color]).</English>
<Portuguese>Configuração de cores de grupo contendo arrays com pares de cores ([leadColor, color]).</Portuguese>
<Polish>Konfiguracja kolorów grup zawierająca tablice par kolorów ([kolorLidera, kolor]).</Polish>
<Russian>Конфигурация цвета групп содержит массив цветовых пар ([лид. цвет, цвет]).</Russian>
<Italian>Configurazioni colori gruppi contenenti array di coppie di colori ([leadColor, color]).</Italian>
<German>Konfiguration der Gruppenfarbe mit zugeordneten Farbpaaren der Aufstellung ([leadColor, color]).</German>
<Spanish>Configuración de color de grupo conteniendo una lista de pares de colores ([colorLider, colo]).</Spanish>
<French>Configuration des couleurs de groupe contenant des tableaux de paires de couleurs ([couleurDeCommandement, couleur]).</French>
<Japanese>アライに格納された組によりグループの色を設定します。([leadColor, color])</Japanese>
</Key>
<Key ID="STR_ACE_map_gestures_GroupColorConfigurationMapping_description">
<English>Hash of Group ID mapped to the Group color configuration index.</English>
<Portuguese>Hashes de ID de grupos mapeados para o índice de configuração de cor de grupos.</Portuguese>
<Polish>Hasz ID grup zmapowanych w indeksie konfiguracji koloru grup.</Polish>
<Russian>Хеш ID групп, соответствующих индексам конфигурации цвета групп.</Russian>
<Italian>Hash degli ID Gruppi mappati nell'indice configurazioni colori gruppi.</Italian>
<German>Hashwert der Gruppen-ID, die dem Konfigurations-Index der Gruppenfarbe zugeordnet werden.</German>
<Spanish>ID de Grupo mapeado al índice de la configuración de color de grupo.</Spanish>
<French>Hash de l'identifiant du groupe mappé à l'index de la configuration de la couleur du groupe.</French>
<Japanese>グループ ID のハッシュはグループの色を設定するインデックスへマッピングされます。</Japanese>
</Key>
<Key ID="STR_ACE_map_gestures_GroupColorConfigurationMapping_displayName">
<English>GroupID Color configuration mapping</English>
<Portuguese>Mapeamento de configuração para cores de GroupID</Portuguese>
<Polish>Mapowanie kolorów poprzez GroupID</Polish>
<Russian>Соответствие ID групп конфигурации цвета групп</Russian>
<Italian>Mappatura configurazioni colori GroupID</Italian>
<German>Gruppen-ID-Farbe Konfigurationszuordnung</German>
<Spanish>Mapeado de ID de Grupo</Spanish>
<French>Configuration du mappage de l'identifiant de la couleur du groupe.</French>
<Japanese>GroupID の色への設定をマッピング</Japanese>
</Key>
<Key ID="STR_ACE_map_gestures_enabled_description">
<English>Enables the Map Gestures.</English>
<Portuguese>Ativa os gestos no mapa</Portuguese>
@ -270,4 +225,4 @@
<Japanese>マップ ジェスチャ</Japanese>
</Key>
</Package>
</Project>
</Project>

View File

@ -10,9 +10,7 @@ if (isServer) then {
[QGVAR(bloodDropCreated), {
params ["_bloodDrop"];
GVAR(bloodDrops) pushBack _bloodDrop;
if (count GVAR(bloodDrops) >= MAX_BLOOD_OBJECTS) then {
private _deletedBloodDrop = GVAR(bloodDrops) deleteAt 0;
deleteVehicle _deletedBloodDrop;
@ -25,7 +23,7 @@ if (isServer) then {
["ace_settingsInitialized", {
TRACE_1("settingsInitialized", GVAR(enabledFor));
if (GVAR(enabledFor) == 0) exitWith {}; // 0: disabled
if (GVAR(enabledFor) == 1 && {!hasInterface}) exitWith {}; // 1: enabledFor_OnlyPlayers
if ((GVAR(enabledFor) == 1) && {!hasInterface}) exitWith {}; // 1: enabledFor_OnlyPlayers
private _listcode = if (GVAR(enabledFor) == 1) then {
{[ACE_player] select {[_x] call FUNC(isBleeding)}} // ace_player is only possible local player

View File

@ -22,6 +22,7 @@
#define OFFSET 0.25
params ["_unit", "_dir", "_damage"];
_damage = _damage min 1;
private _distanceBetweenDrops = DISTANCE_BETWEEN_DROPS * _damage;
private _offset = OFFSET + _distanceBetweenDrops;

View File

@ -23,8 +23,8 @@ if (isNull _target ||
{_target getVariable [QGVAR(jerryCan), false]}) exitWith {};
[_target, _fuelAmount] call FUNC(setFuel);
_target setVariable [QGVAR(jerryCan), true, true];
_target setVariable [QGVAR(source), _target, true];
_target setVariable [QGVAR(jerryCan), true];
_target setVariable [QGVAR(source), _target];
// Main Action
private _action = [QGVAR(Refuel),

View File

@ -84,7 +84,7 @@ for "_i" from 0 to (count _hitPoint) do {
// Don't display part name if no string is found in stringtable
if (_text == LSTRING(Hit)) then {
if (_hitPoint != "") then { WARNING_1("Hitpoint [%1] - could not be localized", _hitPoint); };
if (_hitPoint != "") then { LOG_1("Hitpoint [%1] - could not be localized", _hitPoint); };
_text = _textDefault;
};

View File

@ -51,6 +51,7 @@ if (!([[_unit, _veh]] call _condition)) exitWith {false};
_returnValue = _funcType in ["canLockpick", "startLockpick", "finishLockpick"];
switch (_funcType) do {
case "canLockpick": {};
case "startLockpick": {
[_vehLockpickStrenth, [_unit, _veh, "finishLockpick"], {(_this select 0) call FUNC(lockpick)}, {}, (localize LSTRING(Action_LockpickInUse)), _condition] call EFUNC(common,progressBar);
};

View File

@ -4,7 +4,7 @@
<p align="center">
<a href="https://github.com/acemod/ACE3/releases">
<img src="https://img.shields.io/badge/Version-3.8.0-blue.svg?style=flat-square" alt="ACE3 Version">
<img src="https://img.shields.io/badge/Version-3.8.1-blue.svg?style=flat-square" alt="ACE3 Version">
</a>
<a href="https://github.com/acemod/ACE3/issues">
<img src="https://img.shields.io/github/issues-raw/acemod/ACE3.svg?style=flat-square&label=Issues" alt="ACE3 Fehlermeldungen">

View File

@ -3,7 +3,7 @@
</p>
<p align="center">
<a href="https://github.com/acemod/ACE3/releases">
<img src="https://img.shields.io/badge/Wersja-3.8.0-blue.svg?style=flat-square" alt="ACE3 Wersja">
<img src="https://img.shields.io/badge/Wersja-3.8.1-blue.svg?style=flat-square" alt="ACE3 Wersja">
</a>
<a href="https://github.com/acemod/ACE3/issues">
<img src="https://img.shields.io/github/issues-raw/acemod/ACE3.svg?label=Zagadnienia&style=flat-square" alt="ACE3 Zagadnienia">

View File

@ -11,8 +11,8 @@ ace:
version:
major: 3
minor: 8
patch: 0
build: 10
patch: 1
build: 11
acex:
githubUrl: https://github.com/acemod/ACEX

View File

@ -11,8 +11,8 @@ ace:
version:
major: 3
minor: 8
patch: 0
build: 10
patch: 1
build: 11
acex:
githubUrl: https://github.com/acemod/ACEX

View File

@ -470,6 +470,10 @@
`ace_common`
{% endif %}
{% if include.component == "nouniformrestrictions" %}
`ace_common`
{% endif %}
{% if include.component == "particles" %}
`ace_common`
{% endif %}

View File

@ -73,6 +73,19 @@ Class Name | In-Game Name | Type |
---------- | --------- | ---------
ACE_CableTie | cable tie | ACE_ItemCore |
### Chemlights
`Added in 3.7.0`
Class Name | In-Game Name | Type |
---------- | --------- | ---------
ACE_Chemlight_HiOrange | Chemlight (Hi Orange) | Throwable |
ACE_Chemlight_HiRed | Chemlight (Hi Red) | Throwable |
ACE_Chemlight_HiYellow | Chemlight (Hi Yellow) | Throwable |
ACE_Chemlight_HiWhite | Chemlight (Hi White) | Throwable |
ACE_Chemlight_Orange | Chemlight (Orange) | Throwable |
ACE_Chemlight_White | Chemlight (White) | Throwable |
ACE_Chemlight_IR | Chemlight (IR) | Throwable |
### Common
`Added in 3.0.0`
@ -131,6 +144,7 @@ ACE_HandFlare_White | M127A1 Hand Held Signal (White) | Grenade |
ACE_HandFlare_Red | M127A1 Hand Held Signal (Red | Grenade |
ACE_HandFlare_Green | M127A1 Hand Held Signal (Green) | Grenade |
ACE_HandFlare_Yellow | M127A1 Hand Held Signal (Yellow) | Grenade |
ACE_M14 | AN-M14 Incendiary Grenade | Grenade |
ACE_M84 | M84 Stun Grenade | Grenade |
### Gun Bag
@ -339,6 +353,7 @@ Class Name | In-Game Name | Type |
ACE_SpottingScope | Spotting Scope | ACE_ItemCore |
ACE_SpottingScopeObject | Spotting Scope (placed) | StaticATWeapon |
### Tactical Ladder
`Added in 3.1.1`
@ -352,10 +367,10 @@ ACE_Tactical_Ladder | Telescopic Ladder (placed) | house |
Class Name | In-Game Name | Type |
---------- | --------- | ---------
ACE_SpraypaintBlack | Spraypaint Black | ACE_ItemCore |
ACE_SpraypaintBlue | Spraypaint Blue | ACE_ItemCore |
ACE_SpraypaintGreen | Spraypaint Green | ACE_ItemCore |
ACE_SpraypaintRed | Spraypaint Red | ACE_ItemCore |
ACE_SpraypaintBlack | Black spray paint | ACE_ItemCore |
ACE_SpraypaintBlue | Blue spray paint | ACE_ItemCore |
ACE_SpraypaintGreen | Green spray paint | ACE_ItemCore |
ACE_SpraypaintRed | Red spray paint | ACE_ItemCore |
### Trenches
`Added in 3.5.0`

View File

@ -16,9 +16,10 @@ This page describes how you can setup your development environment for ACE3, all
- A proper installation of the Arma 3 Tools (available on Steam)
- A properly setup P-drive
- Run Arma 3 and Arma 3 Tools directly from steam once to install registry entries (and again after every update)
- Python 3.x, available [here](http://www.python.org)
- The following Mikero's Tools (available [here](https://dev.withsix.com/projects/mikero-pbodll/files)): DePbo, DeRap, DeOgg, Rapify, MakePbo, pboProject
- A properly setup PATH variable (containing Python, the Mikero's Tools and git)
- [Python 3.x](https://www.python.org/)
- [Mikero Tools](https://dev.withsix.com/projects/mikero-pbodll/files): DePbo, DeRap, DeOgg, Rapify, MakePbo, PboProject
- Python, Mikero Tools and Git in PATH environment variable
- [CBA](https://github.com/CBATeam/CBA_A3/releases/latest) mod (release or development version)
## 2. Why so complicated?
@ -28,24 +29,29 @@ If you have contributed to AGM you might be used to an easier build process, whe
Not offering .exes for the Python scripts we use allows us to make easy changes without the hassle of compiling self-extracting exes all the time.
## 3. Getting ACE
## 3. Getting Source Code
To actually get the ACE source code on your machine, it is recommended that you use Git. Tutorials for this are all around the web, and it allows you to track your changes and easily update your local copy.
To actually get the ACE3 source code on your machine, it is recommended that you use Git. Tutorials for this are all around the web, and it allows you to track your changes and easily update your local copy.
If you just want to create a quick and dirty build, you can also directly download the source code using the "Download ZIP" button on the front page of the GitHub repo.
## 4. Initial Setup
## 4. Setup and Building
After ensuring that you have installed all requirements, execute the `setup.py` script found in the `tools` folder. This will do most of the heavy lifting for you, create the links you need and copy the required CBA code to the proper place. Please note that these links are tied to the location of your ACE3 source code, so make sure that the project folder is where you want it to be. We recommend that you store the ACE3 project on your P-drive.
### 4.1 Initial Setup
### 4.1 Manual Setup
Navigate to `tools` folder in command line.
Should the script fail, here is how you create the required links manually:
```
cd "[location of the ACE3 project]\tools"
```
First, to set up the links, create `z` folders both in your Arma 3 directory and on your P-drive. Then run the following commands as admin, replacing the text in brackets with the appropriate paths:
Execute `setup.py` to create symbolic links to P-drive and Arma 3 directory required for building.
```sh
Should the script fail, you can create the required links manually. First, create `z` folders both in your Arma 3 directory and on your P-drive. Then run the following commands as admin, replacing the text in brackets with the appropriate paths:
```bat
mklink /J "[Arma 3 installation folder]\z\ace" "[location of the ACE3 project]"
mklink /J "P:\z\ace" "[location of the ACE3 project]"
```
@ -53,33 +59,50 @@ mklink /J "P:\z\ace" "[location of the ACE3 project]"
Then, copy the `cba` folder from the `tools` folder to `P:\x\cba`. Create the `x` folder if needed. That folder contains the parts of the CBA source code that are required for the macros to work.
## 5. Creating a Test Build
## 4.2 Creating a Test Build
To create a development build of ACE to test changes or to debug something, run the `build.py` file in the `tools` folder. This will populate the `addons` folder with binarized PBOs. These PBOs still point to the source files in their respective folders however, which allows you to use [file patching](#file-patching).
This also means that you cannot distribute this build to others.
To create a development build of ACE3 to test changes or to debug something, run the `build.py` file in the `tools` folder. This will populate the `addons` folder with binarized PBOs. These PBOs still point to the source files in their respective folders however, which allows you to use [file patching](#file-patching). This also means that you cannot distribute this build to others.
To start the game using this build, you can use the following modline:
```sh
-mod=@cba_a3;z\ace
-mod=@CBA_A3;z\ace
```
## 4.3 Creating a Release Build
## 6. Creating a Release Build
To create a complete build of ACE3 that you can use without the source files you will need to:
- Ensure `.hpp` is **NOT** in pboProject's "Exclude From Pbo" list
To create a complete build of ACE that you can use without the source files, run the `make.py` file in the `tools` folder. This will populate the `release` folder with binarized PBOs that you can redistribute. These handle like those of any other mod.
When the requirements are met:
- Execute `make.py version increment_build <other-increment-args> force check_external release` in the `tools` folder, replacing `<other-increment-args>` with the part of version you want to increment (options described below)
This will populate the `release` folder with binarized PBOs, compiled extensions, copied extras, bisigns and a bikey. Additionally, an archive file will also be created in the folder. The folder and archive handle like those of any other mod.
Different `make.py` command line options include:
- `version` - update version number in all files and leave them in working directory (leaving this out will still update the version in all files present in the `release` folder, but they will be reverted to not disturb the working directory)
- `increment_build` - increments _build_ version number
- `increment_patch` - increments _patch_ version number (ignored with `increment_minor` or `increment_major`)
- `increment_minor` - increments _minor_ version number and resets _patch_ version number to `0` (ignored with `increment_major`)
- `increment_major` - increments _major_ version number and resets _minor_ and _patch_ version numbers to `0`
- `force` - force rebuild all PBOs, even those already present in the `release` directory (combined with `compile` it will also rebuild all extensions)
- `check_external` - check external references (incompatible only with `<component1> <component2>` and `force <component1> <component2>`)
- `release` - create release packages/archives
- `<component1> <component2>` - build only specified component(s) (incompatible with `release`)
- `force <component1> <component2>` - force rebuild specified component(s) (incompatible with `release`)
## 7. File Patching
File Patching allows you to change the files in an addon while the game is running, requiring only a restart of the mission. This makes it great for debugging, as it cuts down the time required between tests. Note that this only works with PBOs created using MakePBO, as outlined in [Creating a Test Build](#creating-a-test-build).
File Patching allows you to change the files in an addon while the game is running, requiring only a restart of the mission. This makes it great for debugging, as it cuts down the time required between tests. Note that this only works with PBOs created using MakePBO, which `build.py` uses.
To run Arma 3 with file patching add the `-filePatching` startup parameter (since Arma 3 v1.50, file patching is disabled by default).
### 7.1 Disabling CBA Function Caching
By default CBA caches a compiled version of functions to reduce mission load times. This interferes with file patching. There are three ways to disable function caching:
- Load `cba_cache_disable.pbo` (included in CBA's optional folder)
- Load `cba_cache_disable.pbo` (included in CBA's optional folder - simply move it to `addons` folder for the time being)
- Add the following to your test missions description.ext:
```cpp
@ -94,20 +117,16 @@ class CfgSettings {
};
```
- To only disable caching for a single module, hence greatly improving mission restart time, add the following line to the `script_component.hpp` file of said module:
- To only disable caching for a single module, hence greatly improving mission restart time, add the following line to the `script_component.hpp` file of said module (prepared in each ACE3 component, simply uncomment):
```cpp
#define DISABLE_COMPILE_CACHE
```
### 7.2 Running Arma 3 with File Patching Enabled
Starting from version 1.50, Arma 3 was changed to disable file patching by default, making the feature opt-in. To execute the game with file patching enabled add the `-filePatching` flag to the command line.
### 7.3 Restrictions of File Patching
### 7.2 Restrictions
Files must exist in the built PBOs for file patching to work. If you create a new file you must rebuild the PBO or Arma will not find it in your file paths.
Configs are not patched during run time, only at load time. You do not have have to rebuild a PBO to make config changes, just restart Arma. You can get around this though if you are on the dev branch of Arma 3 and running the [diagnostic exe](https://community.bistudio.com/wiki/Arma_3_Diagnostics_Exe). That includes `diag_mergeConfigFile` which takes a full system path (as in `diag_mergeConfigFile ["p:\z\ace\addons\my_module\config.cpp"]`) and allows you selectively reload config files.
If you need to add/remove files, then you'll need to run build.py again without the game running, and restart. That is all that is required to add new files to then further use in testing.
If you need to add/remove files, then you'll need to run `build.py` again without the game running, and restart. That is all that is required to add new files for further use in testing.

View File

@ -0,0 +1,27 @@
---
layout: wiki
title: Chemlights
description: Adds enhanced types of chemlights.
group: feature
category: equipment
parent: wiki
mod: ace
version:
major: 3
minor: 7
patch: 0
---
<div class="panel callout">
<h5>Note:</h5>
<p>Check out the <a href="{{ site.baseurl }}/wiki/feature/advanced-throwing.html">Advanced Throwing</a> page for the new alternative system introduced in version 3.7.0.</p>
</div>
## 1. Overview
### 1.1 Chemlights
Adds throwable chemlights in the colors white, red, green and yellow. Additionally "Hi" chemlights are added that emit a brighter glow.
## 2. Dependencies
{% include dependencies_list.md component="chemlights" %}

View File

@ -1,7 +1,7 @@
---
layout: wiki
title: Grenades
description: Different throwing modes for grenades, a flashbang and hand flares.
description: Different throwing modes for grenades, a flashbang, incendiary grenade and hand flares.
group: feature
category: equipment
parent: wiki
@ -28,6 +28,9 @@ Adds throwable hand flares in the colors white, red, green and yellow. Additiona
### 1.3 M84 stun grenade
Adds the M84 stun grenade. The stun effect will also affect AI.
### 1.4 M14 Incendiary grenade
Adds the AN-M14 incendiary grenade. This grenade has a thermate filler and is primarily used for the destruction of material.
## 2. Usage
### 2.1 Switching between throw modes

View File

@ -1,8 +1,8 @@
name = "Advanced Combat Environment 3.8.0";
name = "Advanced Combat Environment 3.8.1";
picture = "logo_ace3_ca.paa";
actionName = "GitHub";
action = "https://github.com/acemod/ACE3";
description = "ACE3 - Version 3.8.0";
description = "ACE3 - Version 3.8.1";
logo = "logo_ace3_ca.paa";
logoOver = "logo_ace3_ca.paa";
tooltip = "ACE3";

View File

@ -0,0 +1 @@
z\ace\addons\nouniformrestrictions

View File

@ -0,0 +1,11 @@
class Extended_PreStart_EventHandlers {
class ADDON {
init = QUOTE(call COMPILE_FILE(XEH_preStart));
};
};
class Extended_PreInit_EventHandlers {
class ADDON {
init = QUOTE(call COMPILE_FILE(XEH_preInit));
};
};

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,12 @@
ace_nouniformrestrictions
=======
Removes side restrictions from all vanilla uniforms.
## Maintainers
The people responsible for merging changes to this component or answering potential questions.
- [654wak654](https://github.com/654wak654)
- [Jonpas](https://github.com/jonpas)

View File

@ -0,0 +1 @@
PREP(exportConfig);

View File

@ -0,0 +1,7 @@
#include "script_component.hpp"
ADDON = false;
#include "XEH_PREP.hpp"
ADDON = true;

View File

@ -0,0 +1,3 @@
#include "script_component.hpp"
#include "XEH_PREP.hpp"

View File

@ -0,0 +1,18 @@
#include "script_component.hpp"
class CfgPatches {
class ADDON {
name = COMPONENT_NAME;
units[] = {};
weapons[] = {};
requiredVersion = REQUIRED_VERSION;
requiredAddons[] = {"ace_common"};
author = ECSTRING(common,ACETeam);
authors[] = {"654wak654", "jonpas"};
url = ECSTRING(main,URL);
VERSION_CONFIG;
};
};
#include "CfgEventHandlers.hpp"
#include "CfgVehicles.hpp"

View File

@ -0,0 +1,52 @@
/*
* Author: BaerMitUmlaut, 654wak654
* Generates the CfgVehicles.hpp to unlock all uniforms.
*
* Arguments:
* None
*
* Return Value:
* CfgVehicles.hpp content <STRING>
*
* Example:
* [] call ace_nouniformrestrictions_fnc_exportConfig
*
* Public: [Yes]
*/
#include "script_component.hpp"
private _modifyClasses = [];
private _baseClasses = [];
{
private _modifyClass = {
if (!isNull (_x >> "modelSides")) exitWith {_x};
} forEach (configHierarchy _x);
private _baseClass = inheritsFrom _modifyClass;
_modifyClasses pushBackUnique [_modifyClass, _baseClass];
if !(_baseClass in (_modifyClasses apply {_x select 0})) then {
_baseClasses pushBackUnique _baseClass;
};
false
} count (
("!isNull (_x >> 'modelSides') &&" +
"{!(getArray (_x >> 'modelSides') isEqualTo [6])} &&" +
"{!(getArray (_x >> 'modelSides') isEqualTo [0,1,2,3])}")
configClasses (configFile >> "CfgVehicles")
);
private _nl = toString [13, 10];
private _output = "class CfgVehicles {" + _nl;
{
ADD(_output,format [ARR_3(" class %1;%2",configName _x,_nl)]);
false
} count _baseClasses;
ADD(_output,_nl);
{
_x params ["_class", "_parent"];
ADD(_output,format [ARR_4(" class %1: %2 {%3 modelSides[] = {6};%3 };%3",configName _class,configName _parent,_nl)]);
false
} count _modifyClasses;
ADD(_output,"};");
copyToClipboard _output;
_output;

View File

@ -0,0 +1 @@
#include "\z\ace\addons\nouniformrestrictions\script_component.hpp"

View File

@ -0,0 +1,18 @@
#define COMPONENT nouniformrestrictions
#define COMPONENT_BEAUTIFIED No Uniform Restrictions
#include "\z\ace\addons\main\script_mod.hpp"
// #define DEBUG_MODE_FULL
// #define DISABLE_COMPILE_CACHE
// #define CBA_DEBUG_SYNCHRONOUS
// #define ENABLE_PERFORMANCE_COUNTERS
#ifdef DEBUG_ENABLED_UNIFORMS
#define DEBUG_MODE_FULL
#endif
#ifdef DEBUG_SETTINGS_UNIFORMS
#define DEBUG_SETTINGS DEBUG_SETTINGS_UNIFORMS
#endif
#include "\z\ace\addons\main\script_macros.hpp"

View File

@ -30,7 +30,7 @@
###############################################################################
__version__ = "0.7"
__version__ = "0.8"
import sys
@ -51,8 +51,7 @@ import traceback
import time
import timeit
import re
from tempfile import mkstemp
import fileinput
if sys.platform == "win32":
import winreg
@ -329,7 +328,6 @@ def print_yellow(msg):
def copy_important_files(source_dir,destination_dir):
originalDir = os.getcwd()
# Copy importantFiles
@ -340,17 +338,17 @@ def copy_important_files(source_dir,destination_dir):
for file in importantFiles:
filePath = os.path.join(module_root_parent, file)
# Take only file name for destination path (to put it into root of release dir)
if "\\" in file:
count = file.count("\\")
file = file.split("\\", count)[-1]
print_green("Copying file => {}".format(os.path.join(source_dir,file)))
shutil.copyfile(os.path.join(source_dir,filePath),os.path.join(destination_dir,file))
if os.path.exists(filePath):
print_green("Copying file => {}".format(filePath))
shutil.copy(os.path.join(source_dir,filePath), destination_dir)
else:
missingFiles.append("{}".format(filePath))
print_error("Failed copying file => {}".format(filePath))
except:
print_error("COPYING IMPORTANT FILES.")
raise
#copy all extension dlls
# Copy all extension DLL's
try:
os.chdir(os.path.join(source_dir))
print_blue("\nSearching for DLLs in {}".format(os.getcwd()))
@ -370,13 +368,13 @@ def copy_important_files(source_dir,destination_dir):
os.chdir(originalDir)
def copy_optionals_for_building(mod,pbos):
src_directories = os.listdir(optionals_root)
current_dir = os.getcwd()
print_blue("\nChecking Optionals folder...")
print_blue("\nChecking optionals folder...")
try:
#special server.pbo processing
files = glob.glob(os.path.join(release_dir, project, "optionals", "*.pbo"))
for file in files:
@ -400,7 +398,6 @@ def copy_optionals_for_building(mod,pbos):
finally:
os.chdir(current_dir)
print("")
try:
for dir_name in src_directories:
mod.append(dir_name)
@ -467,9 +464,10 @@ def cleanup_optionals(mod):
def purge(dir, pattern, friendlyPattern="files"):
print_green("Deleting {} files from directory: {}".format(friendlyPattern,dir))
for f in os.listdir(dir):
if re.search(pattern, f):
os.remove(os.path.join(dir, f))
if os.path.exists(dir):
for f in os.listdir(dir):
if re.search(pattern, f):
os.remove(os.path.join(dir, f))
def build_signature_file(file_name):
@ -525,13 +523,13 @@ def addon_restore(modulePath):
return True
def get_project_version():
def get_project_version(version_increments=[]):
global project_version
versionStamp = project_version
#do the magic based on https://github.com/acemod/ACE3/issues/806#issuecomment-95639048
try:
scriptModPath = os.path.join(work_drive, prefix, "main\script_mod.hpp")
scriptModPath = os.path.join(module_root, "main\script_version.hpp")
if os.path.isfile(scriptModPath):
f = open(scriptModPath, "r")
@ -541,11 +539,36 @@ def get_project_version():
if hpptext:
majorText = re.search(r"#define MAJOR (.*\b)", hpptext).group(1)
minorText = re.search(r"#define MINOR (.*\b)", hpptext).group(1)
patchlvlText = re.search(r"#define PATCHLVL (.*\b)", hpptext).group(1)
patchText = re.search(r"#define PATCHLVL (.*\b)", hpptext).group(1)
buildText = re.search(r"#define BUILD (.*\b)", hpptext).group(1)
# Increment version (reset all below except build)
if version_increments != []:
if "major" in version_increments:
majorText = int(majorText) + 1
minorText = 0
patchText = 0
elif "minor" in version_increments:
minorText = int(minorText) + 1
patchText = 0
elif "patch" in version_increments:
patchText = int(patchText) + 1
# Always increment build
if "build" in version_increments:
buildText = int(buildText) + 1
print_green("Incrementing version to {}.{}.{}.{}".format(majorText,minorText,patchText,buildText))
with open(scriptModPath, "w", newline="\n") as file:
file.writelines([
"#define MAJOR {}\n".format(majorText),
"#define MINOR {}\n".format(minorText),
"#define PATCHLVL {}\n".format(patchText),
"#define BUILD {}\n".format(buildText)
])
if majorText:
versionStamp = "{major}.{minor}.{patchlvl}.{build}".format(major=majorText,minor=minorText,patchlvl=patchlvlText,build=buildText)
versionStamp = "{}.{}.{}.{}".format(majorText,minorText,patchText,buildText)
else:
print_error("A Critical file seems to be missing or inaccessible: {}".format(scriptModPath))
@ -565,22 +588,15 @@ def get_project_version():
def replace_file(filePath, oldSubstring, newSubstring):
#Create temp file
fh, absPath = mkstemp()
with open(absPath,'w') as newFile:
with open(filePath) as oldFile:
for line in oldFile:
newFile.write(line.replace(oldSubstring, newSubstring))
newFile.close()
#Remove original file
os.remove(filePath)
#Move new file
shutil.move(absPath, filePath)
for line in fileinput.input(filePath, inplace=True):
# Use stdout directly, print() adds newlines automatically
sys.stdout.write(line.replace(oldSubstring,newSubstring))
def set_version_in_files():
newVersion = project_version # MAJOR.MINOR.PATCH.BUILD
newVersionShort = newVersion[:-2] # MAJOR.MINOR.PATCH
newVersionArr = newVersion.split(".")
newVersionShort = ".".join((newVersionArr[0],newVersionArr[1],newVersionArr[2])) # MAJOR.MINOR.PATCH
# Regex patterns
pattern = re.compile(r"([\d]+\.[\d]+\.[\d]+\.[\d]+)") # MAJOR.MINOR.PATCH.BUILD
@ -598,28 +614,26 @@ def set_version_in_files():
f.close()
if fileText:
# Search and save version stamp, search short if long not found
versionFound = re.findall(pattern, fileText)
if not versionFound:
versionFound = re.findall(patternShort, fileText)
# Version string files
# Search and save version stamp
versionsFound = re.findall(pattern, fileText) + re.findall(patternShort, fileText)
# Filter out sub-versions of other versions
versionsFound = [j for i, j in enumerate(versionsFound) if all(j not in k for k in versionsFound[i + 1:])]
# Replace version stamp if any of the new version parts is higher than the one found
if versionFound:
# First item in the list findall returns
versionFound = versionFound[0]
newVersionUsed = ""
# Use the same version length as the one found
if len(versionFound) == len(newVersion):
newVersionUsed = newVersion
if len(versionFound) == len(newVersionShort):
newVersionUsed = newVersionShort
# Print change and modify the file if changed
if versionFound != newVersionUsed:
print_green("Changing version {} => {} in {}".format(versionFound, newVersionUsed, filePath))
replace_file(filePath, versionFound, newVersionUsed)
for versionFound in versionsFound:
if versionFound:
# Use the same version length as the one found
newVersionUsed = "" # In case undefined
if versionFound.count(".") == newVersion.count("."):
newVersionUsed = newVersion
if versionFound.count(".") == newVersionShort.count("."):
newVersionUsed = newVersionShort
# Print change and modify the file if changed
if newVersionUsed and versionFound != newVersionUsed:
print_green("Changing version {} => {} in {}".format(versionFound, newVersionUsed, filePath))
replace_file(filePath, versionFound, newVersionUsed)
except WindowsError as e:
# Temporary file is still "in use" by Python, pass this exception
pass
@ -634,13 +648,17 @@ def stash_version_files_for_building():
try:
for file in versionFiles:
filePath = os.path.join(module_root_parent, file)
# Take only file name for stash location if in subfolder (otherwise it gets removed when removing folders from release dir)
if "\\" in file:
count = file.count("\\")
file = file.split("\\", count)[-1]
stashPath = os.path.join(release_dir, file)
print("Temporarily stashing {} => {}.bak for version update".format(filePath, stashPath))
shutil.copy(filePath, "{}.bak".format(stashPath))
if os.path.exists(filePath):
# Take only file name for stash location if in subfolder (otherwise it gets removed when removing folders from release dir)
if "\\" in file:
count = file.count("\\")
file = file.split("\\", count)[-1]
stashPath = os.path.join(release_dir, file)
print("Temporarily stashing {} => {}.bak for version update".format(filePath, stashPath))
shutil.copy(filePath, "{}.bak".format(stashPath))
else:
print_error("Failed temporarily stashing {} for version update".format(filePath))
missingFiles.append("{}".format(filePath))
except:
print_error("Stashing version files failed")
raise
@ -652,6 +670,8 @@ def stash_version_files_for_building():
def restore_version_files():
try:
print_blue("\nRestoring version files...")
for file in versionFiles:
filePath = os.path.join(module_root_parent, file)
# Take only file name for stash path if in subfolder (otherwise it gets removed when removing folders from release dir)
@ -659,8 +679,9 @@ def restore_version_files():
count = file.count("\\")
file = file.split("\\", count)[-1]
stashPath = os.path.join(release_dir, file)
print("Restoring {}".format(filePath))
shutil.move("{}.bak".format(stashPath), filePath)
if os.path.exists(filePath):
print("Restoring {}".format(filePath))
shutil.move("{}.bak".format(stashPath), filePath)
except:
print_error("Restoring version files failed")
raise
@ -669,9 +690,9 @@ def restore_version_files():
def get_private_keyname(commitID,module="main"):
global pbo_name_prefix
global project_version
aceVersion = get_project_version()
keyName = str("{prefix}{version}-{commit_id}".format(prefix=pbo_name_prefix,version=aceVersion,commit_id=commitID))
keyName = str("{prefix}{version}-{commit_id}".format(prefix=pbo_name_prefix,version=project_version,commit_id=commitID))
return keyName
@ -786,6 +807,7 @@ def main(argv):
global prefix
global pbo_name_prefix
global ciBuild
global missingFiles
if sys.platform != "win32":
print_error("Non-Windows platform (Cygwin?). Please re-run from cmd.")
@ -854,12 +876,9 @@ See the make.cfg file for additional build options.
if "release" in argv:
make_release_zip = True
release_version = argv[argv.index("release") + 1]
argv.remove(release_version)
argv.remove("release")
else:
make_release_zip = False
release_version = project_version
if "target" in argv:
make_target = argv[argv.index("target") + 1]
@ -889,8 +908,22 @@ See the make.cfg file for additional build options.
else:
version_update = False
if "--ci" in argv:
argv.remove("--ci")
version_increments = []
if "increment_build" in argv:
argv.remove("increment_build")
version_increments.append("build")
if "increment_patch" in argv:
argv.remove("increment_patch")
version_increments.append("patch")
if "increment_minor" in argv:
argv.remove("increment_minor")
version_increments.append("minor")
if "increment_major" in argv:
argv.remove("increment_major")
version_increments.append("major")
if "ci" in argv:
argv.remove("ci")
ciBuild = True
print_yellow("\nCheck external references is set to {}".format(str(check_external)))
@ -956,21 +989,21 @@ See the make.cfg file for additional build options.
optionals_root = os.path.join(module_root_parent, "optionals")
extensions_root = os.path.join(module_root_parent, "extensions")
commit_id = get_commit_ID()
key_name = versionStamp = get_private_keyname(commit_id)
print_green ("module_root: {}".format(module_root))
if (os.path.isdir(module_root)):
os.chdir(module_root)
else:
print_error ("Directory {} does not exist.".format(module_root))
sys.exit()
sys.exit(1)
commit_id = get_commit_ID()
get_project_version(version_increments)
key_name = versionStamp = get_private_keyname(commit_id)
print_green ("module_root: {}".format(module_root))
if (os.path.isdir(optionals_root)):
print_green ("optionals_root: {}".format(optionals_root))
else:
print_error ("Directory {} does not exist.".format(optionals_root))
sys.exit()
print("optionals_root does not exist: {}".format(optionals_root))
print_green ("release_dir: {}".format(release_dir))
@ -1022,7 +1055,6 @@ See the make.cfg file for additional build options.
cache = {}
# Check the build version (from main) with cached version - forces a full rebuild when version changes
project_version = get_project_version()
cacheVersion = "None";
if 'cacheVersion' in cache:
cacheVersion = cache['cacheVersion']
@ -1046,6 +1078,9 @@ See the make.cfg file for additional build options.
print_error("Cannot create release directory")
raise
failedBuilds = []
missingFiles = []
# Update version stamp in all files that contain it
# Update version only for release if full update not requested (backup and restore files)
print_blue("\nChecking for obsolete version numbers...")
@ -1056,14 +1091,12 @@ See the make.cfg file for additional build options.
set_version_in_files();
print("Version in files has been changed, make sure you commit and push the updates!")
amountOfBuildsFailed = 0
namesOfBuildsFailed = []
try:
# Temporarily copy optionals_root for building. They will be removed later.
optionals_modules = []
optional_files = []
copy_optionals_for_building(optionals_modules,optional_files)
if (os.path.isdir(optionals_root)):
optionals_modules = []
optional_files = []
copy_optionals_for_building(optionals_modules,optional_files)
# Get list of subdirs in make root.
dirs = next(os.walk(module_root))[1]
@ -1128,15 +1161,14 @@ See the make.cfg file for additional build options.
if (file.endswith(".pbo") and os.path.isfile(os.path.join(obsolete_check_path,file))):
if check_for_obsolete_pbos(module_root, file):
fileName = os.path.splitext(file)[0]
print_yellow("Removing obsolete file => {}".format(file))
print_yellow("Removing obsolete pbo => {}".format(file))
purge(obsolete_check_path, "{}\..".format(fileName), "{}.*".format(fileName))
obsolete_check_path = os.path.join(module_root, release_dir, project)
for file in os.listdir(obsolete_check_path):
if (file.endswith(".dll") and os.path.isfile(os.path.join(obsolete_check_path,file))):
if check_for_obsolete_pbos(extensions_root, file):
fileName = os.path.splitext(file)[0]
print_yellow("Removing obsolete file => {}".format(file))
if not os.path.exists(os.path.join(module_root_parent, file)):
print_yellow("Removing obsolete dll => {}".format(file))
try:
os.remove(os.path.join(obsolete_check_path,file))
except:
@ -1282,8 +1314,7 @@ See the make.cfg file for additional build options.
print_error("pboProject return code == {}".format(str(ret)))
print_error("Module not successfully built/signed. Check your {}temp\{}_packing.log for more info.".format(work_drive,module))
print ("Resuming build...")
amountOfBuildsFailed += 1
namesOfBuildsFailed.append("{}".format(module))
failedBuilds.append("{}".format(module))
continue
# Back to the root
@ -1379,7 +1410,8 @@ See the make.cfg file for additional build options.
finally:
copy_important_files(module_root_parent,os.path.join(release_dir, project))
cleanup_optionals(optionals_modules)
if (os.path.isdir(optionals_root)):
cleanup_optionals(optionals_modules)
if not version_update:
restore_version_files()
@ -1399,8 +1431,7 @@ See the make.cfg file for additional build options.
# Make release
if make_release_zip:
release_name = "{}_{}".format(zipPrefix, release_version)
print_blue("\nMaking release: {}.zip".format(release_name))
release_name = "{}_{}".format(zipPrefix, project_version)
try:
# Delete all log files
@ -1415,7 +1446,10 @@ See the make.cfg file for additional build options.
os.remove(os.path.join(release_dir, file))
# Create a zip with the contents of release folder in it
print_blue("\nMaking release: {}.zip ...".format(release_name))
print("Packing...")
release_zip = shutil.make_archive("{}".format(release_name), "zip", release_dir)
# Move release zip to release folder
shutil.copy(release_zip, release_dir)
os.remove(release_zip)
@ -1450,15 +1484,23 @@ See the make.cfg file for additional build options.
except:
print_error("Could not copy files. Is Arma 3 running?")
if amountOfBuildsFailed > 0:
print_error("Build failed. {} pbos failed.".format(amountOfBuildsFailed))
if len(failedBuilds) > 0 or len(missingFiles) > 0:
if len(failedBuilds) > 0:
print()
print_error("Build failed! {} PBOs failed!".format(len(failedBuilds)))
for failedBuild in failedBuilds:
print("- {} failed.".format(failedBuild))
for failedModuleName in namesOfBuildsFailed:
print("- {} failed.".format(failedModuleName))
if len(missingFiles) > 0:
missingFiles = set(missingFiles)
print()
print_error("Missing files! {} files not found!".format(len(missingFiles)))
for missingFile in missingFiles:
print("- {} failed.".format(missingFile))
sys.exit(1)
else:
print_green("\Completed with 0 errors.")
print_green("\nCompleted with 0 errors.")
if __name__ == "__main__":
start_time = timeit.default_timer()