Moin,
mir ist (vermutlich) ein Bug / Dupe aufgefallen, man kann mit einen Speedclicker Häuser mehrfach Verkaufen (wegen der "Wollen sie wirklich" frage).
Genauere Infos findet ihr auch hier nochmal: https://github.com/AsYetUntitled/Framework/issues/584
Ein Video zum Bug:
Wie ihr den Bug reproduzieren könnt
- Buy a Garage / House (i mostly tried Garages)
- Have a Speedclicker (https://www.speedautoclicker.net/ <- is a basic one, you can sell the house about 3-4 times with the default "save" settings)
- Open die House menu (windows button)
- Hover over the "Sell" button and activate the speed clicker
- Check your Bank...
Also was machen wir: Wir fügen einen Counter ein der Hochzählt wie oft "verkauft" wird und dann sperrt das die änderungen das Hausverkaufen für 60 Sekunden
So zum fix
1. Altis_Life.Altis/core/configuration.sqf
Unter life_firstSpawn = true; folgendes einfügen gettingBought = 0;
So sollte die Standart Datei aussehen
#include "..\script_macros.hpp"
/*
File: configuration.sqf
Author:
Description:
Master Life Configuration File
This file is to setup variables for the client, there are still other configuration files in the system
*****************************
****** Backend Variables *****
*****************************
*/
life_action_delay = time;
life_trunk_vehicle = objNull;
life_session_completed = false;
life_garage_store = false;
life_session_tries = 0;
life_siren_active = false;
life_clothing_filter = 0;
life_redgull_effect = time;
life_is_processing = false;
life_bail_paid = false;
life_impound_inuse = false;
life_action_inUse = false;
life_spikestrip = objNull;
life_knockout = false;
life_interrupted = false;
life_respawned = false;
life_removeWanted = false;
life_action_gathering = false;
life_god = false;
life_frozen = false;
life_save_gear = [];
life_container_activeObj = objNull;
life_disable_getIn = false;
life_disable_getOut = false;
life_admin_debug = false;
life_civ_position = [];
life_markers = false;
life_markers_active = false;
life_canpay_bail = true;
life_storagePlacing = scriptNull;
life_hideoutBuildings = [];
life_firstSpawn = true;
gettingBought = 0;
//Settings
life_settings_enableNewsBroadcast = profileNamespace getVariable ["life_enableNewsBroadcast", true];
life_settings_enableSidechannel = profileNamespace getVariable ["life_enableSidechannel", true];
life_settings_tagson = profileNamespace getVariable ["life_settings_tagson", true];
life_settings_revealObjects = profileNamespace getVariable ["life_settings_revealObjects", true];
life_settings_viewDistanceFoot = profileNamespace getVariable ["life_viewDistanceFoot", 1250];
life_settings_viewDistanceCar = profileNamespace getVariable ["life_viewDistanceCar", 1250];
life_settings_viewDistanceAir = profileNamespace getVariable ["life_viewDistanceAir", 1250];
//Uniform price (0),Hat Price (1),Glasses Price (2),Vest Price (3),Backpack Price (4)
life_clothing_purchase = [-1, -1, -1, -1, -1];
/*
*****************************
****** Weight Variables *****
*****************************
*/
life_maxWeight = LIFE_SETTINGS(getNumber, "total_maxWeight");
life_carryWeight = 0; //Represents the players current inventory weight (MUST START AT 0).
/*
*****************************
****** Life Variables *******
*****************************
*/
life_net_dropped = false;
life_use_atm = true;
life_is_arrested = false;
life_is_alive = false;
life_delivery_in_progress = false;
life_thirst = 100;
life_hunger = 100;
CASH = 0;
life_istazed = false;
life_isknocked = false;
life_vehicles = [];
/*
Master Array of items?
*/
//Setup variable inv vars.
{
missionNamespace setVariable [ITEM_VARNAME(configName _x), 0];
} forEach ("true" configClasses (missionConfigFile >> "VirtualItems"));
/* Setup the BLAH! */
{
_varName = getText(_x >> "variable");
_sideFlag = getText(_x >> "side");
missionNamespace setVariable [LICENSE_VARNAME(_varName,_sideFlag), false];
} forEach ("true" configClasses (missionConfigFile >> "Licenses"));
/* Setup life_hideoutBuildings */
{
_building = nearestBuilding getMarkerPos _x;
life_hideoutBuildings pushBack _building
} forEach (LIFE_SETTINGS(getArray,"gang_area"));
Alles anzeigen
2. Altis_Life.Altis/core/housing/fn_houseMenu.sqf
_Btn1 buttonSetAction "[life_pInact_curTarget] spawn life_fnc_sellHouse; closeDialog 0;"; durch _Btn1 buttonSetAction "gettingBought = gettingBought + 1; diag_log gettingBought; closeDialog 0; [life_pInact_curTarget] spawn life_fnc_sellHouse;"; ersetzen
_Btn1 buttonSetAction "[life_pInact_curTarget] spawn life_fnc_sellHouse; closeDialog 0;"; durch _Btn1 buttonSetAction "gettingBought = gettingBought + 1; diag_log gettingBought; closeDialog 0; [life_pInact_curTarget] spawn life_fnc_sellHouse;"; ersetzen
_Btn4 buttonSetAction "[life_pInact_curTarget] spawn life_fnc_sellHouseGarage; closeDialog 0;"; durch _Btn4 buttonSetAction "gettingBought = gettingBought + 1; diag_log gettingBought; closeDialog 0; [life_pInact_curTarget] spawn life_fnc_sellHouseGarage;"; ersetzen
So sollte die Standart Datei aussehen
#include "..\..\script_macros.hpp"
/*
File: fn_houseMenu.sqf
Author: Bryan "Tonic" Boardwine
Description:
Building interaction menu
*/
#define Btn1 37450
#define Btn2 37451
#define Btn3 37452
#define Btn4 37453
#define Btn5 37454
#define Btn6 37455
#define Btn7 37456
#define Btn8 37457
#define Title 37401
private ["_display","_curTarget","_Btn1","_Btn2","_Btn3","_Btn4","_Btn5","_Btn6","_Btn7","_Btn8"];
disableSerialization;
_curTarget = param [0,objNull,[objNull]];
if (isNull _curTarget) exitWith {}; //Bad target
_houseCfg = [(typeOf _curTarget)] call life_fnc_houseConfig;
if (count _houseCfg isEqualTo 0 && playerSide isEqualTo civilian) exitWith {};
if (!dialog) then {
createDialog "pInteraction_Menu";
};
_Btn1 = CONTROL(37400,Btn1);
_Btn2 = CONTROL(37400,Btn2);
_Btn3 = CONTROL(37400,Btn3);
_Btn4 = CONTROL(37400,Btn4);
_Btn5 = CONTROL(37400,Btn5);
_Btn6 = CONTROL(37400,Btn6);
_Btn7 = CONTROL(37400,Btn7);
_Btn8 = CONTROL(37400,Btn8);
{_x ctrlShow false;} forEach [_Btn1,_Btn2,_Btn3,_Btn4,_Btn5,_Btn6,_Btn7,_Btn8];
life_pInact_curTarget = _curTarget;
if (_curTarget in life_hideoutBuildings) exitWith {
closeDialog 0;
hint localize "STR_House_Hideout";
};
if (_curTarget isKindOf "House_F" && playerSide isEqualTo west) exitWith {
private _vaultHouse = [[["Altis", "Land_Research_house_V1_F"], ["Tanoa", "Land_Medevac_house_V1_F"]]] call TON_fnc_terrainSort;
private _altisArray = [16019.5,16952.9,0];
private _tanoaArray = [11074.2,11501.5,0.00137329];
private _pos = [[["Altis", _altisArray], ["Tanoa", _tanoaArray]]] call TON_fnc_terrainSort;
if ((nearestObject [_pos,"Land_Dome_Big_F"]) isEqualTo _curTarget || (nearestObject [_pos,_vaultHouse]) isEqualTo _curTarget) then {
_Btn1 ctrlSetText localize "STR_pInAct_Repair";
_Btn1 buttonSetAction "[life_pInact_curTarget] spawn life_fnc_repairDoor; closeDialog 0;";
_Btn1 ctrlShow true;
_Btn2 ctrlSetText localize "STR_pInAct_CloseOpen";
_Btn2 buttonSetAction "[life_pInact_curTarget] call life_fnc_doorAnimate; closeDialog 0;";
_Btn2 ctrlShow true;
} else {
if (!isNil {_curTarget getVariable "house_owner"}) then {
_Btn1 ctrlSetText localize "STR_House_Raid_Owner";
_Btn1 buttonSetAction "[life_pInact_curTarget] call life_fnc_copHouseOwner;";
_Btn1 ctrlShow true;
_Btn2 ctrlSetText localize "STR_pInAct_BreakDown";
_Btn2 buttonSetAction "[life_pInact_curTarget] spawn life_fnc_copBreakDoor; closeDialog 0;";
_Btn2 ctrlShow true;
_Btn3 ctrlSetText localize "STR_pInAct_SearchHouse";
_Btn3 buttonSetAction "[life_pInact_curTarget] spawn life_fnc_raidHouse; closeDialog 0;";
_Btn3 ctrlShow true;
if (player distance _curTarget > 3.6) then {
_Btn3 ctrlEnable false;
};
_Btn4 ctrlSetText localize "STR_pInAct_LockHouse";
_Btn4 buttonSetAction "[life_pInact_curTarget] spawn life_fnc_lockupHouse; closeDialog 0;";
_Btn4 ctrlShow true;
} else {
closeDialog 0;
};
};
};
if (!(_curTarget in life_vehicles) || isNil {_curTarget getVariable "house_owner"}) then {
private _isHouse = (isClass (missionConfigFile >> "Housing" >> worldName >> typeOf _curTarget));
private _buildingPurchaseString = [
"STR_pInAct_BuyGarage",
"STR_pInAct_BuyHouse"
] select _isHouse;
_Btn1 ctrlSetText localize _buildingPurchaseString;
_Btn1 buttonSetAction "[life_pInact_curTarget] spawn life_fnc_buyHouse; closeDialog 0";
_Btn1 ctrlShow true;
if (!isNil {_curTarget getVariable "house_owner"}) then {
_Btn1 ctrlEnable false;
};
if (_isHouse) then {
if (getNumber (missionConfigFile >> "Housing" >> worldName >> (typeOf _curTarget) >> "canGarage") isEqualTo 1) then {
_Btn2 ctrlSetText localize "STR_pInAct_GarageExt";
_Btn2 buttonSetAction 'hint format [localize "STR_pInAct_GarageExtNOTF",[LIFE_SETTINGS(getNumber,"houseGarage_buyPrice")] call life_fnc_numberText];';
_Btn2 ctrlShow true;
};
};
} else {
if (isClass (missionConfigFile >> "Garages" >> worldName >> (typeOf _curTarget))) then {
_Btn1 ctrlSetText localize "STR_pInAct_SellGarage";
_Btn1 buttonSetAction "gettingBought = gettingBought + 1; diag_log gettingBought; closeDialog 0; [life_pInact_curTarget] spawn life_fnc_sellHouse;";
_Btn1 ctrlShow true;
if !(((_curTarget getVariable "house_owner") select 0) isEqualTo getPlayerUID player) then {
_Btn1 ctrlEnable false;
};
_Btn2 ctrlSetText localize "STR_pInAct_AccessGarage";
_Btn2 buttonSetAction "[life_pInact_curTarget,""Car""] spawn life_fnc_vehicleGarage; closeDialog 0;";
_Btn2 ctrlShow true;
_Btn3 ctrlSetText localize "STR_pInAct_StoreVeh";
_Btn3 buttonSetAction "[life_pInact_curTarget,player] spawn life_fnc_storeVehicle; closeDialog 0;";
_Btn3 ctrlShow true;
} else {
_Btn1 ctrlSetText localize "STR_pInAct_SellHouse";
_Btn1 buttonSetAction "gettingBought = gettingBought + 1; diag_log gettingBought; closeDialog 0; [life_pInact_curTarget] spawn life_fnc_sellHouse;";
_Btn1 ctrlShow true;
if (((_curTarget getVariable "house_owner") select 0) != (getPlayerUID player)) then {
_Btn1 ctrlEnable false;
};
if (_curTarget getVariable ["locked",false]) then {
_Btn2 ctrlSetText localize "STR_pInAct_UnlockStorage";
} else {
_Btn2 ctrlSetText localize "STR_pInAct_LockStorage";
};
_Btn2 buttonSetAction "[life_pInact_curTarget] call life_fnc_lockHouse; closeDialog 0;";
_Btn2 ctrlShow true;
if (isNull (_curTarget getVariable ["lightSource",objNull])) then {
_Btn3 ctrlSetText localize "STR_pInAct_LightsOn";
} else {
_Btn3 ctrlSetText localize "STR_pInAct_LightsOff";
};
_Btn3 buttonSetAction "[life_pInact_curTarget] call life_fnc_lightHouseAction; closeDialog 0;";
_Btn3 ctrlShow true;
if (getNumber (missionConfigFile >> "Housing" >> worldName >> (typeOf _curTarget) >> "canGarage") isEqualTo 1 && {!(_curTarget getVariable ["blacklistedGarage",false])}) then {
if (_curTarget getVariable ["garageBought",false]) then {
_Btn4 ctrlSetText localize "STR_pInAct_SellGarage";
_Btn4 buttonSetAction "gettingBought = gettingBought + 1; diag_log gettingBought; closeDialog 0; [life_pInact_curTarget] spawn life_fnc_sellHouseGarage;";
_Btn4 ctrlShow true;
if (((_curTarget getVariable "house_owner") select 0) != (getPlayerUID player)) then {
_Btn4 ctrlEnable false;
};
_Btn5 ctrlSetText localize "STR_pInAct_AccessGarage";
_Btn5 buttonSetAction "[life_pInact_curTarget,""Car""] spawn life_fnc_vehicleGarage; closeDialog 0;";
_Btn5 ctrlShow true;
_Btn6 ctrlSetText localize "STR_pInAct_StoreVeh";
_Btn6 buttonSetAction "[life_pInact_curTarget,player] spawn life_fnc_storeVehicle; closeDialog 0;";
_Btn6 ctrlShow true;
} else {
_Btn5 ctrlSetText localize "STR_pInAct_BuyGarage";
_Btn5 buttonSetAction "[life_pInact_curTarget] spawn life_fnc_buyHouseGarage; closeDialog 0;";
};
_Btn5 ctrlShow true;
};
};
};
Alles anzeigen
3. Altis_Life.Altis/core/housing/fn_sellHouse.sqf
Fügt nach if (_action) then { folgendes ein if (gettingBought > 1) exitWith { hint localize "STR_House_CoolDown"; };
Fügt ganz unten folgendes ein
So sollte die Standart Datei aussehen
#include "..\..\script_macros.hpp"
/*
File: fn_sellHouse.sqf
Author: Bryan "Tonic" Boardwine
Modified : NiiRoZz
Description:
Sells the house and delete all container near house.
*/
private ["_house","_uid","_action","_houseCfg"];
if (dialog) then {closeDialog 0};
_house = param [0,objNull,[objNull]];
_uid = getPlayerUID player;
if (isNull _house) exitWith {};
if (!(_house isKindOf "House_F")) exitWith {};
if (isNil {_house getVariable "house_owner"}) exitWith {hint localize "STR_House_noOwner";};
closeDialog 0;
_houseCfg = [(typeOf _house)] call life_fnc_houseConfig;
if (count _houseCfg isEqualTo 0) exitWith {};
_action = [
format [localize "STR_House_SellHouseMSG",
(round((_houseCfg select 0)/2)) call life_fnc_numberText,
(_houseCfg select 1)],localize "STR_pInAct_SellHouse",localize "STR_Global_Sell",localize "STR_Global_Cancel"
] call BIS_fnc_guiMessage;
if (_action) then {
if (gettingBought > 1) exitWith { hint localize "STR_House_CoolDown"; };
_house setVariable ["house_sold",true,true];
if (life_HC_isActive) then {
[_house] remoteExecCall ["HC_fnc_sellHouse",HC_Life];
} else {
[_house] remoteExecCall ["TON_fnc_sellHouse",RSERV];
};
_house setVariable ["locked",false,true];
deleteMarkerLocal format ["house_%1",_house getVariable "uid"];
_house setVariable ["uid",nil,true];
BANK = BANK + (round((_houseCfg select 0)/2));
[1] call SOCK_fnc_updatePartial;
_index = life_vehicles find _house;
if (LIFE_SETTINGS(getNumber,"player_advancedLog") isEqualTo 1) then {
if (LIFE_SETTINGS(getNumber,"battlEye_friendlyLogging") isEqualTo 1) then {
advanced_log = format [localize "STR_DL_AL_soldHouse_BEF",(round((_houseCfg select 0)/2)),[BANK] call life_fnc_numberText];
} else {
advanced_log = format [localize "STR_DL_AL_soldHouse",profileName,(getPlayerUID player),(round((_houseCfg select 0)/2)),[BANK] call life_fnc_numberText];
};
publicVariableServer "advanced_log";
};
if !(_index isEqualTo -1) then {
life_vehicles deleteAt _index;
};
_index = [str(getPosATL _house),life_houses] call TON_fnc_index;
if !(_index isEqualTo -1) then {
life_houses deleteAt _index;
};
_numOfDoors = FETCH_CONFIG2(getNumber,"CfgVehicles",(typeOf _house), "numberOfDoors");
for "_i" from 1 to _numOfDoors do {
_house setVariable [format ["bis_disabled_Door_%1",_i],0,true];
};
_containers = _house getVariable ["containers",[]];
if (count _containers > 0) then {
{
_x setVariable ["Trunk",nil,true];
if (life_HC_isActive) then {
[_x] remoteExecCall ["HC_fnc_sellHouseContainer",HC_Life];
} else {
[_x] remoteExecCall ["TON_fnc_sellHouseContainer",RSERV];
};
} forEach _containers;
};
_house setVariable ["containers",nil,true];
};
sleep 60;
gettingBought = 0;
Alles anzeigen
4. Altis_Life.Altis/core/housing/fn_sellHouseGarage.sqf
Fügt nach if (_action) then { folgendes ein if (gettingBought > 1) exitWith { hint localize "STR_House_CoolDown"; };
Fügt ganz unten folgendes ein
So sollte die Standart Datei aussehen
#include "..\..\script_macros.hpp"
/*
File: fn_sellHouseGarage.sqf
Author: BoGuu
Description:
Sell functionality for house garages.
*/
if (dialog) then {closeDialog 0};
private _house = param [0,objNull,[objNull]];
private _uid = getPlayerUID player;
if (isNull _house) exitWith {};
if !(_house getVariable ["garageBought",false]) exitWith {hint localize "STR_Garage_NotOwned";};
if ((_house getVariable "house_owner") select 0 != getPlayerUID player) exitWith {hint localize "STR_Garage_NotOwner";};
closeDialog 0;
private _sellPrice = LIFE_SETTINGS(getNumber,"houseGarage_sellPrice");
_action = [
format [localize "STR_House_SellGarageMSG",
[_sellPrice] call life_fnc_numberText],
localize "STR_House_GarageSell",
localize "STR_Global_Sell",
localize "STR_Global_Cancel"
] call BIS_fnc_guiMessage;
if (_action) then {
if (gettingBought > 1) exitWith { hint localize "STR_House_CoolDown"; };
if (life_HC_isActive) then {
[_uid,_house,1] remoteExec ["HC_fnc_houseGarage",HC_Life];
} else {
[_uid,_house,1] remoteExec ["TON_fnc_houseGarage",RSERV];
};
BANK = BANK + _sellPrice;
[1] call SOCK_fnc_updatePartial;
_house setVariable ["garageBought",false,true];
};
sleep 60;
gettingBought = 0;
Alles anzeigen
5. Altis_Life.Altis/stringtable.xml
Fügt unter <Package name="Housing_Strings"> folgendes ein:
<Key ID="STR_House_CoolDown">
<Original>You can only sell a house every 60 seconds.</Original>
<Czech>Dům můžete prodat pouze každých 60 sekund.</Czech>
<Spanish>Solo puedes vender una casa cada 60 segundos.</Spanish>
<Russian>Вы можете продавать дом только каждые 60 секунд.</Russian>
<German>Du kannst ein Haus nur alle 60 Sekunden verkaufen.</German>
<French>Vous ne pouvez vendre une maison que toutes les 60 secondes.</French>
<Italian>Puoi vendere una casa solo ogni 60 secondi.</Italian>
<Portuguese>Você só pode vender uma casa a cada 60 segundos.</Portuguese>
<Polish>Możesz sprzedać dom tylko co 60 sekund.</Polish>
<Chinesesimp>您每60秒只能卖出一栋房子。</Chinesesimp>
</Key
Alles anzeigen
Bedenkt das die Standard Dateien nur verwendet werden könnt wenn ihr noch nichts an diesen Dateien verändert habt.