• Content count

  • Joined

  • Last visited

  • Medals

Community Reputation

22 Excellent


About Muzzleflash

  • Rank
    First Sergeant


  • Interests
    Little of everything
  1. In general you can't change config properties unless they are exposed from a particular script command, like setUnitTrait. It is the case for almost all config properties that you cannot change them unless you modify the addon. I believe you can in VBS, but that won't help you here. It seems from the talk page on Biki - if you look at the bottom - that you are not alone in your request: .
  2. There is a very good reason for that. It is done to both avoid leaking local variables, and also not to have them accidentally overridden. The _this variable is local (private) like any other variable, and is accessible like any other. The variable _this is not always nil for a function called with no argument, and doing that kind of nil check will not work for nested calls. Not setting it to an explicit value can make errors harder to diagnose, especially for medium to large codebases. Personally, I consider code that calls like this for broken, if the code is somehow to be used by others, are call others. Here is an example: Fnc_WithOptionalArgument = { // You can use this instead: // params [["_value", 10]] // but the call later is still wrong private _value = if (isNil "_this") then {10} else {_this}; // Do something with value. }; // For some reason, give this unit waypoint on some its nearest alive enemy. [someDude] call { params ["_unit"]; // This function call will not work intended since the // argument is not a number, but rather call Fnc_WithOptionalArgument; // Do something with _unit //.... };
  3. You asked how to do everything manually. Here is one explanation. The typical approach used (at least for me) is to consider two kinds of clients. The ones currently in the game. For those you give updates regularly and they are then always up to date - this is Part 1. The second kind just joined (JIP) and are not up to date. The goal here is to make them up to date like the rest - Part 2 - and then give them the same updates regularly. Here is how to do it without completely vanilla. For Part 1, (could be in init.sqf): // Section 1 - This is essentially your "stat.sqf" except rewritten as a function. You can still do it with a script though. OnTaskStatusChange = { params ["_taskId", "_newStatus"]; if (_taskId == 1) then { // Create task if not existing // ... // Other tasks based on new status for example: if (_newStatus == "SUCCEEDED") then { // Play conversation // Move respawn }; if (_newStatus == "FAILED") then { // Play other conversation }; }; }; // Section 2 if (hasInterface) then { "Task_1_Status" addPublicVariableEventHandler {[1, _this select 1] spawn OnTaskStatusChange;}; }; // Section 3 if (isServer) then { // Initialize to say, "PENDING" Task_1_Status = "PENDING"; publicVariable "Task_1_Status"; }; In your trigger you would then have something like this in your on act: if (isServer) then {Task_1_Status = "SUCCEEDED"; publicVariable "Task_1_Status"; if (hasInterface) then {[1, Task_1_Status] spawn OnTaskStatusChange; };}; The first two pieces update the variable, and gives it to all clients. Their handler then runs, and thus runs OnTaskStatusChange on all their machines. The last expression is needed because if you do publicVariable, the handlers only run on all other machines except the one you public variable on, so you need to do that manually. This takes care of all current clients. But if someone JIPs that won't get the task until the next update. So we modify the previous section 2 to this: // New section 2: if (hasInterface) then { //Either we already got the data, or we have not received any yet. //If we already have it we need to run manually if (!isNil "Task_1_Status") then { [1, Task_1_Status] spawn OnTaskStatusChange; }; //If we did not have the data yet, we can expect it shortly. //Regardless, on any future updates run the function again. "Task_1_Status" addPublicVariableEventHandler {[1, _this select 1] spawn OnTaskStatusChange;}; }; To be honest all this public variable becomes annoying, so I use something like CBA_addEventHandler and CBA_GlobalEvent . Then the on act of the trigger simply becomes: ["Task_Status", [1, "SUCCEEDED"]] call CBA_fnc_globalEvent; And instead of addPublicVariableEventHandler I just do: ["Task_Status", OnTaskStatusChange] call CBA_fnc_addEventHandler;
  4. For the task itself, your second code should be fine, assuming your trigger is something like: ["t1","stat.sqf"] remoteExec ["execVM",0], since the task framework should automatically work both for current and JIPs so nothing to do there. Instead of both your calls to taskSetState, I would do: if (isServer) then {["tsk1", "SUCCEEDED",true] spawn BIS_fnc_taskSetState;}; since the a single call should automatically sync with current players and JIPs. Assuming BIS_fnc_addRespawnPosition is JIP-compatible - since it is global you might want to wrap that in isServer also - you should be done.
  5. Well the trigger itself only activates/has any effect on the server right? The execution of remoteExec command is only done on the server, and it ensures that "task1completed" execVM "stat.sqf" runs for all current clients. If you add the JIP flag, then it will also run for all future JIPs - isn't that what you want? For all future JIPs to see the task status as complete? Edit: looking at Task Framework implementation you could use that, and at appearance it does look like BI actually made a library that is JIP compatible. It makes all the data about tasks available using publicVariables, and also uses a [...] remoteExecCall ["TaskId", 0, true] to ensure JIPs also get the tasks.
  6. After looking at it a bit. You can't overwrite the function since it is defined in cfgFunction and is final. There are in fact two places it is randomized, and one of them is run directly, so overwriting was never a choice anyway. If you want to overwrite using CBA you would have to do something like this in description.ext: class Extended_Init_EventHandlers { class PO_ISTS_Infantry_B_Base_IND { init = "_this execVM ""myScript.sqf"";"; }; }; You would have to repeat that for the inner Infantry_Base class for all of them. Your "myScript.sqf" in the mission should then revert the randomization. I think that should work - have done similar things using CBA event handlers before. Only other option is to modify, or make an extension addon, for project OPFOR, but that would mean getting permission and etc.. Best bet may be to ask project OPFOR to add such a feature: "PO_enableRandomization" .
  7. Try adding the JIP parameter, then it should also run for JIPs. ["task1Completed","stat.sqf"] remoteExec ["execVM",0, true];
  8. The units from project OPFOR has their own code and has no special handling from BIS_enableRandomization. They run their own function which randomizes outfits. You would have to either overwrite the event handler in the config; or overwrite the entries it uses to pick the equipment; or hijack the randomize function, but I think it is finalized from cfgFunctions so you cannot do that. Interestingly, my own squad is experiencing some weird stuff when a new Zeus joins. Some project opfor units lose their pants. But we run multiple other addons so can't say for sure which one is at fault. Another option if you use CBA, would be to define you own init event handler in description.ext, where you replace their equipment.
  9. Doesn't matter where it is added since it is added for the (always) local player, and the variable incremented is always the global variable on a single machine. This could only lead to multiple countings if added too many times. But, if you see the friends value, that would suggests the value is somehow being made public (e.g. using publicVariable) and overwriting it on other machines.
  10. Depending on what you mean by 3rd party databases, I'm guessing sqlite is also not viable, nor anything else that requires putting a DLL on the server. You can dump info into the .rpt file but that requires .rpt logging is enabled, and only easily handles the saving part. Otherwise your only solution is to use profileNamespace. But for saving the actual data, I guess you can just use the same technique you currently use to save the player positions? Curios to how that is done. For vehicles it is more complicated because you need correlate ids with what you saved. So if you have Vehicle A at mission start and give it ID X, then when you load the mission, you have to somehow find out how to give it ID X again, otherwise you can't update its stats to match what was saved, and you risk spawning another vehicle on top of it. Another option is to distinguish between starting and loading a mission. If the mission is "started" you don't load anything. If the mission was "loaded", you delete everything at the beginning and recreate what is necessary from the save. Other than that, you save stuff pretty much like you do for players.
  11. I don't know their reason, but can think of multiple minor reasons: 1. The game loop. Every frame the game runs through and update the physics and the graphics, check key inputs. So they only check whether you are shooting FPS times per second. They could do a more advanced shooting model to help with that, but that would complicate the code, and for what? With 15 fps, barely playable, you can still fire at 900 rpm. 2. Performance. If you have bad FPS, then it is because there is too much stuff going on. Putting more than one bullet in the air per frame just means you computer has to deal with even more stuff. Restricting it could help with that. 3. Would you even notice? If you fire more than 1 bullets per frame, some frame will create 2 new bullets at the same time, which is something only shotguns should do. I think if it is any of these reasons, it is either 1 or 3.
  12. The firing rate is 60 / reloadtime . For your Katiba it is 800 rpm. The FPS only limits if it is too high. If you have 40FPS you can't fire more than 2400 rpm.
  13. You can use these new event scripts if you want to. But it is not clear (to me), whether initPlayerServer.sqf, and initPlayerLocal.sqf both runs for the host on a hosted server (haven't bothered testing). Even then, if only one runs, initServer.sqf still also runs. And if you look at the initialization order it is not even guaranteed what order they run in. In addition they are run the scheduled environment, so one might be paused halfway through, and then the other runs. So you can't be sure anything defined by the "previous" script is ready. I find that it is easier to just use one script (init.sqf) we always had, and then manually control the execution. That way you can be sure things don't conflict. Something like: // You can't prevent this file from being run for JIPs // But you can make them abort processing it immediately if (didJIP) exitWith { //Bird is the word }; if (isServer) then { [] call compile preProcessFile "jts_serverInit.sqf"; }; if (hasInterface) then { [] call compile preProcessFile "jts_playerInit.sqf"; }; if (!isServer && !hasInterface) then { // If you want to handle headless clients };
  14. That certainly was the usual way. But with the recent extension to private and the introduction of params I will never write so many lines again when I can just do: params ["_group", "_pos", "_max_area", "_behav"]; private _min_area = if (_max_area < 50) then {0} else {50};
  15. Unless they changed something recently, init.sqf is always run.