[aps]gnat 28 Posted November 23, 2009 The whole locality thing does my head in .... looking for some advice on tuning these scripts to work in MP. These work fine in SP (and most can be found inside the beta PBO release of my Subs) INIT.SQS - Called from the addons INIT Eventhandler - If not ISSERVER, exits - Runs ARM.SQF - Runs mando_missileinit.sqf ARM.SQF - Main looping Sub monitoring scipt - If not ISSERVER, exits - Checks animationPhase on the Subs "dive" animation - Checks if PLAYER is in the Sub or not, modifies automatic behaviour according (like auto diving when AI crew see danger) - Uses createvehicle and createUnit to attachto a dummy radar profile vehicle to the sub when Sub on surface of water (surfaced detected via animationPhase of dive animation) - Deletes the dummy vehicle when sub dives - Animates the crew proxy between the conning tower and the bridge dependant on dive status. DIVE.SQF - One shot script whenever crew member triggers (UserActions) a depth change on the of the Subs addon menu - Entry of script has 3 parameters : [this, depth, boolean - absolute depth or change in depth] - If not ISSERVER, exits - Checks the current animationPhase of the addons dive animation - Adjust the addons dive animation via 'animate' command to set a new dive depth FIREMISSILE.SQF - Called from the addons FIRED Eventhandler - If not ISSERVER, exits - If a missile was fired, uses commands like; nearestobject Setvelocity setVectorDir to reposition the missile and let it fly again. - If it was a "dummybullet", use nearestobject to grab it and use deletevehicle to delete it - If it was a "dummybullet" trigger the TARGETTORPEDO script TARGETTORPEDO.SQF - No test like ISSERVER (hmmm, I guess because I call it from FireMissile) - Gets the direction of that fired dummybullet and uses createTrigger to generate and lay a Trigger from the Sub in that direction for 5000 meters. - Trigger is ANY and PRESENT - Grab a LIST of whats in the Trigger - Filter the LIST for Type "Ship" - Find the closest one - Make it the Target and trigger MandoMissile scipts to launch a Torpedo at it. - Adjust the ammo level of the Sub accordingly - Remove the detector trigger (deletevehicle trigger) ..... any advice appreciated :) Share this post Link to post Share on other sites
poweruser 10 Posted November 24, 2009 (edited) Arm.sqf: On OFP and ArmA1 dedicated servers, the command animationPhase always returned 0. I don't know if it's still the same in ArmA2, you might want to check that. If it still returns 0 always, you have to work around it (in singleplayer games and multiplayer games with a client-host you don't need to do that of course). By manually monitoring the latest set animation phase: Simply store the value you used in the animate command, in the variable space of the submarine. In the init-script you have to store the default anim-phase value first of course. And then, whenever you want to check the anim-phase on the dedicated server, read the value from there. To make sure that those two values (value stored in variable space and value read by animationPhase) match at all times (during the animation they don't match of course) execute the animation and the storing of the value only on the server. And that brings me to the next script (dive.sqf): Set up a pvEh on the server that listens to dive requests of the clients. The clients just send a message via publicVariable containing the three parameters of the script. All the checks and the animate command (along with storing the new latest anim-phase) are executed on the server, the clients just send the requests. So far this setup is strictly for mp games with dedicated servers, to have it still working in the other two possible environments arrange the script triggered by the useraction (run on client) this way : if(isServer) then { // do as the server would do } else { // send a request message }; firemissile.sqf should work fine the way it is. targettorpedo.sqf: Instead of creating a trigger you could also use nearestObjects which directly looks for vehicles of the type "Ship". That could reduce the risk of lag, as ArmA doesn't have to syncronise the created trigger with all clients (there's no 'createTriggerLocal' afaik). If nearestObjects with a 2,5km radius (when run on the center of the location to search at) is not performant enough, you could do this: Add a extended init-eH to the vehicle class "Ship" and store all those ever created vehicles in an array. When fired, retrieve all the vehicles from it that are inside the given area. Edited November 24, 2009 by dengibtsschon typos Share this post Link to post Share on other sites
[aps]gnat 28 Posted November 25, 2009 (edited) Thanks mate. Couple comments, new questions; For the animationPhase problem, is there are command to detect is the vehicle is Local to that machine I wonder. (like this isLocal) I assume it has to be local to 1 PC somewhere. The Dive script. No, I can't use global (generally my golden rule anyway). Its ok to use global variables when youre the Mission Maker and you control everything within that game, but its no good when you are just the addon maker. Users of your addon could do things you never catered for. But, the isLocal solution may well be the solution here as well. Another but; I've always assumed that anyone who has accesses and uses an addons action menu will always trigger the resulting action on the "local" version of the addon, and not on all client versions. Anyone confirm? The targettorpedo. The trigger is 5000 meters long, but only 20 meters wide, so its not going to case too much lag I think. Nice idea on the extended eH though .... something to think about. EDIT: A vehicle is always local to the client of its driver.Empty vehicles/objects placed in the mission editor are local to the server. This is from the BIKI, but dates back to OFP. The assumption is a spawned empty vehicle is local to server, and even if a driver has left the vehicle and its empty, it still stays local to the driver until a new driver gets in. Is this still true for ArmA2? And there is a LOCAL command. This may help a lot. Edited November 25, 2009 by [APS]Gnat Share this post Link to post Share on other sites
norrin 9 Posted November 25, 2009 (edited) Hi Gnat, Scripting for MP as you know is a bitch. The hardest thing when scripting for MP for vehicles is knowing their locality. As you're probably aware if a player is the pilot/driver of a vehicle then the vehicle is local to the pilot - if you're in the cargo and its an AI pilot/driver then the vehicle is local to the server but if the pilot/driver is a player its local to the player pilot again. This can cause all sorts of headaches. As you've started to discover the isServer, local and their negatives !isServer and !local are going to become you're new best friends. Another thing is in ArmA2 you can define global variables in a new way using the setVariable and getVariable commands and send them across the network using a true switch in their definition. These can be defined for specific vehicles using the ingame identifier of the vehicle (it does not need to be named in the editor) so you can do something like this in your script _sub setVariable ["Gnat_submersedState", true, true]; - the second true sends the variable across the network and now everyone both client and server will know the state of the sub - I cannot stress enough how useful this is for MP coding. As you suggest an "action" will trigger local to the player however, depending on the code and commands used it may have a global effect. On a related note a piece of code that I use in MP addons that is called by an action looks like this (using the fast rope scripts as an example): if (local _heli) then { nul = [_heli] execVM "\norrn_dbo_fastrope\scripts\draw_ropes.sqf"; nul = [_heli] execVM "\norrn_dbo_fastrope\scripts\draw_ropes1.sqf"; } else { _heli setVehicleInit "nul = [this] execVM '\norrn_dbo_fastrope\scripts\draw_ropes.sqf'; nul = [this] execVM '\ad_helos\FastRope\scripts\draw_ropes1.sqf'"; processINitCommands; }; Essentially, the action calls this script then if the chopper is local to the player it runs the script locally but if the chopper is not local it runs it on all computers connected to the mission, however at the start of the draw_ropes scripts (ie. the scripts called by this code) there is a if(!local _chopper) exitWith {}; statement to prevent the script running on any PCs not local to the chopper. Sorry this all so convoluted but I hope it makes some sense. norrin Edited November 25, 2009 by norrin Share this post Link to post Share on other sites
[aps]gnat 28 Posted November 25, 2009 Thanks Norrin, all of that great info make sense, I just have to get my slow brain to absorb it so I can apply to my addons. I might have to break my golden rule, setVariable and getVariable do sound interesting ;) Share this post Link to post Share on other sites
cross 1 Posted November 25, 2009 http://community.bistudio.com/wiki/Image:arguments_global.gif For any readers reference... Share this post Link to post Share on other sites
UNN 0 Posted November 25, 2009 The assumption is a spawned empty vehicle is local to server, and even if a driver has left the vehicle and its empty, it still stays local to the driver until a new driver gets in.Is this still true for ArmA2? Thats what I always thought, until I was recently told different. Spawned vehicles are local to the client or server that spawns them. So a vehicle created as a result of a user action, will be local to the player. I tested it, just to be sure. It does appear to be the case. Share this post Link to post Share on other sites
ANZACSAS Steven 396 Posted November 27, 2009 I would say so too.I have made missions in the past for dedi server and have used an action that allows players to create the vehicles they want .I didnt do it correctly at first and had "invisible" tanks driving around with humans in them.They and I were there but noone could see each other. Share this post Link to post Share on other sites
VictorFarbau 0 Posted November 27, 2009 Another but; I've always assumed that anyone who has accesses and uses an addons action menu will always trigger the resulting action on the "local" version of the addon, and not on all client versions. Anyone confirm? The way you phrase it is a bit mindboggling. Well, here's my understanding of addon locality: All addon code (called by action menu or eventhandlers or whatever) will be started on each machine. It is up to YOU to either allow or deny further execution on each machine by using "isServer" (see *1 below). A good example of a server only addon would be a time server. You only want one instance of that of course. In that case your first line of code would be checking "isServer" and quit if false. A good example of a client only addon would be particle effects - you can't use particles as MP objects anyway, so quit if "isServer" is true - then it will run only on clients. If a player on a server machine calls the timeserver script it will be run and do what is supposed to do; if a player on a local machine manages to call the script it will also be started but it will quit rightaway. You can add menu actions to each player. If the related action starts a script from an addon - back to statement #1. It will be started locally but you need to determine where it can run. If you want a server only addon only to be controlled by player action menus then I would see two options.1: You will always be the player on the server machine - in that case you can start your addon script and it will run fine. In any case you always need someone playing on the server to call the script successfully.2: You use a dedicated server. In that case the architecture of the addon needs to be a loop checking for global variables. The player action menu would need to call script that sets a global var. Basically the "remote control" principle. In that case you might even only install the addon on your dedicated server - no need for client side installation. My 2 cents - hope there's no twist in there. Seems to work fine for me at least :) VictorFarbau *1 = You could of course do an "isServer" check in the action menu code already - that way you might also control who is allowed to call the code in the 1st place. Share this post Link to post Share on other sites