Moin Leute.
Hier mal mein kleines EXP System. Ihr könnt hiermit beim farmen ganz einfach EXP sammeln und diese dann mit life_EXP abfragen.
Wenn ihr Fehler habt, schickt mir bitte euren kompletten Log + ExtDB Log, ansonsten kann und wird euch keiner helfen.
Let's go.
Life_server
fn_queryRequest
Spoiler anzeigen
Code
#include "\life_server\script_macros.hpp"
/*
File: fn_queryRequest.sqf
Author: Bryan "Tonic" Boardwine
Description:
Handles the incoming request and sends an asynchronous query
request to the database.
Return:
ARRAY - If array has 0 elements it should be handled as an error in client-side files.
STRING - The request had invalid handles or an unknown error and is logged to the RPT.
*/
private ["_uid","_side","_query","_queryResult","_tickTime","_tmp"];
_uid = [_this,0,"",[""]] call BIS_fnc_param;
_side = [_this,1,sideUnknown,[civilian]] call BIS_fnc_param;
_ownerID = [_this,2,objNull,[objNull]] call BIS_fnc_param;
if (isNull _ownerID) exitWith {};
_ownerID = owner _ownerID;
_query = switch (_side) do {
// West - 11 entries returned
case west: {format ["SELECT pid, name, cash, bankacc, adminlevel, donorlevel, cop_licenses, coplevel, cop_gear, blacklist, cop_stats, playtime FROM players WHERE pid='%1'",_uid];};
// Civilian - 13 entries returned
case civilian: {format ["SELECT pid, name, cash, bankacc, adminlevel, donorlevel, civ_licenses, arrested, civ_gear, civ_stats, civ_alive, civ_position, playtime, EXP, LEVEL FROM players WHERE pid='%1'",_uid];};
// Independent - 10 entries returned
case independent: {format ["SELECT pid, name, cash, bankacc, adminlevel, donorlevel, med_licenses, mediclevel, med_gear, med_stats, playtime FROM players WHERE pid='%1'",_uid];};
};
_tickTime = diag_tickTime;
_queryResult = [_query,2] call DB_fnc_asyncCall;
if (EXTDB_SETTING(getNumber,"DebugMode") isEqualTo 1) then {
diag_log "------------- Client Query Request -------------";
diag_log format ["QUERY: %1",_query];
diag_log format ["Time to complete: %1 (in seconds)",(diag_tickTime - _tickTime)];
diag_log format ["Result: %1",_queryResult];
diag_log "------------------------------------------------";
};
if (_queryResult isEqualType "") exitWith {
[] remoteExecCall ["SOCK_fnc_insertPlayerInfo",_ownerID];
};
if (count _queryResult isEqualTo 0) exitWith {
[] remoteExecCall ["SOCK_fnc_insertPlayerInfo",_ownerID];
};
//Blah conversion thing from a2net->extdb
_tmp = _queryResult select 2;
_queryResult set[2,[_tmp] call DB_fnc_numberSafe];
_tmp = _queryResult select 3;
_queryResult set[3,[_tmp] call DB_fnc_numberSafe];
//Parse licenses (Always index 6)
_new = [(_queryResult select 6)] call DB_fnc_mresToArray;
if (_new isEqualType "") then {_new = call compile format ["%1", _new];};
_queryResult set[6,_new];
//Convert tinyint to boolean
_old = _queryResult select 6;
for "_i" from 0 to (count _old)-1 do {
_data = _old select _i;
_old set[_i,[_data select 0, ([_data select 1,1] call DB_fnc_bool)]];
};
_queryResult set[6,_old];
_new = [(_queryResult select 8)] call DB_fnc_mresToArray;
if (_new isEqualType "") then {_new = call compile format ["%1", _new];};
_queryResult set[8,_new];
//Parse data for specific side.
switch (_side) do {
case west: {
_queryResult set[9,([_queryResult select 9,1] call DB_fnc_bool)];
//Parse Stats
_new = [(_queryResult select 10)] call DB_fnc_mresToArray;
if (_new isEqualType "") then {_new = call compile format ["%1", _new];};
_queryResult set[10,_new];
//Playtime
_new = [(_queryResult select 11)] call DB_fnc_mresToArray;
if (_new isEqualType "") then {_new = call compile format ["%1", _new];};
_index = TON_fnc_playtime_values_request find [_uid, _new];
if (_index != -1) then {
TON_fnc_playtime_values_request set[_index,-1];
TON_fnc_playtime_values_request = TON_fnc_playtime_values_request - [-1];
TON_fnc_playtime_values_request pushBack [_uid, _new];
} else {
TON_fnc_playtime_values_request pushBack [_uid, _new];
};
[_uid,_new select 0] call TON_fnc_setPlayTime;
};
case civilian: {
_queryResult set[7,([_queryResult select 7,1] call DB_fnc_bool)];
//Parse Stats
_new = [(_queryResult select 9)] call DB_fnc_mresToArray;
if (_new isEqualType "") then {_new = call compile format ["%1", _new];};
_queryResult set[9,_new];
//Position
_queryResult set[10,([_queryResult select 10,1] call DB_fnc_bool)];
_new = [(_queryResult select 11)] call DB_fnc_mresToArray;
if (_new isEqualType "") then {_new = call compile format ["%1", _new];};
_queryResult set[11,_new];
//Playtime
_new = [(_queryResult select 12)] call DB_fnc_mresToArray;
if (_new isEqualType "") then {_new = call compile format ["%1", _new];};
_index = TON_fnc_playtime_values_request find [_uid, _new];
if (_index != -1) then {
TON_fnc_playtime_values_request set[_index,-1];
TON_fnc_playtime_values_request = TON_fnc_playtime_values_request - [-1];
TON_fnc_playtime_values_request pushBack [_uid, _new];
} else {
TON_fnc_playtime_values_request pushBack [_uid, _new];
};
[_uid,_new select 2] call TON_fnc_setPlayTime;
_tmp = _queryResult select 13;
_queryResult set[12,[_tmp] call DB_fnc_numberSafe];
_tmp = _queryResult select 14;
_queryResult set[13,[_tmp] call DB_fnc_numberSafe];
/* Make sure nothing else is added under here */
_houseData = _uid spawn TON_fnc_fetchPlayerHouses;
waitUntil {scriptDone _houseData};
_queryResult pushBack (missionNamespace getVariable [format ["houses_%1",_uid],[]]);
_gangData = _uid spawn TON_fnc_queryPlayerGang;
waitUntil{scriptDone _gangData};
_queryResult pushBack (missionNamespace getVariable [format ["gang_%1",_uid],[]]);
};
case independent: {
//Parse Stats
_new = [(_queryResult select 9)] call DB_fnc_mresToArray;
if (_new isEqualType "") then {_new = call compile format ["%1", _new];};
_queryResult set[9,_new];
//Playtime
_new = [(_queryResult select 10)] call DB_fnc_mresToArray;
if (_new isEqualType "") then {_new = call compile format ["%1", _new];};
_index = TON_fnc_playtime_values_request find [_uid, _new];
if !(_index isEqualTo -1) then {
TON_fnc_playtime_values_request set[_index,-1];
TON_fnc_playtime_values_request = TON_fnc_playtime_values_request - [-1];
TON_fnc_playtime_values_request pushBack [_uid, _new];
} else {
TON_fnc_playtime_values_request pushBack [_uid, _new];
};
[_uid,_new select 1] call TON_fnc_setPlayTime;
};
};
publicVariable "TON_fnc_playtime_values_request";
_keyArr = missionNamespace getVariable [format ["%1_KEYS_%2",_uid,_side],[]];
_queryResult pushBack _keyArr;
_queryResult remoteExec ["SOCK_fnc_requestReceived",_ownerID];
Alles anzeigen
fn_updatePartial
case 8 erstellen
Spoiler anzeigen
Code
case 8: {
_value = [_this,2,0,[0]] call BIS_fnc_param;
_value = [_value] call DB_fnc_numberSafe;
_query = format ["UPDATE players SET EXP='%1' WHERE pid='%2'",_value,_uid];
};
case 9: {
_value = [_this,2,0,[0]] call BIS_fnc_param;
_value = [_value] call DB_fnc_numberSafe;
_query = format ["UPDATE players SET LEVEL='%1' WHERE pid='%2'",_value,_uid];
};
Alles anzeigen
fn_updateRequest
Spoiler anzeigen
Code
/*
File: fn_updateRequest.sqf
Author: Bryan "Tonic" Boardwine
Description:
Updates ALL player information in the database.
Information gets passed here from the client side file: core\session\fn_updateRequest.sqf
*/
private ["_uid","_side","_cash","_bank","_licenses","_gear","_stats","_name","_alive","_position","_query","_thread","_EXP","_LEVEL"];
_uid = [_this,0,"",[""]] call BIS_fnc_param;
_name = [_this,1,"",[""]] call BIS_fnc_param;
_side = [_this,2,sideUnknown,[civilian]] call BIS_fnc_param;
_cash = [_this,3,0,[0]] call BIS_fnc_param;
_bank = [_this,4,5000,[0]] call BIS_fnc_param;
_licenses = [_this,5,[],[[]]] call BIS_fnc_param;
_gear = [_this,6,[],[[]]] call BIS_fnc_param;
_stats = [_this,7,[100,100],[[]]] call BIS_fnc_param;
_alive = [_this,9,false,[true]] call BIS_fnc_param;
_position = [_this,10,[],[[]]] call BIS_fnc_param;
_EXP = [_this,11,0,[0]] call BIS_fnc_param;
_LEVEL = [_this,12,0,[0]] call BIS_fnc_param;
//Get to those error checks.
if ((_uid isEqualTo "") || (_name isEqualTo "")) exitWith {};
//Parse and setup some data.
_name = [_name] call DB_fnc_mresString;
_gear = [_gear] call DB_fnc_mresArray;
_stats = [_stats] call DB_fnc_mresArray;
_cash = [_cash] call DB_fnc_numberSafe;
_bank = [_bank] call DB_fnc_numberSafe;
_EXP = [_EXP] call DB_fnc_numberSafe;
_LEVEL = [_LEVEL] call DB_fnc_numberSafe;
_position = if (_side isEqualTo civilian) then {[_position] call DB_fnc_mresArray} else {[]};
//Does something license related but I can't remember I only know it's important?
for "_i" from 0 to count(_licenses)-1 do {
_bool = [(_licenses select _i) select 1] call DB_fnc_bool;
_licenses set[_i,[(_licenses select _i) select 0,_bool]];
};
_licenses = [_licenses] call DB_fnc_mresArray;
//PLAYTIME
_playtime = [_uid] call TON_fnc_getPlayTime;
_playtime_update = [];
{
if ((_x select 0) isEqualTo _uid) exitWith
{
_playtime_update pushBack [_x select 1];
};
} forEach TON_fnc_playtime_values_request;
_playtime_update = (_playtime_update select 0) select 0;
switch (_side) do {
case west: {_playtime_update set[0,_playtime];};
case civilian: {_playtime_update set[2,_playtime];};
case independent: {_playtime_update set[1,_playtime];};
};
_playtime_update = [_playtime_update] call DB_fnc_mresArray;
switch (_side) do {
case west: {_query = format ["UPDATE players SET name='%1', cash='%2', bankacc='%3', cop_gear='%4', cop_licenses='%5', cop_stats='%6', playtime='%7' WHERE pid='%8'",_name,_cash,_bank,_gear,_licenses,_stats,_playtime_update,_uid];};
case civilian: {_query = format ["UPDATE players SET name='%1', cash='%2', bankacc='%3', civ_licenses='%4', civ_gear='%5', arrested='%6', civ_stats='%7', civ_alive='%8', civ_position='%9', playtime='%10', EXP='%11', LEVEL='%12' WHERE pid='%13'",_name,_cash,_bank,_licenses,_gear,[_this select 8] call DB_fnc_bool,_stats,[_alive] call DB_fnc_bool,_position,_playtime_update,_EXP,_LEVEL,_uid];};
case independent: {_query = format ["UPDATE players SET name='%1', cash='%2', bankacc='%3', med_licenses='%4', med_gear='%5', med_stats='%6', playtime='%7' WHERE pid='%8'",_name,_cash,_bank,_licenses,_gear,_stats,_playtime_update,_uid];};
};
_queryResult = [_query,1] call DB_fnc_asyncCall;
Alles anzeigen
Das wars schon vom life_server her.
Jetzt gehen wir zur Mission
fn_requestReceived
bei case Civilian
Spoiler anzeigen
fn_updatePartial
case 8 erstellen
fn_updateRequest
Spoiler anzeigen
Code
#include "..\..\script_macros.hpp"
/*
File: fn_updateRequest.sqf
Author: Tonic
Description:
Passes ALL player information to the server to save player data to the database.
*/
private ["_packet","_array","_flag","_alive","_position"];
_packet = [getPlayerUID player,(profileName),playerSide,CASH,BANK];
_array = [];
_alive = alive player;
_position = getPosATL player;
_flag = switch (playerSide) do {case west: {"cop"}; case civilian: {"civ"}; case independent: {"med"};};
{
_varName = LICENSE_VARNAME(configName _x,_flag);
_array pushBack [_varName,LICENSE_VALUE(configName _x,_flag)];
} forEach (format ["getText(_x >> 'side') isEqualTo '%1'",_flag] configClasses (missionConfigFile >> "Licenses"));
_packet pushBack _array;
call life_fnc_saveGear;
_packet pushBack life_gear;
_array = [];
_array pushBack life_hunger;
_array pushBack life_thirst;
_array pushBack (damage player);
_packet pushBack _array;
switch (playerSide) do {
case civilian: {
_packet pushBack life_is_arrested;
_packet pushBack _alive;
_packet pushBack _position;
_packet pushBack life_EXP;
_packet pushBack life_LEVEL;
};
};
if (life_HC_isActive) then {
_packet remoteExecCall ["HC_fnc_updateRequest",HC_Life];
} else {
_packet remoteExecCall ["DB_fnc_updateRequest",RSERV];
};
Alles anzeigen
Für Eure Datenbank.
Code
ALTER TABLE `altislife`.`players`
ADD COLUMN `EXP` INT(100) NOT NULL DEFAULT 0,
ADD COLUMN `LEVEL` INT(100) NOT NULL DEFAULT 0
In der Config_Gather bei jedem farmitem einfügen. DIe Farmzeit könnt ihr auch beliebig ändern.
fn_gather
Spoiler anzeigen
Code
#include "..\..\script_macros.hpp"
/*
File: fn_gather.sqf
Author: Devilfloh
Description:
Main functionality for gathering.
*/
private ["_maxGather","_resource","_amount","_maxGather","_requiredItem","_EXP","_farmTime"];
if (life_action_inUse) exitWith {};
if !(isNull objectParent player) exitWith {};
if (player getVariable "restrained") exitWith {hint localize "STR_NOTF_isrestrained";};
if (player getVariable "playerSurrender") exitWith {hint localize "STR_NOTF_surrender";};
life_action_inUse = true;
_zone = "";
_requiredItem = "";
_exit = false;
_resourceCfg = missionConfigFile >> "CfgGather" >> "Resources";
for "_i" from 0 to count(_resourceCfg)-1 do {
_curConfig = _resourceCfg select _i;
_resource = configName _curConfig;
_maxGather = getNumber(_curConfig >> "amount");
_zoneSize = getNumber(_curConfig >> "zoneSize");
_resourceZones = getArray(_curConfig >> "zones");
_requiredItem = getText(_curConfig >> "item");
_EXP = getNumber(_curConfig >> "exp");
_farmTime = getNumber(_curConfig >> "farmTime");
{
if ((player distance (getMarkerPos _x)) < _zoneSize) exitWith {_zone = _x;};
} forEach _resourceZones;
if (_zone != "") exitWith {};
};
if (_zone isEqualTo "") exitWith {life_action_inUse = false;};
if (_requiredItem != "") then {
_valItem = missionNamespace getVariable "life_inv_" + _requiredItem;
if (_valItem < 1) exitWith {
switch (_requiredItem) do {
//Messages here
};
life_action_inUse = false;
_exit = true;
};
};
if (_exit) exitWith {life_action_inUse = false;};
_amount = round(random(_maxGather)) + 1;
_diff = [_resource,_amount,life_carryWeight,life_maxWeight] call life_fnc_calWeightDiff;
if (_diff isEqualTo 0) exitWith {
hint localize "STR_NOTF_InvFull";
life_action_inUse = false;
};
switch (_requiredItem) do {
case "pickaxe": {player say3D "mining";};
default {player say3D "harvest";};
};
for "_i" from 0 to _farmTime do {
player playMoveNow "AinvPercMstpSnonWnonDnon_Putdown_AmovPercMstpSnonWnonDnon";
waitUntil{animationState player != "AinvPercMstpSnonWnonDnon_Putdown_AmovPercMstpSnonWnonDnon";};
sleep 0.5;
};
if ([true,_resource,_diff] call life_fnc_handleInv) then {
_itemName = M_CONFIG(getText,"VirtualItems",_resource,"displayName");
[ format ["<t size='1'>Erfahrungspunkte +%1</t><t><br/> Du sammelst %2 %3 in %4s</t>",_EXP, _amount, (localize _itemName),_farmTime], SzoneXW, SzoneYH, 5, 0.25 ] spawn BIS_fnc_dynamicText;
};
if (life_EXP isEqualType "" ) then {
life_EXP= parseNumber (life_EXP);
};
life_EXP = life_EXP + _EXP;
sleep 1;
life_action_inUse = false;
Alles anzeigen
fn_mine
Spoiler anzeigen
Code
#include "..\..\script_macros.hpp"
/*
File: fn_mine.sqf
Author: Devilfloh
Editor: Dardo
Description:
Same as fn_gather,but it allows use of probabilities for mining.
*/
private ["_maxGather", "_resource", "_amount", "_requiredItem", "_mined","_EXP","_farmTime"];
if (life_action_inUse) exitWith {};
if !(isNull objectParent player) exitWith {};
if (player getVariable "restrained") exitWith {
hint localize "STR_NOTF_isrestrained";
};
_exit = false;
if (player getVariable "playerSurrender") exitWith {
hint localize "STR_NOTF_surrender";
};
life_action_inUse = true;
_zone = "";
_requiredItem = "";
_resourceCfg = missionConfigFile >> "CfgGather" >> "Minerals";
_percent = (floor random 100) + 1; //Make sure it's not 0
for "_i" from 0 to count(_resourceCfg)-1 do {
_curConfig = _resourceCfg select _i;
_resources = getArray(_curConfig >> "mined");
_maxGather = getNumber(_curConfig >> "amount");
_zoneSize = getNumber(_curConfig >> "zoneSize");
_resourceZones = getArray(_curConfig >> "zones");
_requiredItem = getText(_curConfig >> "item");
_EXP = getNumber(_curConfig >> "exp");
_farmTime = getNumber(_curConfig >> "farmTime");
_mined = "";
if (_resources isEqualTo []) exitWith {}; //Smart guy :O
for "_i" from 0 to count (_resources) do {
if (count _resources isEqualTo 1) exitWith {
if (!((_resources select 0) isEqualType [])) then {
_mined = _resources select 0;
} else {
_mined = (_resources select 0) select 0;
};
};
_resource = (_resources select _i) select 0;
_prob = (_resources select _i) select 1;
_probdiff = (_resources select _i) select 2;
if ((_percent >= _prob) && (_percent <= _probdiff)) exitWith {
_mined = _resource;
};
};
{
if ((player distance(getMarkerPos _x)) < _zoneSize) exitWith {
_zone = _x;
};
} forEach _resourceZones;
if (_zone != "") exitWith {};
};
if (_zone isEqualTo "") exitWith {
life_action_inUse = false;
};
if (_requiredItem != "") then {
_valItem = missionNamespace getVariable "life_inv_" + _requiredItem;
if (_valItem < 1) exitWith {
switch (_requiredItem) do {
case "pickaxe": {
titleText[(localize "STR_NOTF_Pickaxe"), "PLAIN"];
};
};
life_action_inUse = false;
_exit = true;
};
};
if (_exit) exitWith {
life_action_inUse = false;
};
_amount = round(random(_maxGather)) + 1;
_diff = [_mined, _amount, life_carryWeight, life_maxWeight] call life_fnc_calWeightDiff;
if (_diff isEqualTo 0) exitWith {
hint localize "STR_NOTF_InvFull";
life_action_inUse = false;
};
player say3D "mining";
for "_i" from 0 to _farmTime do {
player playMoveNow "AinvPercMstpSnonWnonDnon_Putdown_AmovPercMstpSnonWnonDnon";
waitUntil {
animationState player != "AinvPercMstpSnonWnonDnon_Putdown_AmovPercMstpSnonWnonDnon";
};
sleep 0.5;
};
if (([true, _mined, _diff] call life_fnc_handleInv)) then {
_itemName = M_CONFIG(getText, "VirtualItems", _mined, "displayName");
[ format ["<t size='1'>Erfahrungspunkte +%1</t><t><br/> Du sammelst %2 %3 in %4s</t>",_EXP, _amount, (localize _itemName),_farmTime], SzoneXW, SzoneYH, 5, 0.25 ] spawn BIS_fnc_dynamicText;
};
if (life_EXP isEqualType "" ) then {
life_EXP= parseNumber (life_EXP);
};
life_EXP = life_EXP + _EXP;
sleep 2.5;
life_action_inUse = false;
Alles anzeigen
configuration.sqf
Code
SzoneXW = [safezoneX + safezoneW - 0.89,0.50]; //was tollesSzoneYH = [safezoneY + safezoneH - 1.28,0.7]; //nochwas tolles
Der DynamicText ist von D41.
Derzeitige Bugs:
- Keine! Danke an Speedo
Viel Spaß