Skip to content

Commit

Permalink
Initial public commit
Browse files Browse the repository at this point in the history
Currently in a working state
  • Loading branch information
Sotirios Pupakis committed Jun 13, 2022
1 parent 1ecaa25 commit f999832
Show file tree
Hide file tree
Showing 22 changed files with 789 additions and 1 deletion.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@

.vscode/
41 changes: 40 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,40 @@
StatsLogger
# Arma 3 Stats Plugin
This plugin is still in **early development** and will change going forward.<br>
This plugin is mainly intended to be used in [OFCRA](https://ofcrav2.org/forum/index.php) PvP games. But is simple to use and can be used by anyone.

# **CURENTLY TESTED AND DEVELOPED ONLY ON LINUX**

## Current features
- tracks all players, their role, side and squad
- tracks all kills, distance, weapon used (filters out bots)
- tracks number of shots fired per each user
- ability to add winning side and the points

## Planned features
- add number of hits for every player (accuracy can be calculated afterwards)
- simple windows compilation
- config file so output folder can be easily configured

# Usage
**Curently, the default output folder is `/stats-output/`, user running the server needs permission to write into this folder.**<br>
This folder can be edited in `extension/main.cpp` on line 150 and needs to be recompiled afterwards - **THIS WILL CHANGE**.<br>
This is a server sided mod, so clients are not supposed to have it.
- Download the current released version
- Add the folder into your mods folder
- Add `@statslogger` into you -mod in start script
- Play a mission
- If you want to add a winning side, execute `["WINNING SIDE", "BLUEFOR POINTS", "REDFOR POINTS"] remoteExec "statslogger_fnc_mission_end", 2];`
- Execute `call statslogger_fnc_export;` on the server before mission end (either from debug console, or add it into your framework to be called automatically)

# Currently known bugs
- If a player respawns, some things break (not high priority, mainly used in 1 life PvP games right now)

# Extension compilation
- In case you want to edit the path in the excention and compile it yourself, go into `extension/` and if on Linux, use `make` (x64 version only, you shouldn't use 32 bit anymore anyway)
- If you are on Windows, or want 32 bit version, compilation is on you (for now)

# Editing your framework
- If you want to add a call to this mod into your framework, you can use `if (isClass(configFile >> "CfgPatches" >> "STATSLOGGER")) then {// your code};` to make sure this plugin is loaded.

# Special thanks
Special thanks go to [Indigo](https://github.com/indig0fox), for his help in the creation of this plugin.
33 changes: 33 additions & 0 deletions addons/statslogger/config.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@

class CfgPatches {
class STATSLOGGER {
name = "StatsLogger";
author = "ilbinek";
authors[] = {"ilbinek"};
url = "https://github.com/ilbinek";
version = 0.1;
versionStr = "0.1";
versionAr[] = {0, 1};
requiredAddons[] = {};
requiredVersion = 2.04;
units[] = {};
weapons[] = {};
};
};

class CfgFunctions {
class STATSLOGGER {
class null {
file = "statslogger\functions";
class init {preInit = 1;};
class addEventMission {};
class eh_connected {};
class eh_killed {};
class export {};
class getEventWeaponText {};
class eh_fired {};
//class eh_hit {};
class mission_end{};
};
};
};
7 changes: 7 additions & 0 deletions addons/statslogger/functions/fn_addEventMission.sqf
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
addMissionEventHandler ["PlayerConnected", {
_this call statslogger_fnc_eh_connected;
}];

addMissionEventHandler ["EntityKilled", {
_this call statslogger_fnc_eh_killed;
}];
54 changes: 54 additions & 0 deletions addons/statslogger/functions/fn_eh_connected.sqf
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/*
** indigo, thank you so much for your help, this was... Crazy...
** What you do for the community is awesome! Please keep it up.
*/

// exclude server connected event
if ((_this#4) != 2) then {
_this spawn {
params ["_id", "_uid", "_name", "_jip", "_owner", "_idstr"];

private "_unit";

// wait until the unit associated with the player's netId is not null
waitUntil {
uiSleep 1;
_unit = getUserinfo _idstr select 10;
!isNull _unit;
};

_strClass = typeOf _unit;

_strRole = gettext(configFile >> "Cfgvehicles" >> typeOf(_unit) >> "displayname");
if ((roleDescription _unit) != "") then {
_nbr = (roleDescription _unit) find "@";
if (_nbr < 0) then {
_strRole = (roleDescription _unit);
} else {
_strRole = ((roleDescription _unit) select [0, _nbr]);
};
};

_side = str (side _unit);
_group = str (group _unit);
_tmp = ["PLAYER", _uid, _name, _strRole, _strClass, _side, _group] joinstring "::";
diag_log(text ('[STATS] ' + _tmp));
"Stats" callExtension _tmp;

_unit addEventHandler ["firedMan", {
_this call statslogger_fnc_eh_fired;
}];

// TODO Will add hits, just not working for now
/*_unit addMPEventHandler ["MPhit", {
_this call statslogger_fnc_eh_fired;
}];*/

// If unit is respawned, something weird happens, so this should get around it
_unit addEventHandler ["Respawn", {
_unit addEventHandler ["firedMan", {
_this call statslogger_fnc_eh_fired;
}];
}];
};
};
5 changes: 5 additions & 0 deletions addons/statslogger/functions/fn_eh_fired.sqf
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
params ["_unit", "_weapon", "_muzzle", "_mode", "_ammo", "_magazine", "_projectile", "_gunner"];
_tmp = ["SHOT", getPlayerUID _unit] joinString "::";
diag_log(text ('[STATS] ' + _tmp));

"Stats" callExtension _tmp;
4 changes: 4 additions & 0 deletions addons/statslogger/functions/fn_eh_hit.sqf
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
//params ["_unit", "_source", "_damage", "_instigator"];
_tmp = ["HIT", getPlayerUID (_this select 1)] joinString "::";
diag_log(text ('[STATS] ' + _tmp));
"Stats" callExtension _tmp;
35 changes: 35 additions & 0 deletions addons/statslogger/functions/fn_eh_killed.sqf
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
params ["_victim", "_killer", "_instigator"];

[_victim, _killer] spawn {
params ["_victim", "_killer"];
if (_killer == _victim) then {
private _time = diag_ticktime;
[_victim, {
_this setVariable ["ace_medical_lastdamageSource", (_this getVariable "ace_medical_lastdamageSource"), 2];
}] remoteExec ["call", _victim];
waitUntil {
diag_ticktime - _time > 10 || !(isnil {
_victim getVariable "ace_medical_lastdamageSource"
});
};
_killer = _victim getVariable ["ace_medical_lastdamageSource", _killer];
} else {
_killer
};
_time = dayTime;
_tmpTime = [_time, "HH:MM"] call BIS_fnc_timeToString;
_weapon = [_killer] call statslogger_fnc_getEventWeaponText;
_uid = "0";
if (isPlayer _victim) then {
_uid = getPlayerUID _victim;
};
_uidk = "0";
if (isPlayer _killer) then {
_uidk = getPlayerUID _killer;
};
if (_uidk != "0" && _uid != "0") then {
_tmp = ["KILL", _uidk, _uid, _weapon, round(_killer distance _victim), _tmpTime] joinString "::";
diag_log(text ('[STATS] ' + _tmp));
"Stats" callExtension _tmp;
}
};
2 changes: 2 additions & 0 deletions addons/statslogger/functions/fn_export.sqf
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
"Stats" callExtension "EXPORT::REALLY::REALLY::REALLY";
diag_log(text ('[STATS] EXPORT CALLED!'));
70 changes: 70 additions & 0 deletions addons/statslogger/functions/fn_getEventWeaponText.sqf
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
/* ----------------------------------------------------------------------------
Script: ocap_fnc_getEventWeaponText
Description:
Used to identify the current weapon a unit is using that has injured or killed another. Will determine the handheld weapon or vehicle weapon they're using.
Called during <ocap_fnc_eh_hit> and <ocap_fnc_eh_killed>.
Parameters:
_instigator - The unit to evaluate [Object]
Returns:
The description of weapon or vehicle > weapon. [String]
Examples:
--- Code
[_instigator] call ocap_fnc_getEventWeaponText
---
Public:
No
Author:
IndigoFox
Note:
Taken from OCAP2 https://github.com/OCAP2
Thank you for all your work you do for the Arma community, great learning resource for new addon makers
---------------------------------------------------------------------------- */

params ["_instigator"];

if (vehicle _instigator isEqualTo _instigator) exitWith {
getText (configFile >> "CfgWeapons" >> currentWeapon _instigator >> "displayName");
};

// pilot/driver doesn't return a value, so check for this
private _turPath = [];
if (count (assignedVehicleRole _instigator) > 1) then {
_turPath = assignedVehicleRole _instigator select 1;
} else {
_turPath = [-1];
};

private _curVic = getText(configFile >> "CfgVehicles" >> (typeOf vehicle _instigator) >> "displayName");
(weaponstate [vehicle _instigator, _turPath]) params ["_curWep", "_curMuzzle", "_curFiremode", "_curMag"];
private _curWepDisplayName = getText(configFile >> "CfgWeapons" >> _curWep >> "displayName");
private _curMagDisplayName = getText(configFile >> "CfgMagazines" >> _curMag >> "displayName");
private _text = _curVic;
if (count _curMagDisplayName < 22) then {
if !(_curWepDisplayName isEqualTo "") then {
_text = _text + " [" + _curWepDisplayName;
if !(_curMagDisplayName isEqualTo "") then {
_text = _text + " / " + _curMagDisplayName + "]";
} else {
_text = _text + "]"
};
};
} else {
if !(_curWepDisplayName isEqualTo "") then {
_text = _text + " [" + _curWepDisplayName;
if (_curWep != _curMuzzle && !(_curMuzzle isEqualTo "")) then {
_text = _text + " / " + _curMuzzle + "]";
} else {
_text = _text + "]";
};
};
};

_text;
42 changes: 42 additions & 0 deletions addons/statslogger/functions/fn_init.sqf
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
// Will change, first test if it even freaking works
{
player createDiarySubject ["StatsLoggerInfo", "StatsPlugin", "\A3\ui_f\data\igui\cfg\simpleTasks\types\whiteboard_ca.paa"];

player createDiaryRecord [
"StatsLoggerInfo",
[
"About",
(
"Because our lord and savior was asking for this for so long,<br/>" +
"this thing finally exists and maybe, just maybe, works.<br/>" +
"this is still in a 'testing' phase and if it breaks, it's not my fault.<br/>" +
"In case you see something weird this game, please report it direcly to<br/>" +
"me (your friend ilbinek), or Manchot and he'll relay it to me."
)
]
];

player createDiaryRecord [
"StatsLoggerInfo",
[
"Status",
(
"Probably working<br/>" +
"Version 0.1<br/>" +
"Really prone to breaking."
)
]
];

} remoteExecCall ["call", 0, true];

// Register mission handlers
call statslogger_fnc_addEventMission;

// Call the basic ocnfiguration for the extension with the mission info
_time = dayTime;
_tmpTime = [_time, "HH:MM"] call BIS_fnc_timeToString;
"Stats" callExtension "RESET";
_tmp = ["MISSION", briefingName, worldName, getMissionConfigValue ["author", ""], "public", _tmpTime] joinString "::";
"Stats" callExtension _tmp;
diag_log(text ('[STATS] Called Stats with ' + _tmp));
7 changes: 7 additions & 0 deletions addons/statslogger/functions/fn_mission_end.sqf
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
params ["_winner", ["_scoreBlue", 0], ["_scoreRed", 0]];

_time = dayTime;
_tmpTime = [_time, "HH:MM"] call BIS_fnc_timeToString;
_tmp = ["WIN", _winner, _tmpTime, _scoreBlue, _scoreRed] joinString "::";
diag_log(text ('[STATS] ' + _tmp));
"Stats" callExtension _tmp;
11 changes: 11 additions & 0 deletions extension/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
CC=g++

all: main.o kill.o player.o mission.o
#$(CC) -c -o main.o main.cpp
$(CC) -shared -o Stats_x64.so main.o kill.o player.o mission.o
rm *.o
#cp Stats_x64.so /home/steam/arma3/

%.o: %.cpp
$(CC) $(CFLAGS) -fPIC -c $<

9 changes: 9 additions & 0 deletions extension/kill.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#include "kill.hpp"

Kill::Kill(std::string killerUID, std::string killedUID, std::string weapon, std::string distance, std::string time) {
this->killerUID = killerUID;
this->killedUID = killedUID;
this->weapon = weapon;
this->distance = distance;
this->time = time;
};
23 changes: 23 additions & 0 deletions extension/kill.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#ifndef KILL_H
#define KILL_H

#include <string>

class Kill {
private:
std::string killerUID;
std::string killedUID;
std::string weapon;
std::string distance;
std::string time;

public:
Kill(std::string killerUID, std::string killedUID, std::string weapon, std::string distance, std::string time);
std::string getKillerUID() {return killerUID;};
std::string getKilledUID() {return killedUID;};
std::string getWeapon() {return weapon;};
std::string getDistance() {return distance;};
std::string getTime() {return time;};
};

#endif
Loading

0 comments on commit f999832

Please sign in to comment.