#arma3_scripting
1 messages ยท Page 225 of 1
Probably something really bad in the formation pathfinding.
Maybe the trouble is that if a unit gets a doMove or whatever, it calculates the whole path up-front, but if they're in a formation it's recalculating paths every few seconds.
So you want them ignore their group member getting killed? It's a stealth mission?
Sniping mission but yes
Best bet might be to place agents and then swap them out once they go combat.
couple of units in watchtowers, all in one group. If the player kills one, normally all of them go into combat mode because someone died, even if they don't see each other.
but disabling almost all of their AI and doing the spotting logic yourself is another option.
Or keeping them in careless with custom spotting logic
Someone in the group getting killed bumping the knowsAbout to 1.5 might be unavoidable though.
I though pathfinding is simpfied when they following formation
Simple & often may still be worse than complex and occasional.
so if I disable autocombat on all units and then an "alarmed" unit has it turned back on due to, for example, a missed shot, only that one will go into combat mode?
There's a combat mode for the group as well, which determines some behaviour. Not sure if that one autoswitches or when.
I don't think they switch to combat when autocombat is disabled
It won't prevent them from geting alerted
In aware, they go in formation and upon seeying enemy for example, they autoswitch into combat. In combat mode, they break formation to use cover and move slower as result
But it's not about not getting alerted
Note that the 1.5 knowsAbout bump for killing units only happens local to the shooter, so behaviour on a dedicated server is different to localhost testing.
Well if you are only looking up player you don't need a hashtable for a single entry. And if you are not, it is slower:
getPlayerUID player (0.00027)
idTable get owner player (0.00036)
And on mine this isn't even faster:
idTable get clientOwner; (0.00029)
Though my numbers are from debug console (nvm, the numbers from debug is identical with codePerformance).
Does anyone have a server/mission intro where a video file plays after downloading mission file/selecting role.
I just wanna get uid out of remoteExecutedOwner, which I think is fair
The other way around would be looping thru allPlayers to find the owner that is the same as remoteExecutedOwner and getplayeruid to that player
I see, I could not tell that context from earlier.
Are you sure they are not reused, and if not, are you clearing the data on the hashtable?
My lazy answer would be to unpack BI missions. They are often pretty well annotated. Do the Apex Protocol cooperative campaign missions have videos in the intro?
Heyo guys, I'm planning on creating some evolving style world events on my next scenario that may require some player triggered events. I have a whole thing setup for the aftermath of a camp raid, but I need to find out how to make it be triggered by the player using the radio. Ill create a diagram of what im intended later which should give ya a better idea of what im going for.
So basically swap some bunch of objects into some bunch of objects?
Again ill make a diagram soon that better shows what im going for since its hard to word it haha
Okay heres a breakdown of what I want to do. Hope it helps better explain what knowledge I am looking to attain.
The figs are much more harder to understand the concept to me. I think you can just:
- Store all objects that should appear in the before state into a folder in Eden
- Store all objects that should appear in the after state Into another folder in Eden
- Use
hideObjectGlobalforEachgetMissionLayerEntitiescommands accordingly to switch the state
All thats already prepared, I just need to figure out how to have the radio option activate the trigger I have set up
What I've just told is one way
If you have this already, just set it to Radio Alpha?
In Activation Condition or whatever its called. Find "Radio Alpha"
Is it a script I need to write in the activation field?
No. Above of any script field in the trigger. One of three or four box to select from
Can't tell what's it called right now
Oh I see it needs to be a trigger not tied to a group. Ive found the options now
Can I rename the radio to a custom type?
In-game text? IIRC yes. One of the text field you see in the trigger
Ah I see yeee
That solves the first thing I wanna do with this event.
How can I teleport the player to a specific spot on the map and have them locked in place for a few seconds?
maybe use for locking https://community.bistudio.com/wiki/showCinemaBorder and https://community.bistudio.com/wiki/setPos for teleporting๐คท
disableCollisionWith doesn't work with PhysX geometry objects from my experience.
Hey there, I don't quite understand what you mean on that last sentence.
By the way, did you try the code performance benchmark on SP or MP?
getPlayerUID player SP: 0.00028ms MP: 0.00053ms
There there any stance EHs? (standing, crouching)
only anim ones iirc
If for player, you can use input/ useraction eh
I wouldn't rely on that alone. There's a surprising number of things that can change your stance without you pressing the change stance button.
This is local argument I guess?
https://community.bistudio.com/wiki/addUserActionEventHandler
It's not added to an object. Locality of the arguments doesn't matter because none of them are things that have locality.
It is Local Effect, as noted, meaning it's only added on the machine where the command is executed, and therefore can only fire for actions that happen on that machine
Just tested WeapnChanged, it only fires for local units
https://community.bistudio.com/wiki/Arma_3:_Event_Handlers#WeaponChanged
SP, I am not surprised MP is more expensive. But the point was just resolving the key to lookup take time. It was not clear from the original example code that the final key was given.
What I mean with the last sentence, is that I am not sure machine ID are not reused. Say machine ID 0, 1, 2 are special, clients get assigned 3 or higher on upon joining, and it is not clear whether they are reused or they keep going towards infinity. Consider this example:
- Good Guy Joe joins as machine ID=7.
- You have no entry for 7 so you store 7=getPlayerUID GoodGuyJoe basically.
- Good Guy Joe leaves the server, so machine id 7 is now empty.
- Bad Guy Bjorn joins. The server, maybe it picks first unused slot, or may it has wrapped around because network limits the machine size type, and started looking for empty slots after 2, and it happens to pick 7.
- Bad Guy Bjorn does bad thing. But because you already had an entry you did not lookup getPlayerUID for BadGuyBjorn, but just sees you have a cached entry for machine id 7, so you do attribut the action to GoodGuyJoe.
I don't know whether machine IDs are reused. But if I don't know that they are not, and the use case is attributing blame, I would indeed use the loop you mentioned earlier at a typical bounded upper cost of 0.1ms.
Oh, yeah, I also wanted to point that out. As machine ids get larger, getPlayerUID could potentially surpass the hashmap lookup approach. Indeed, machine ids are not reused and it's incremental
Good to know. I will add that fact to my arma obsidian vault. Bit surprising, but I guess Arma maps the ID to network/directplay IDs internally then.
But yeah, your scheme should be good then
PlayerConnect and HandleDisconnect, I think, could be the ones doing the additions and substractions to the hashmap
But I do not know if the client owner can change at anytime during playtime
Yeah, if all the relevant logic is only on the server then that is indeed a robust simple solution.
I would assume if that could happen we would have known about it by various MP bugs, so I think we safe on that front.
Yeah because the loop is kinda inefficient
And I have to get the player object always in order to get the uid and such
I also dont know if the unit changes when player respawns and all of that, if it doesn't then I could also include the unit to the hashmap
So I get the player object and the uid without looping
Seems like intensity flashlight vs "#lightreflector" is different. Created "#lightreflector" using "acc_flashlight" values from config and even with 10x intensity "#lightreflector" is still less intense
I'm trying to create a Civilian population system where civilians move around the map dynamically/random but one thing that really bothers me and where I hope someone might have an idea is that civilians on foot always walk in the middle of the road. No matter what I do I can't get them to walk on the sidewalks or the side of the road.
Barring very expensive and complex code you are stuck with that.
my problem right now is that I can't think of a way to fix it. Like when I try to make waypoints next to the road and use different combinations of combat mode and so on they still walk on the road, move to the sidewalk to get their waypoint and then get back on the road.
If you give them short distance (like 10m) waypoints along the edge of the road, they'll follow them, right?
let me check (havent tried with such short distances)
just tested, the threshold does seem to be about 10-20m :P
okay yeah even with a distance of less the 10m between the waypoints on a straight sidewalk they go to the waypoint, trun to the road, walk on the road until they are next to the next waypoint and then turn to the waypoint to leave the road for a few seconds
I just used a random road in kavala but maybe.
Also just noticed if you make the distance to short they get stuck between the waypoints
Theres that one mod that has invisible roadway lod objects - if you place those along the sidewalks that could work and not be too expensive
They walk on these slow though
They will walk into the road to move around those pedestrian crossing signs in Kavala.
Eh he wants pedestrians soo.... probably fine?
would be fine yeah
Granted your next hurdle is spawning those on every sidewalk lol. Could probably automate it by taking road positions and offsrtting sideways by x amount and then spawning the objects in the direction of the next road segment
I mean technically all this wouldn't be an issue if it weren't for the problem that I end up having like 30 civis on the road that block the AI vehicles or just get run over
I could spawn them along the path that I calculate for the civ to take to only spawn them where they are really needed
Ye
So either that or... use agents since theyre cheap and what john jordan said just have dense waypoints except theyd be setdestination calls for agents
Not sure agent path calculation is much different except for ignoring enemies. Which is something that should really be an option for normal AIs but isn't.
Its not but i think set destination is cheaper than spawning waypoints, and ofc they dont have any other calcs associated with ai making them cheaper overall
Yeah that's probably true.
But yeah id love more control over ai tbh
The fact its impossible to completely lobotomize it while still allowing you to order them to do specific things is incredibly frustrating
I.e force them to switch weapons lmao
It's kinda strange they don't avoid roads in general. Since pedestrian doesn't want to get hit by a car and soldier in combat doesn't want to be in middle of the road either, because of lack of cover
It might be in favor of preventing vehicles from accidentally moving onto the pavement due to proximity
But idk if ai in vehicles use different pathfinding or not
I'm talking about units
oh yeah i know i just mean that units likely move on the roads because the sidewalks dont have roadway segments or whatever, and they might not have those because it might confuse vehicles due to how close they'd be to the actual road, so basically it's "units will walk on road so that vehicles don't screw up"
So using Agents and doing calculatepath and so on it seems to work perfectly. The agent walks on the side of the road, leaving enough space for vehicles
I just did a little bit of testing but I looks like using agents for the ambient works fine and when I need to do something else with the civilian I can replace the agent with a real unit
huh. Agents don't have the road preference?
Even if you give them a longer destination?
I used the Example 3 from the calculatePath wiki entry and modified it a bit and after like over 10 test runs the agent always walks on the side of the road and only got more to the middle of the road where it was absolutly needed.
Ok well i had to jinx it...
It works almost everytime.
Arma
yeah. But I rather take it where it works 90% of the time instead of it not working at all.
And with like 50 ai's moving around you won't really notice the 10% where it does not work.
Theyre just jaywalkers ๐
Its realistic you see
Either that or insurance fraudsters
But it's still kinda weird that the path calculation for an agent seems to work better then the path path calculation for normal units
It's probably a bug, like 50% of AI behaviour
I'd report the local kill knowsAbout bug except I'm not sure which one is intended :P
I mean imagine creating something without getting at least one bug.
Not AI, but I found this bug yesterday
@tough abyss get away from grid and use safezone
done
and again you use no markdown
start fucking using it
code looks ugly in text chat
either that or use pastebin
Feel that
I've been working on doors today and was checking how units interact with locked doors. I stuck an AI in a fully locked house and ordered them outside to see if they'd walk through the doors (which is what I expected).
The ai surprisingly stopped at the door and just stood there. I telephoned them through the door and then they walked to the next locked door and stopped. I was about to praise Arma for once just to alt tab and tab back in to see it walk through the locked door
On Gabreta(from CSLA CDLC) AI go through closed door regularly. They don't open door for some reason and as a result they just walk through
Any scripting way to detect if someone has their personal NVGs active? I know there's a visionModeChanged handler and that you can bind a flag to flip when the NVG key is pressed, curious if there was just a getter command for that which I missed
Yeah AI just loves to mess with us
works, ok. yeah, had found this before and forgot. thanks
post a pic
and the config#
still i am not sure if this not belongs more to config editing
Ai opening doors requires the Path lod (what ai follow through buildings) to have points set up to where ai will use actions
So if they're not set up correctly, ai just follow the path through the door
scale with resolution ?
if a player is thecommander of a tank, the gunner refuses to listen to doWatch. What can i do to force him to do it?
looks like the classy problem of somebody not understanding the "anchor points"
your X is not the static value you set there
it is the end + the offset from the last element on its left side
reason it looks good on your screen but horrible on his is simply because you have to do the L-R-T-B alignment proper
ArmA itself wont support you
dialogs in general are PITA anyway in arma ๐
That shouldn't be a issue. I just tested in vanilla by placing a tank in editor (player as commander) and issuing the command via debug console. Worked just fine. Is it possible your target is objNull? A mod is cancelling it out?
i can send the script im trying it with
its a bit ugly but well, actively WIP lol
Pastebin.com is the number one paste tool since 2002. Pastebin is a website where you can store text online for a set period of time.
In this section: sqf /// figure out if the commander of the gunner is the primary observer (here called "watcher") /// usually this role is the commanders private _watcher = commander _veh; /// if no commander is found, the gunner is the selected watcher if (isNull _watcher) then { _watcher = gunner _veh; }; if the commander is a player, you are issuing the command to a player unit which is ignored. Try instead something like: ```sqf
/// figure out if the commander of the gunner is the primary observer (here called "watcher")
/// usually this role is the commanders
private _watcher = commander _veh;
/// if no commander is found, the gunner is the selected watcher
if (isNull _watcher || {isPlayer _watcher}) then {
_watcher = gunner _veh;
};
Note: I did not test this solution but, if a player is commander you'd want it anyway. @cursive tundra
private _random = 0;
if (_watcher != gunner _veh) then {
if (count _nearTargets == 0) then {
private _headingGun = _dirVeh;
private _randomDir = random 3;
if (round _random > 2) then {
if (round _randomDir == 0) then {_headingGun = _dirVeh + 20 + random 15;};
if (round _randomDir == 1) then {_headingGun = _dirVeh - 20 - random 15;};
};
if (round _random == 2) then {
if (round _randomDir == 0) then {_headingGun = _dirVeh + 20 + random 35;};
if (round _randomDir == 1) then {_headingGun = _dirVeh - 20 - random 35;};
};
if (round _random == 3) then {
if (round _randomDir == 0) then {_headingGun = _dirVeh + 30 + random 35;};
if (round _randomDir == 1) then {_headingGun = _dirVeh - 30 - random 35;};
};
private _positionGunner = _veh getPos [600,_headingGun];
gunner _veh doWatch _positionGunner;
gunner _veh lookAt _positionGunner;
sleep 5 + random 5;
private _randomReset = random 3;
if (round _randomReset == 0) then {
gunner _veh doWatch objNull;
};
};
};
};
this part seems to be the problem for me - if the watcher is the commander, not the gunner, the gunner should also check infront of the tank, but it wont if a player is in there
at least for me
ah, I see you do specify gunner further down
the reason for this setup is that some vehicles only have a gunner (like HMMWVs) so the gunner needs to be the watcher and turn 360ยฐ, if there is a seperate commander who can do that the gunner should keep the gun pointed forward and only check the front
(also looks a bit silly if tanks constantly turn their turret 360ยฐ lol, esp if multiple are doing it)
Technically all vehicles have a commander. If it's just driver/gunner than driver is effectiveCommander See wiki for commander command.
Since Armed Assault it returns the primary observer.
So you're probably still issuing it to the player. Try my solution and see if it helps. If it does you can probably remove all those (_watcher != gunner _veh) checks
ill have to test a bit if its now the intended behavior but looked promising for now
I admit I didn't deep dive your code. I would assume your explicit gunner _veh would have worked but ๐คท
well, the gunner now turns the turret if the player is the commander, but ceases to turn it if the player is in the vehicle but not the commander...
an AI crewed vehicle will have both the commander turn the cupola and the gunner swing the turret...
i dont get why
Not familiar with these vehicles. As a commander in them, does the player have control over the main gun? Maybe it;s a mod issue? Try a vanilla tank.
The only time I can think the AI loses turret control is if player has control.
it behaves the same in the vanilla tank
ok, I'm going to load up arma and see if I can help.
there is however something odd going on with the gunner slewing the gun in the direction the commander does look, which is why im spamming "gunner _veh doWatch objNull;" during the full commanders rotation
like if u put down a tank and put something like "commander Tank1 doWatch player;" the whole turret will follow the player moving around, not just the gun the commander controls
some other bugs I found: ```sqf
private _randomDir = random 3;
i can only imagine as soon as the player becomes the effectiveCommander, the turret will follow where the player looks
I dont think will ever be 3
out wait no I'm mistaken
this is weird. You round the number which could be 0,1,2, or 3 but only check if it's equal to 0 or 1?
and _random is always 0 so none of those are even checked at all either
does random not create float?
yeah i just saw that
i am wondering how that came to be
and i think i did that so there are lulls
where the turret doesnt turn so the tank doesnt seem hyperactive.. theres probably some better way to do this tho
lol
oh my god - it was the _random = 0 i think.. i wonder how that got there
i was already losing my mind cause the script worked a few days ago, but then i changed a few things, but i dont remember changing that... nor do i see any reason to ever do that
yeah I just eliminated all those if checks and just used _positionGunner = _veh getpos [600, random 360] and it was randomly pointing the gun. So I assume your _headingGun was just always straight ahead.
i think i really messed up when i tried to tune down the constant turning of the turrets
and changed the value to 0 without thinking lol
@cursive tundra Some simplification. Change this entire section : ```sqf
private _random = 0;
if (_watcher != gunner _veh) then {
if (count _nearTargets == 0) then {
private _headingGun = _dirVeh;
private _randomDir = random 3;
if (round _random > 2) then {
if (round _randomDir == 0) then {_headingGun = _dirVeh + 20 + random 15;};
if (round _randomDir == 1) then {_headingGun = _dirVeh - 20 - random 15;};
};
if (round _random == 2) then {
if (round _randomDir == 0) then {_headingGun = _dirVeh + 20 + random 35;};
if (round _randomDir == 1) then {_headingGun = _dirVeh - 20 - random 35;};
};
if (round _random == 3) then {
if (round _randomDir == 0) then {_headingGun = _dirVeh + 30 + random 35;};
if (round _randomDir == 1) then {_headingGun = _dirVeh - 30 - random 35;};
};
private _positionGunner = _veh getPos [600,_headingGun];
gunner _veh doWatch _positionGunner;
gunner _veh lookAt _positionGunner;
sleep 5 + random 5;
private _randomReset = random 3;
if (round _randomReset == 0) then {
gunner _veh doWatch objNull;
};
};
};
To this: ```sqf
if (_watcher != gunner _veh) then {
if (count _nearTargets == 0) then {
private _headingGun = _dirVeh;
private _offset = [0,20 +random 15, 20 + random 35, 30 + random 35] select round random 3; // index 1 and 2 are 33% chance each - 0 and 3 are 16.5% chance
_headingGun = [_headingGun - _offset, 0, 0 , _headingGun + _offset] select round random 3; // ~33% chance of moving and ~66% chance it doesn't
private _positionGunner = _veh getPos [600,_headingGun];
gunner _veh doWatch _positionGunner;
gunner _veh lookAt _positionGunner;
sleep 5 + random 5;
private _randomReset = random 3;
if (round _randomReset == 0) then {
gunner _veh doWatch objNull;
};
};
}; ```
And eliminate the _watcher != gunner _veh check too if you can
Just a reminder when you do rounding (instead of floor or ceil) you effectively make first and last number a smaller chance than the numbers 'in-between
private _randomDir = random 3;
if (round _random > 2) then {
if (round _randomDir == 1) then {_headingGun = _dirVeh + 20 + random 15;};
if (round _randomDir == 2) then {_headingGun = _dirVeh - 20 - random 15;};
};
yeah i noticed, i changed it to this already but ill just integrate ur snippet
ok if you want it a higher chance just change this line to: ```sqf
_headingGun = [0, _headingGun - _offset, _headingGun + _offset, 0] select round random 3;
ill have to tweak the numbers a few times anyway so it feels more human
but thanks for helping me ๐ if u hadnt looked at the variables there id still be sitting here clueless
Also, sqf private _randomReset = random 3; to ```sqf
private _randomReset = round random 3;
or it will be a very VERY small chance it ever resets ๐คฃ
im rounding it in the check thankfully haha
ah, just noticed ๐
would ofc be cleaner to stick to one method of doing it lol
Not really sure what you're trying to achieve but note that round random 3 does not give an equal chance of each number from 0 to 3.
If you wanted that then you'd do floor random 4
I almost learned that the hard way big time when making this #arma3_scripting message ๐
I ran a simulation of odds and was like "ayo this shit ain't matching up" and sure enough I was using round instead of floor 
Hey y'all. I am working on a Survival server that is kind of a cross between project zomboid and antistasi. I want to have a US remnants force as blufor, ussr remnants as opfor, bandits/looters as independent, and I want the player faction as civilian but I want them to be hostile to the bandits (independent). Is that possible?
I tried changing civilian side relations but nothing happens
I could very well be mistaken since I don't do anything with AI but I don't think there's any natural natural to allow other sides to target civilian. Pretty sure units dead or in downed states will have civilian player side specifically to avoid being targeted by other AI too I think?
setFriend command can do it
Dialogs in Arma can be a PITA, but you can set your workspace up to make it less painful. First I'd recommend to look into preprocessor defines, and how to use them. For example #define LEFTANCHOR safezoneX - safeZoneW.
Now you can start your params for dialogs with x = LEFTANCHOR; and you'll know instantly where this item is positioned.
setFriend appears to allow units on civ side to shoot at others, but no-one will shoot back at them.
They'll aim sometimes but not fire.
Next step would be to divide the entire screenspace into blocks. One block/grid item could be a percentage of the screen space, or a number of pixels (a bit more difficult to get accurately right). For example:
#define BLOCK_H safezoneH * 0.03
#define BLOCK_W safezoneW * 0.04
Note that the entire screenspace is divided into 0 to 1 values assuming a 4:3 aspect ratio within the original frame (Legacy behaviour from OFP). So you need to account for that. Easiest way is to have it set up in your block/grid defines so you never need to worry about it from here on after. (You might need to make safeZoneW * 0.03 and safeZoneH * 0.04 to flip it around. I'm writing this from memory)
Now you can just go and define anchors for all four corners and then position your elements by "counting" blocks from the left or right, top or bottom.
No worries. I may have my safezone math a bit mixed up. But I hope the concept is clear. ๐
Did you do it both ways? It needs to be done both ways for mutual aggression.
That said, there is a note on the setFriend page that says making civilian hostile will also make the other sides attack empty objects and props. It's from 2007 so may or may not still be true, but worth keeping in mind.
@bleak valley you can only have a single onEachFrame, it won't stack but instead will replace. Recommend you use setVelocityModelSpace
I will, thanks
I was messing around with a script, it uses createVehicle to spawn some missiles, (for ambient purposes), the missiles fly and then hit something, added some velocity, works fine.
BUT: What I want is for the missile to explode mid air, I already tried setDamage 1 but this does not seem to work. Does anyone know how I can accompllish this?
I will check that out once I have the opportunity, thank you! I did not know that function existed.
If you assign the Respawn event handler to the player and they respawn, it will go off, right? If they respawn again, will it go off again?
Yes.
Another thing is that normal civilians don't seem to know how to use guns even if you make them hostile. You have to convert another unit to civ side (joinSilent or drag into group). I would guess that's FSM differences.
The EHs should stay
I don't think so, I made a "Hostile Civilians" module that'd make civilians go pick up guns and they'd join a hostile group to the player (e.g. opfor if player is blufor) and they engaged just fine
Unless joining a different side's group changes their fsms
Does attaching objects to terrain objects have issues?
I'm working on an ace PR to allow attaching explosives to any objects, so you can place explosives on buildings/doors/etc. directly. However placing things on terrain objects causes the explosive to be placed at [0, 0, -200] (ish)
idk if there's a way to resolve that particular attach issue, but failing to resolve it you could just create an attachment object or disable simulation on the explosive (it's not like a building's gonna be moving)
oh, wait, doors, right
nevermind
well first idea still stands ๐
Well its not following doors currently anyway (though that could be cool), but I'm not too fussed about it
Main issue I see is like walls
It might just need some kind of if (isTerrainObject _object) then { _dummy = createVehicle [...]; _thing attachTo [_dummy] }; or something if attachTo just doesn't really work on terrain objects
Yeah trying to attach other things to terrain objects just does nothing
check... i think terrain objects dont have netId?
so you can just check if netid is empty
That was going to be my next question, how do I check if its a terrain object
Running on a fence gives "1:-1895546830"
oof
A vehicle I spawned gives positive value
So maybe terrain objects have negative ids?
could very well be negative values only for terrian objects but i'd do more testing to be sure (maybe ask dedmen)
however, that first number is clientOwner - there is never a client owner of 1 as far as i know (unless that's a SP thing) - run it on a real object and see if it begins with 0 or maybe 2 - terrain objects might just always say client owner 1 as well
Yeah vehicle was "0:164006"
I've never seen 1 either, so maybe 1 is supposed to be for "terrain owned" objects
likely - if you wanna be extra safe just check for both negative and client owner 1, but im pretty sure you can be safe just checking for 1
just test in multiplayer now to see if it changes lmao
Same results in LAN at least, I don't have a dedicated server to test on
Should be fine then
Doubt it makes a distinction between dedicated and user hosted
This makes sense actually, i recall the wiki stating that clientowner 1 was meant to be reserved for local client but shouldnt be used - all terrain objects are local, so netid returns to 1
I imagine you can check if a vehicle is local only that way too - just first value of netid
might just slap that into my own mod as an sqf command or function now lol
isTerrainObject and isLocalOnly
if terrain objects are all negative (and local only vehicles are not) that'd make the distinction possible between the two as well
Spawned a random local only object and it gave "0:0" as netId
fug
wait
@tulip ridge spawn another one, maybe it's always 0:0?
(i could try but you're already testing ๐ )
Yeah it's always 0:0
Two props that I ticked "Local Only" on for, and a vehicle spawned through createSimpleObject
interesting
well, 0:0 for local only vehicles and netId with clientowner 1 + possibly always negative in the second part for terrain objects
truly fascinating
@still forum would you be able to confirm/deny that?
-# It's not 5PM here yet
The steam profile name, in getUserInfo. Is NOT the users profilename that you ask for.
Its the profile name, of the user who's running the game (the server, which doesn't need running steam, thus has no name)
I wonder why that is even in there, seems very confusing
It literally just returns the output of profileNameSteam. Which doesn't have any userID argument, it just returns the local name
The performance of getPlayerUID depends on how many players are on the server.
Cannot
it does
1: stands for static objects, yes.
And in singleplayer, all other objects are 0:
Negative should also be reliable. Its a bitflag to indicate that its a terrain object id
But you shouldn't depend on us not changing the number to unsigned and fixing the negative
local-only objects, have creator id 0, they have null ID's. I'd assume the object id is also null for them?
What covers "all other objects"? Because "normal" objects (placed props, vehicles, etc.) still have 2 as expected
What should be used to check if something is a terrain object?
If you mean getObjectId, it returns 163961
Code is
if (isMultiplayer)
return ComplexFunction()
else
return format(obj.IsStatic ? "1:%i" : "0:%i", obj.GetObjectID());
So in singleplayer, placed objects should all be 0:
not 2:
Oh right I forgot I was still in LAN from testing other parts, I thought I restarted it
Okay yeah it's 1 for statics and 0 for other objects in SP
Drones (UAVs) that are spawned on the server, do they remain local to the server? Or do they change locality when player takes control? ๐ค
Asking for EHs
They change locality
Bummer. All right, thank you
You could look up near terrain objects using nearestTerrainObjects and check if object you are looking at is in the returned array. But this solution may not the best performance wise
Hed have to check at least 60 metres in case of large buildings so yeeeah
60 metres in radius? That's very large buliding
Large but technically possible ๐
Thats the geom size limit
60 ish
Ok ๐
Granted... itd be 30 then since you can be on either side, but still
My isInRock function looks up rocks in somehting like 50 radius, because something like 40 was not enough in some specific spots
Wait, additional question, the EH I'm looking at EpeContactStart is marked as Ga, does that mean locality change does not matter and it will still fire on server side? ๐ค
A lot of those events are marked as GA but don't actually fire unless the object is currently local. I suspect that's one of them.
Yeah entity ehs can be a nightmare sometimes - thats why i made a helper so that i can add an EH and itll just transfer the handler to the new client upon locality change lol
So is there no proper way to check other than doing a nearestTerrainObjects and then check if the object is in the return?
Oh right sorry I misread what you said earlier when scrolling back up
Hey guys, i am trying to accomplish the following: Every player can use a hold action on any other player but not himself. And locality is f-ing with me. I tried to remote Exec it in the initplayerlocal, and that worked but each player had the action themselves, but as soon as i used "-clientOwner" in the targets, it didnt work at all. The i tried to run through allPlayers and add the action for the joining player to each of the other players, and that didnยดt work either.
Anybody got an idea, how to solve that mess?
i'd probably add the action to the player locally on respawn and have the condition only reveal the action when they're looking at a player, that way it doesn't have to be broadcasted at all
well i tried that, but doesnt my client need to know about the action that is attached to this other dude?
Different players have different actions?
no
well actually i guess from the games point of view they are.
It is basically an ace full heal.
well it's two different ways of going about it, one way is adding the action to every player unit (like you're doing) and letting the engine check if the client is looking at one of those player units, and the other way is adding it once to the client's player and have the condition reveal the action anytime they look at a player
Every player should be able to heal every other player, but not himself.
ahhh, i would basically perform an action that is attached to myself instead of the other dude?
Can't perform it on cursorObject?
That might be tough though, as i am checking several conditions for the action to appear, and doing that on a remote target might be more complex.
yeah, actions attached to the current player always have the potential to be visible, so you can take advantage of that to fake an action appearing only when looking at certain objects
that is, assuming your action should be exactly the same across those obects too, e.g. same title, condition, code, etc.
it might help if i post the actual action. iirc there was a way to format it properly?
```sqf
your code
```
[_player, "Medizinisch zu versorgen",
"\A3\Ui_f\data\IGUI\Cfg\HoldActions\holdAction_revive_ca.paa", "\A3\Ui_f\data\IGUI\Cfg\HoldActions\holdAction_revive_ca.paa",
"(alive _target) && (_this distance _target < 4) && ((_target call ace_medical_fnc_isInjured) || (!(_target call ace_medical_fnc_isInStableCondition)))",
"(alive _target) && ((getDir _caller) < ((_caller getDir _target) + 20))&&((getDir _caller) > ((_caller getDir _target) - 20))&&(_caller distance _target < 4)",
{}, {}, {_target call ace_medical_fnc_fullHeal},
{hint "Action interrupted"},
[], 25, 1000, false] remoteExec ["BIS_fnc_holdActionAdd"]
And that in the initpayerlocal works perfectly, except for the fact, that the player has the action themselves (obviously)
Afterwards i tried this:
params ["_player", "_didJIP"];
private _NetworkId = clientOwner;
[_player, "Medizinisch zu versorgen", "\A3\Ui_f\data\IGUI\Cfg\HoldActions\holdAction_revive_ca.paa", "\A3\Ui_f\data\IGUI\Cfg\HoldActions\holdAction_revive_ca.paa", "(alive _target) && (_this distance _target < 4) && ((_target call ace_medical_fnc_isInjured) || (!(_target call ace_medical_fnc_isInStableCondition)))", "(alive _target) && ((getDir _caller) < ((_caller getDir _target) + 20))&&((getDir _caller) > ((_caller getDir _target) - 20))&&(_caller distance _target < 4)", {}, {}, {_target call ace_medical_fnc_fullHeal}, {hint "Action interrupted"} , [], 25, 1000, false] remoteExec ["BIS_fnc_holdActionAdd", -NetworkId]
And that didnt work at ALL
hm yeah, that looks suitable enough to try the one-local-action style
essentially instead of using the _target provided by holdAction, you use cursorObject instead: sqf // onPlayerRespawn.sqf or equivalent: [ player, "My shared action", toString { _this distance cursorObject < 4 && {other condition ...} }, "true", {}, {}, { cursorObject call TGC_fnc_doSomething; }, ... ] call BIS_fnc_holdActionAdd;
because it's attached to player, the action is always visible, and using cursorObject lets you conditionally reveal the action as if it came from that object
AS this is a 25 second action, wouldnยดt that get interrupted if someone ran between us, or my target moved, or i looked a bit around? We are a few pretty noobish guys, and discipline isnยดt our strong side ๐
hmm, yeah it would, a hold action on the object wouldn't interrupt the same way
yeah i could "lift" the restrictions on the interrupt to be more forgiving.
But then they would only have to make sure to point to the correct dude, once the action is finished.
i very much appreciate the help by the way.
iirc for my service vehicle action, i made it store cursorObject in a variable and use it in subsequent calls, so looking away doesn't halt said action
that would be an option.
https://github.com/Warriors-Haven-Gaming/WHFramework/blob/54441c6/WHFramework.Altis/Functions/Service/fn_initServiceAction.sqf sqf private _actionID = [ player, ... toString {[false] call WHF_fnc_canServiceVehicle}, toString {[true] call WHF_fnc_canServiceVehicle}, { if !([true] call WHF_fnc_canServiceVehicle) exitWith {}; // Player looked away WHF_service_target = cursorObject; // started }, {...}, { private _vehicle = WHF_service_target; WHF_service_target = nil; // completed ... }, { WHF_service_target = nil; // interrupted }, ... ] call BIS_fnc_holdActionAdd;
where fn_canServiceVehicle.sqf has the following: sqf if (isNil "WHF_service_target") then { private _params = getCursorObjectParams; _vehicle = _params # 0; _distance = _params # 2; } else { _vehicle = WHF_service_target; _distance = focusOn distance _vehicle; }; ... // actual condition checks here
if you do find the need to create a unique action on every player, you can come back to this cause -clientOwner would have worked too, it just becomes less efficient as number of targets increases, e.g. adding an action to all vehicles on map
Yeah iยดll try both tomorrow. Your approach is definitly interesting and even if i stay with what i already have (mission is thursday therefore time is limited :D) i think i can use it to bring some other ideas of mine to life ๐
I am trying to get the AI to do the briefing animation (https://www.youtube.com/watch?v=1AULdtZ7y4c around a minute in, I am rather sure it is not from a mod) with a trigger.
major setCombatMode "BLUE";
major playMoveNow "CutsceneBriefingSA_StartingLoop";
AI just stands there and does nothing.
Any help greatly appreciated
Random moments of bullshit with the Zero Fucks clan.
Streaming at - http://www.twitch.tv/sovietwomble
Patreon page - https://www.patreon.com/SovietWomble
Twitter - https://twitter.com/SovietWomble
Video made between the 21st July and the 4th August 2016.
Approximately 84 man hours of work.
Sources:
0:27 - The Sims buying theme
5:14 - LOST in...
Try with switch move
major switchMove "CutsceneBriefingSA_StartingLoop";
already tried that
You need to disable ai and use the alt syntax for switchmove
Try.
major switchMove "CutsceneBriefingSA_StartingLoop";
0 spawn
{
sleep 0.5;
major playMove "CutsceneBriefingSA_StartingLoop"";
};
Ai tends to sometimes override certain animations
Alt syntax of switchmove does this basically
ai want do own shit because they dont like do what you want :D
Yep...
oooh, will try that when I get home later
Don't forget your disableAI "ANIM". Makes animation forcing a lot more reliable in general.
Switchmove with alt syntax will work once you do that btw
No need to spawn a script
Also the one prisoner posted willl just make the ai go prone after 0.5s
Not sure thats the intent
aye, will do
I just copy paste from wiki :D
fixed , thanks :D
But anyway, seems ai anim behaviour is not easy to force something else than they are doing
all gucci ๐
nope, I am trying to do that finger pointing animation briefing loop thing
essentially:
major disableAi "ANIM";
major switchMove ["CutsceneBriefingSA_StartingLoop"];
if you really wanna prevent issues do major disableAi "ALL";
since even if you disable anim im sure it can find a way or circumstance to tell you to go get fucked with your demands lol
will try that, funnily enough "[] spawn { major playMove "AmovPercMstpSnonWnonDnon_exerciseKata"; sleep 30; major playMove ""; };" work just fine
yeah it depends on the animation really
some of them lock the AI into a state that it cant escape from, others dont
so disabling ai tends to be mandatory if you want consistency
arma can indeed be janky like that
and playmove wont work if there's no connection iirc, so switchmove alt syntax is more reliable there
(and instantaneous)
gotcha
playMove also waits for the current anim to finish, in your case that's irrelevant but it's good to learn about the differences in commands
so you can actually do playMove animation1 and then immediately playmove animation2 - without adding some kind of wait or suspension
THAT IS if the animation itself has a minimum play time, otherwise animation2 will interrupt animation1
that is also if animation1 doesnt allow animation2 to skip it regardless of minimum play time
welcome to animation state machines ๐
I swear scripting, and programming in general, can be like playing whack a mole or bashing my head against a brick wall lol
it's an exercise in patience and a test of just how far you're willing to push the limits of your sanity
yuuuuuup
i've got around 30-50k lines of code for my mod right now (some of it is c++ and not sqf for an extension but still) - can't say it hasn't been frustrating, but man has it been rewarding
I bet, I have been learning C# as my first language recently and BOY does it feel good when stuff finally works
how does ace medical determine what body part was hit?
Same way every other mod does - handledamage event handler
_selection?
Well it gives you the selection, hit part index, and hitpoint name, plenty of info there (unless im missing the point)
A single hit generates several handleDamage calls.
And ACE attempts to turn all of those calls for a single damage event into one wound on a body part.
Mostly it works :P
They used to add their own hitpoint so that they could tell when the end of a series of HandleDamage calls was.
These days there's an extra param on HandleDamage that does that for you.
Fair. still ๐ it does it differently but ultimately uses the same underlying method
Curious as to why its done that way though
why what's done that way
Consolidating the calls to a single hit
Arma's engine mechanics here are overdetailed. If you hit a guy in the body with a 50cal, you also get some sort of shock damage to the head and arms.
In ace
And the results of that look a bit silly when you turn them individually into damage results on the UI
I see
i see, i looked at the Dammaged eventHandler and that did not work as expected, i will have a look at the HandleDamage one.
just be careful about what you return with that one - if you just need to know the hitpoint, simply return nil (that'll allow the next EH to take over from whichever medical system you use)
Whats the script to cancel the ability for a trigger to activate?
Try yourTrigger setTriggerStatements [false] .
Okie dokes ill give it a shot thanks
If I wanted to know which body was hit. Wouldn't it be enough to check each damaged body part and compare damage they took? It makes sense to me that the most damaged one(in last hit), would be the one that got hit
another fun bug I found while testing around with Agents.
If you have an agent in a vehicle driving down the road and an agent on foot, when they meet eachother instead of drving normal on the road past the agent on foot, the vehicle stops and then carefully truns onto the foot agent and drives over him, making sure he actually ran him over before continuing back on the road
Actually, how it happens (the driver making sure he ran him over and even running him over again if hes not dead) makes it feel like it's intended behaviour xD
you can use the 'Dammaged' Evh where it gives you the hitSelection and everything if that's what you are looking for
https://community.bistudio.com/wiki/Arma_3:_Event_Handlers#Dammaged
Looks like it's very similar to handleDamage
Yeah the both give you the hit selection. HandleDamage gives you a few more informations and is also more persistent
"ContainerOpened" EH doesn't seem to work on corpses. "InventoryOpened" EH is the only option it seems
https://community.bistudio.com/wiki/Arma_3:_Event_Handlers#ContainerOpened
is it possible to detect or prevent client using setVariable with the public flag?
You want exclude x client to get variable?
/ set
You could do all your setvariables on the serverside, which would be more predictable and better for you to handle correctly and detect whenever a variable has been set public without permission (server will always know when and how it has set a variable)
no i want to deny client making public setvariables (like sending to server and other clients)
Aa, okey.
Not really possible
too late for that ๐
You just wanna deny one variable or all setvariable calls?
just one
You could also alter the variable value and extract that added altered value when parsing, the altered value will be an unique identifier for you to know that the server has set it
Well then you could just do a publicvariable event handler and reset it when its changed
If you want to deny it before it reaches to the server, well, you have to get really technical
ya i might make it so the server knows the "right" value for the variable
well that's not possible ๐ it's GOING to reach the target client whether you like it or not, but you can deny it by what i mentioned which is a public variable event handler
you just make it so that the pveh changes it as soon as it receives it
It's possible because I've worked on it, but not within SQF bounds
cant because every client has their own value. the value im talking is player money
well maybe using an extension sure, but i dont think this scenario warrants an extension tbh
My approach to that is I just moved everything to the serverside and let the server handle all of it in a hashmap that does OwnerID: [Money, atmMoney]
also i assume this is for a public server?
thats a good idea
When talking about a life server like in my case, the most valuable resource is time and items
yes possibly
yeah just run it serverside, it's generally a bad idea to run anything that's critical clientside anyway
(i.e store a player stat like money)
not only becuase it can be manipulated but also because if that player crashes there's a chance it wont be saved properly for next time
I had to recode most of altis life and move currency to the damn serverside
lol
but anyway generally you wanna make the server be the authority for systems, whether it's some kind of resource, currency, a mission state variable, or similar - if said variable has to be shared to clients then just public it to that client (only when that client needs it)
non critical stuff you can keep clientside (stuff like preferences or ui things and whatnot)
thats how i have it, server does all the work basically
good
Yes, and don't be afraid of moving things to the server side, there are a BUNCH of packets coming to your server giving info about Position and direction and animation and such. A few packets wont do harm unless the content is really long and you send it repeatedly
^
when people say "dont oversaturate the network" it's largely when mods do something stupid like idk, sharing a 100 element array on each frame to all clients
I've always been afraid but it's worthless, and you can always have headless clients too
an occasional batch of short strings or numbers sent a few times (even per x seconds) is completely fine
And numbers are compressed
im probably going with the hashmap and remexec the money to client
you dont necessarily need to even store the variable or remoteexec, just use a cba event that is called whenever the client needs info from the server
- client clicks button to open store
- client sends message to server to "get money"
- server sends message back with money count
- client takes the number and displays it or whatever
The checks that the client does before substracting or adding money (distance is higher than x meters, check if you have enough money to spend, etc) I keep them in client and server. The real money is on the serverside, I just send the variable to the client for it to display it in the HUD and ALSO to a client sided variable which is only useful for the client sided checks to save me a few packets
that way you're not risking a simple setVariable call changing that either
Yess
thx for the ideas guys, i got it from here ๐
Wow, helping feels amazing
Pretty sure addPublicVariableEventHandler will work as an adequate detection. Not sure if there is any way to really disable broadcast though without disabling related commands entirely.
https://community.bistudio.com/wiki/addPublicVariableEventHandler
most scripters are stupid scriptkiddies who just copy paste someones code so if you have a second random var also keeping track of money with some additional math(that changes often, once a restart is safe so you dont have to deal with the logic of it changing) and run checks against that you catch most of them
believe the standard life-framework already does that sortof (be sure to change it tho lol)
gud stuff
For money I wouldn't recommend broadcasting public. Most Altis Life frameworks handle the money on the clients missionNamespace and make sure it "checks out". Having it on server would be more secure but you're gonna be performing a lot of network calls which it probably isn't worth.
money in server and pub var it to client is what im planning
#arma3_scripting message
is mostly used for a local cached value
can perform basic checks against it but real checks should be against db money
Eh? Youd only network it if money changes, which i imagine isnt too frequent so itd be event based anyway
obviously dont have to perform any serverside additional checks for buying idk a house if their local money cache is < the purchase price
it just gives u a way to not run any server code at all, money cache < purchase price? exit without expensive db money call
I mean you'd also have to check in anytime you display it; unless you intend to cache it every time- where it could also potentially become out of sync. That's a lot of network with a lot of players.
which i imagine isnt too frequent so itd be event based anyway
you get race conditions of people trying to cram purchase/buy events into the same time and bug it that way
I suppose the main reason here would be to keep it secure so keep it only on the server
Fair lol
But hold on dont public variable ehs trigger in order?
Or at least i was told in the ace discord a while back when i asked about cba events
I.e you trigger a few of the same event on the same frame, its received in order of send without overwriting previous sends
I get that. Kinda better though to just prevent it through checks anyway as even if you make it server authoritative- you'd still have to do. Cheaters can remoteExec anything whitelisted within CfgRemoteExec- even the money handler with their own arguments.
multiple calls in the same frame which results in multiple async "buy" functions that do a few checks at different times so could be a few of them pass the "have enough money?" check before its actually reducted from the cache/db
Fair point
normally script is like
check stuff
check money
more checks
bla
bla
bla
take money
do stuff
if multiple calls reach blablabla at the same time you can get some fucked situations
Mm, i see
Which i think is possible? idk i've seen some interesting situations before that don't make sense otherwise
i imagine so if the scheduler is used for the process
never dabbled in life or any of the RP frameworks so im just in the blind here on how they build their stuff
never dabbled in life or any of the RP frameworks so im just in the blind here on how they build their stuff
with lots of spaghetti kept together with
lmao, yeah i can imagine
though with something so big it's probably unavoidable, my own mod has grown immensely over the months and i've built a bunch of underlying systems that are so tightly controlled and interwoven that if one thing breaks i have to dig through 10 separate functions to find the issue 
We've definitely had a few different race conditions with money. I'd like to think we do it pretty well but definitely just "happens". Pretty sure there's still a really rare one in ours I just haven't fixed yet because I'm lazy >_>.
(at least if the one thing is a commonly used feature)
Our mission is also 11 years old so sometimes we also deal with miserable issues from crap we can't be bothered to rework 
yeah i dont wanna be a scheduler hater since i understand how useful it is, but that's partly why i avoid it like the plague, only maybe using it for small mission-only scripts
really no way to avoid it on a life server
there is thousands of script heavy things happening at the same time
Unless somethings changed, pretty sure Arma only runs one sqf script at any given time, and if you use unscheduled you won't be preemptively interrupted
yeah - tho ofc not everything's built unscheduled and you run into issues from lack of modder experience
most mods use the scheduler frequently
Yeah, but then you switch to unscheduled for the critical parts
and that's where the lack of experience part comes in ๐
thats where the spaghetti comes in ๐
Maybe I should finish my guide. Currently 2000 words on what and how to handle concurrency in ARma.
We schedule soooooo much shit- if you can avoid it, definitely can save yourself some pain. Not to say scheduling is inherently bad obviously but race condition yada yada lol
unscheduled's a lot messier to write if you want suspension and waiting until and whatnot, just doing a sleep x or waituntil x is easier
but its more stable
yeah the scheduler is good for holding your hand and just quick tests
and stuff that doesnt matter much
like warning the user of undefined variables too - for beginners that's almost a must
Besides waiting for say, "un-eventable" conditions, what are people using scheduled for? Is it because your scripts look like this?
// Do something
// Wait for something
// Do something more
// Wait for something else
// Do sometihng ....
i used to do that when i was starting off lol
it was such a mess of sleeps and waituntils
I have schduled code checking units in area with couple of seconds sleep between interations
however once i finally finish my mod that i keep feature-creeping stuff into i'll probably give lua coroutines a shot just to spice things up and see how many sqf scripts i can convert to it to make it a bit tidier than using wait-until/sleep functions like from cba
(granted i dont use as many waits or sleeps as i do pure events but still)
More just that a lot of stuff either needs to be ran async or (if I am being candidly honest) enough spaghetti code you kinda just get in the habit of littering anywhere that's already a dump if it's too troublesome to rework
// lockpick car script
// spawn animation script
// spawn progress bar
// spawn hint
// etc
I'm super stoked for script promises in 2.22. I think it's gonna be kinda situational; but I feel like it will be really really nice to have
i mean life framework is like 10k LoC and a different server i've seen was like 100k+ LoC
its hard to create proper code when you have to work with whats basically a slightly polished turd
no offense to the original life-framework, its still impressive
but these projects haven't gotten cleaner/nicer to work with after all the years of code from random devs ๐
a blessing and a curse when you're the only one who works on a project i guess - you have a consistent codebase that's written ... mostly the same, but god help you if you wanna bring someone else on board and have to explain everything because you were too lazy to leave comments ๐ซ
That reminds of recent topic in other_ip_topics... Everybody wants a better Life framework. No-one wants to work or share on it, everybody keeps their "improvements" to themselves, to "grow" their community.
Because for most life servers improvements to code are directly improvements to income, the models just don't match up
Over the years our repo has seen commits equivalent to war crimes by developers who (bless their souls) had no idea what they were doing; or didn't care haha
I've seen life devs directly pipe client side code into their db calls with 0 sanitation 
LMAO
In before the DROP

so happy i only play in my private friends group and dont have to worry about any of that (anti cheating measures at least for example) 
(I want to work on and share it, but not skilled enough to do it alone)
Like it's been put: "I reject your reality and substitute it with my own"
That is commendable. To clear I wasn't targeting anyone, just making a general statement about things on the Life side of Arma.
Not variable value numbers.
I made an optimization which improves sending very large strings.
But large arrays will be bad and lag spike on both sending and receiving side. Plus the network traffic. But traffic itself isn't much of an issue anymore on profiling branch
heck yeah networking improvements!
I really sympathize for smaller servers that don't really have a team. Although I'd like to say I'm pretty well versed in AC stuff, truth be told I really haven't written anything AC for our mission. Been fortunate enough for that to have been Fraali's hat for many years. Truly a cat and mouse game and not an easy one. Seen the dude derive solutions from theory alone, crazy stuff.
sorry, AC?
oh anticheat
sorry, bit slow today
"a lot of network calls"
How often do players really handle their money. Once or twice a minute?
yeah i can imagine anti cheat solutions are incredibly difficult, i mean, big studios are having to resort to the kernel so... yeah, i sympathize with people having to create them with a scripting engine
granted the scope is lesser for sqf cheating as opposed to actual cheats that hijack the game, but still
Is money not solved by:
- The server handles (validates, authorizes) any money transaction, and then regardless of failure or success, inform the client of how much money they have available at the end.
- Upon client join, inform them how much money they have available.
?
Like you only need to inform when the amount changes.... But as Dedmen says, even regular informing of money is not a network problem. The game sends tons of float positions regularly.
The life server I interact with keeps all their code in a single file.
For some unexplained legacy reasons, and because its more "convenient".. apparently.. uh..
they do WHATT?
Hi! I have a quick question, I'm making a 2 player coop mission and I was wondering how to make a trigger start Only when both players are in the trigger zone, thanks in advance!
ah yes i love scrolling through a massive file to find functions 
I am a "module" (code-wise, not the arma editor thing) structuring preference myself. Dislike tons of small function each in their own file, but only having a single is excessive.
I haven't seen it yet. I have been told several times I don't want to see it. I have access now but didn't look into it.
I'll just not have any expectations at all for what I'll find, so I won't be surprised
I'll also be implementing anticheat for money ๐คฃ
one file = faster to load, duh!!
go one step further, inline everything, you save that one params and "call" command invoke ๐
what are functions
i do agree here though - if it's less than 3-5 lines minimum, dont care for makin a function for it
Honestly not sure I could tell you how many a minute- I think it tends to vary. We have casino games and people will spam click the red button for roulette praying for riches so that's probably on the higher end haha. On the lower and probably more average end you're probably right only twice a minute.
We perform "partial syncs" so we don't have to actually update database every time they buy something or lose money. Looking at it now I forgot but it appears we send a remoteExec each time for those syncs so I suppose I probably shouldn't be deterring it from a network standpoint tbf.
maybe their obfuscator doesnt keep track of names across files๐
Even then, you are probably capped to at most 3.6 10 clicks per second.. Not great, not terrible.
But that can be prevented in the UI.
When it comes to architecture, I just love this piece of timeless advice https://gameprogrammingpatterns.com/architecture-performance-and-games.html
But that is where good abstractions can help:
if (["CASINO_ROULETTE", 1] call TAG_fnc_debounce) then {
// Act as if the user presses the button
};
// [TAG, TIMEOUT] Tag_fnc_debounce uses the TAG and previous timeout (or last nil) to either:
// Return true if it has never happened, or more than 1s (in this case) ago, and updates it last timestamp
// Return false otherwise
this is beyond scope for most but i suppose if you really wanna be conscious of arma's own networking thread and settings/limitations, one could use a custom TCP implementation, running on a separate thread, purely for handling these critical aspects of a system ๐คท
but obviously that goes into "hey go make an extension for it"
Yeah, rate limiter like that would be perfect I think
Are we debating the money thing? I dont see any downside to it being hanled by server, donโt think network congestion is a thing here
I may misunderstand you but for anything casino we take the money the moment they hit bet regardless of whether they win or lose so their transaction is locked. Otherwise there is opportunity that they can abuse network / close their game to prevent them from having lost.
I don't see why that would be incompatible with rate limiter
What I just did is purely a user input thing... I simply say that if the user has successfully interacted with the thing (any roulette button), then no such button will actually interact for another 1 second. Basically I prevent you from hitting "bet" too often.
The intended side-effect is to prevent these unnecessary network traffic in this case.
Oh. I misunderstood you, I did not know the term debounce. We do rate limit certain actions and also have cooldowns to prevent things from being spammed.
We actually may or may not have something similar to this :D
most issue i remember were from legacy local cash transacations in the original life framework, bank was bandled fully server side, cash wasnt
so to spawn "cash" all you would need is to figure out the var and the magic offset thing i was talking about before
Altis with extensions??!
intercept
yeah intercept is king
managed to get one of my friends who refused to do arma modding because of sqf - i managed to implement lua through intercept - he is now messing around lol
(he's originally a gmod modder so lua's his thing)
i managed to implement lua through intercept
๐ค https://github.com/intercept/intercept-lua
implemting lua should be a crime
is that so fivem modders can code for arma? ๐
Written by someone smarter than I will ever be in a lifetime ๐ฅฒ
well at least in my case it was gmod modders, so not as bad ๐
god damn i really should've checked the underlying repo for intercept... you've got python and a networking implementation here too
fancy
ah nvm python's not implemented
not that i'd use it
Pythia exists- but haven't tried it
Both of which (and the lua one) so outdated they probably don't work anymore. Because no-one cared to use it
RIP
ngl i dont see much point in using python in arma besides ease of use with python (even though i dont find python particularly easy to read) - seems like you're sacrificingg performance when sqf itself is already easy to learn
but i dont judge
Its in a branch https://github.com/intercept/intercept-python/tree/Draft
ah, i see
(you can tell i dont work with github often, main source control program i used at work was perforce)
I've lost the need for Intercept on more modern projects.
The game has native support for hashmaps and JSON and not double-escaping quotes. That makes passing data (Which used to be the most annoying part) trivial.
Callbacks make passing data back also trivial.
New script commands are nice to have, but only really worth it for projects that add some big API
I mean I think it's kinda just like any extension, the goal isn't to really write SQF inside of it; more just to allow you to interface outside of Arma in another language. Obviously really anything else like C/C++ are gonna be more performant, just honestly haven't ever really played around with making my own extension before; outside some primitive stuff.
i see - i personally have taken on intercept maybe like 6 months ago - at first i did it just to learn, but then i ended up adding a custom filesystem for my unit to just store persistency data and whatnot (without polluting the profilenamespace for example) - then went on to do lua and a bunch of other small things that are probably unnecessary but thought were fun
though for the first one you dont need intercept
but i used it for that anyway since i wanted custom commands ๐คท
true
though probably the most fun i had was linking up llama and made an LLM miller AI insult me through text to speech 
i was gonna use it to mess with my players but due to the vram requirements i decided not to since i dont have a proper gpu on my server box atm
is there any down-side to making global variables, performance or otherwise?
At the top of my head the only language feature left, that would be nice to have (after 22) would be closing over variables (aka closures), but I don't see how to syntactically integrate that without breaking tons of stuff even if the SQF engine could handle it.
Uh.. They'll use memory?
yeah, but i assume the impact is not that big right?
Depends on the size of the content of the variable.
I'd think it doesn't matter
What's your reason for asking, maybe you wanted to ask something different instead?
nah, i'm just making a script to spawn vehicles for testing
if (missionNamespace getVariable ["DEMO_X3_Spawning", false]) exitwith {};
missionNamespace setVariable ["DEMO_X3_Spawning", true, true];
if (isNil "X3_ARRAY") then {X3_ARRAY = [];};
{
deleteVehicle _x;
}foreach X3_ARRAY;
sleep 1.5;
X3_AAT = "3AS_AAT" createVehicle position DEMOX3_AAT;
X3_AAT setDir 240;
X3_DEFO = "3AS_Heavy_AAT_Defoliator_F" createVehicle position DEMOX3_DEFO;
X3_DEFO setDir 208;
X3_GAT = "3AS_GAT" createVehicle position DEMOX3_GAT;
X3_GAT setDir 283;
X3_CRATE = "AmmoCrates_NoInteractive_Large" createVehicle position DEMOX3_CRATE;
X3_CRATE setDir 283;
X3_ARRAY = [X3_CRATE,X3_GAT,X3_DEFO,X3_AAT];
missionNamespace setVariable ["DEMO_X3_Spawning", false, true];
i wanted to make sure there's nothing else that it could affect
i don't want performance to drop
-# too much
If you're not writing something bigger (Framework or mod), it won't matter.
Not sure how often you do that but the larger concern would probably be your createVehicle and public usage with setVariable. Assuming you're not doing that a ton though probably won't make a difference
That's a script that will be called via an AddAction in an object, mostly run server-side X3_Terminal addAction ["<t color='#ffacac'>Spawn Vehicles</t>", {["Demo\X3\SpawnVehicles.sqf"] remoteExec ["execVM", 2]},[],16,false,true,"","",5];
I'm always looking foward to making a more "clean" and performant script
You're probably fine then :)
If you intend for your server to be public and non-passworded I would see this though: #arma3_scripting message
i think arma 3, especially with intercept to resolve any limitations like this, is in a spot where it can just have optimizations be done to it and the modders can continue to make stuff - heck even closures idk we might get, we're getting promises so ๐คท
honestly i'd argue what might be more important is just exposing more engine functionality to sqf or config (may or may not be a tall ask depending on what it is ofc)
good to know, ty
off the top of my head i have tons of niche stuff i'd love to be able to do (for example animation wise), from manually controlling masked bones with offsets to applying IK procedurally, but with how old the game is i dont have high hopes of that happening, however it's not a deal breaker for me, still having a blast modding
(strayed a bit far from wishes for language features at this point but eh ๐ )
Is closure not just, basically a spawned script. That is not triggered by the scheduler but instead only on "call" ?
The next "language feature" if you can call it that is probably REST/Websocket API
Maybe he meant without having to use call/spawn or isnil with privateall but ๐คท
though it'd be pretty unorthodox in a language where whole commands used for everything
By closures I meant like in JS, Lua, C# or C++ lambda so instead of having to acquire from a separately passed context you would have like:
private _someVar = 42;
private _code = {
// ...
// use _someVar . It is bound at { } "definition" time
};
// send _code somewhere and later it will run.
But it would require some special syntax, since SQF uses dynamic scoping and not lexical scoping which I guess is pretty much a requirement for closures.
^ i'd imagine it like creating a code type with someone else's scope tied to it, rather than the caller's scope
in recent time i haven't encountered the need for it, but i do remember having a few functions where i thought i could accept code, but then realized i needed to accept [args, code] as a parameter
hmm, object event handlers would probably be another common use case for closures (though supporting _thisArgs would work too)
I would consider commands to do REST/Websocket as traditionally more "library" utility than "language feature". But I guess in an embedded game scripting language the distinction diminish.
It would be like a c++ lambda capture, where you specify which variables to capture.
At that point it's basically just a tiny hashMapObject. Has the variables in it, and call calls your func
If we had
Args call hashMapObject. You'd be most of the way there
Yeah, I dunno maybe that could work, for capture-by-value. In most languages variables (or rather "objects") are captured by reference
In SQF every value is passed by reference.
HMO is the same
I though types like numbers, bool and strings are passed as values
Not entirely sure I understand how you map would work. In most languages with closures if I did this:
private _someVar = 42;
private _code = {
_someVar = 11;
};
// Send _code off to somewhere that runs it (_code) within the next 5s.
sleep 5;
systemChat str _someVar; // Would expect 11 now
Adding a SQF hashMap in the middle I don't see how this could work.
No
i mean it's dirty but you can technically achieve this by just using a single-element array and then within the "somewhere else" that runs the code, you just change that element in the array, and have the systemchat read str _somevar select 0
Creating the array would put the value of the variable into the array as the slot. You are modifying the array, not the variable. It is not technically the same.
yee it's not the same but it's the same result, just extra steps ๐
not a solution just a workaround ๐คท
But now you have to get the array (its variable) "into" the "code" (closure).
Local variables don't work like that. If you definel local variable and global function in the same file, and then call that function from some other file, then local variable won't be defined
SQF language just doesn't do that yeah.
fwiw python makes that type of reassignment explicitly opt-in with global/nonlocal: py def make_callback(): n = 0 def callback(): nonlocal n print(n) n += 1 return callback otherwise you'd get an UnboundLocalError for attempting to reassign without declaring its scope (if there were no assignment though, it'd traverse up the scope like normal)
Yes, was about to mention your edit.
The variable is still captured without nonlocal
Anyway, I was just wish listing in terms of "language features". (Proper) closures is a non-trivial thing to add to a language correctly.
With our "pseudo classes" and upcoming "promises" the language has made great strides, not to mention what I class as "library" improvements like JSON etc.
But pretty awesome if REST (guess that means HTTP 1.1, or maybe "REST"because it is restricted somehow?) + websockets is incoming. Now just need sqlite3 integration too, and I probably won't need extensions ๐
selectWeaponMode doesn't exist....
you want
unit selectWeapon [weapon, muzzle, firemode]
as the wiki says if you eventually wanna switch weapon you should use the action instead
selectWeapon selects firemode
First 3 elements returned by weaponState are what you need for selectWeapon
But thats gotta be on a modpack for client
they dont actually have a custom networking implementation for clients doing sensitive stuff, just handling most of that serverside stuff with intercept
Can I somehow add damage to vehicle, so I can trigger texture on windshield and hull to look-like it was shot by bullets?
The windshield should have a hit point to setHitPointDamage on (found in the config viewer?).
Look for it in returned array, it may be called something like hitglass
https://community.bistudio.com/wiki/getAllHitPointsDamage
_vehicle setHitPointDamage [ "hitbody", 1 ];
Something like that, but most likely glass isn't part of "hitbody"
You also gonna need certain level of damage
Buildings switch to damaged texture around 0.5 damage, if I remember correctly
Oh I may have misread something
Thought they did TCP and all of that
Why intercept tho?
question for them. i just know they use it
We have a bunch of custom commands and behaviors that are dependent on some intercept things
Database communication, http, json before it was implemented and a few more things
We ran into issues years ago with server performance and spinpolling with extdb3 callbacks, so one of our developers made it for us
Managed to make an objective where ya must identify 3 vehicles in a dense area to unlock a airstrike. I would like to make it so you need to point a laser to activate the trigger. Is there something I can add to CursorObject == to have this be the case?
Yes
Or maybe raytracing
params ["_artilleryPiece","_positionTarget",["_targetsize",250],["_rounds",8]];
if (_artilleryPiece == objNull) exitWith {};
_Rhs252 = ["RHS_M252_WD","RHS_M252_D","RHS_M252_USMC_D","RHS_M252_USMC_WD"];
_RhsPodnos = ["hs_2b14_82mm_vdv","hs_2b14_82mm_msv","hs_2b14_82mm_vmf"];
_RhsD30 = ["rhs_D30_vmf","rhs_D30_vdv","rhs_D30_msv","rhsgref_ins_d30","rhsgref_g_d30","rhsgref_nat_d30","rhsgref_reg_d30"];
_Rhs2s1 = ["rhs_2s1_tv","rhsgref_cdf_b_2s1","rhsgref_ins_g_2s1","rhsgref_cdf_2s1"];
_RhsM119 = ["RHS_M119_WD","RHS_M119_D"];
_RhsM109A6 = ["rhsusf_m109d_usarmy", "rhsusf_m109wd_usarmy"];
_Rhs2S3 = ["rhs_2s3_tv"];
_ammoType = currentMagazine _artilleryPiece;
if ( _artilleryPiece in _Rhs252) then {_ammoType = "rhs_12Rnd_m821_HE"; _delay = random [1,1,2];} else {
if ( _artilleryPiece in _RhsPodnos) then {_ammoType = "rhs_mag_3vo18_10"; _delay = random [1,1,2];} else {
if ( _artilleryPiece in _RhsD30) then {_ammoType = "rhs_mag_3of56_10"; _delay = random [8,8,9]; } else {
if ( _artilleryPiece in _RhsM119) then {_ammoType = "rhs_mag_m1_he_12"; _delay = random [8,8,9];} else {
if ( _artilleryPiece in _Rhs2s1) then {_ammoType = "rhs_mag_3of56_35"; _delay = random [8,8,9]; } else {
if ( _artilleryPiece in _RhsM109A6) then {_ammoType = "rhs_mag_155mm_795_28"; _delay = random [8,8,9]; }else {
if ( _artilleryPiece in _Rhs2S3) then {_ammoType = "rhs_mag_HE_2a33"; _delay = random [8,8,9];}
;};};};};};};
_trg = createTrigger ["EmptyDetector", _positionTarget];
_trg setTriggerArea [_targetsize, _targetsize, 0, false];
for "_i" from 1 to _rounds do {
_artilleryPiece setVehicleAmmo 1;
_positionTarget = _trg call BIS_fnc_randomPosTrigger;
_artilleryPiece doArtilleryFire [_positionTarget, _ammoType, 1];
sleep _delay;
};
deletevehicle _trg;
does anyone know why this guys, tested with RHS mortars, will only shoot once atthe target?
[gun1,position player,100,6] call AWP_fnc_ArtilleryDoFire;
calling it like this
This is the trigger I want to make activate when having pointed a laser at the object.
Are you using ACE? if so, check if the mortar ammunition handling is enabled.
no ACE, no
your sleep delay is set to 0, so maybe the loop ran too quickly before the arty piece could load its next round?
it shouldnt need a sleep at all - but even if i remove the sleep, it wont work
the for loop doesnt seem to work
for that case you will need a sleep
i set it to 0 for testing purposes - but even if its _delay = random [8,8,9] it wont work...
but it worked before, im not sure why it wont now
how long would it take between firing each shell from that RHS mortar? like if you were to use it manually
I have a question ? Did you check what was the results returned by the function "BIS_fnc_randomPosTrigger" ?
i never used it and i don't use trigger either so that's why i'm asking
no - but it worked before, and i used this setup already
but i can let it hint the results ill check
I always get the gun reload time (from configs) and add a delay
yeah, at least to why they are shooting at the same position
yeah speaking of which, that is an odd use for a trigger when it could be calling BIS_fnc_randomPos directly, or passing an area array instead (apparently the trigger function supports that? that's wacky)
it just hints one position - it seems the loop wont execute
do i have to use spawn to be able to suspend a function?
normally yes
but it depends where your script is
then this could be the problem
looks like that is the problem
now you said "it just hints one position - it seems the loop wont execute"
but what if the position is 8 times the same ?
because you won't see any difference or if the sleep is instant, you will only see the last one because it is too fast
the _delay should make it sleep before it hints
what i usually do is making an array and pushing the string directly into it so you can see how much time it was executed
8 times the same POS is incredibly unlikely - but ill try using spawn
also, I recommend that you private your local variables
and maybe use switch to replace those if
For what it's worth, RHS mortars absolutely need the sleep between shots, and it needs to be long enough. Vanilla mortars you can spam. Not sure why there's a difference.
There's no way that I know of to hold an artillery piece at the correct elevation so you need to account for that as well as the reload time.
ikd either but i noticed it wouldnt work properly without so i added the delay
the values should be tested
cause i had the issue that it didnt have enough time to turn on the target again, if its over a larger area
And any traverse that they need to do, but you can at least setDir the thing in the right direction.
did some testing with a simplified version, the AI wouldn't fire the full barrage if they're given multiple fire orders at the same time:
_mortar spawn {
sleep 2;
for "_i" from 1 to 3 do {
_pos = [target, 50] call BIS_fnc_randomPosTrigger;
_this doArtilleryFire [_pos, currentMagazine _this, 1];
systemChat str [name gunner _this, _pos, _i];
};
};```
would players not notice the gun snapping to the direction?
or is there a way to make it smoother?
yeah that's what we do.
in comparison with a waitUntil {unitReady _this}: sqf _mortar spawn { sleep 2; for "_i" from 1 to 3 do { _pos = [target, 50] call BIS_fnc_randomPosTrigger; _this doArtilleryFire [_pos, currentMagazine _this, 1]; systemChat str [name gunner _this, _pos, _i]; waitUntil {unitReady _this}; }; };
(excuse me for filling the chat)
Also I poll the weapon reload values after it's fired instead of sleeping now. Code is nasty but it's reliable.
okay the spawn seems to be the problem - it didnt throw the error "suspending not allowed" tho...
I would be surprised if unitReady was useful for that.
it is indeed one of the comments on that page:
https://community.bistudio.com/wiki/doArtilleryFire
After using this command, use unitReady to see if the unit is done firing all rounds:
sqf _mortar doArtilleryFire [[3000, 120, 1000], "8Rnd_82mm_Mo_shells", 3]; waitUntil {sleep 1; unitReady _mortar}; // Note: make sure you run this in scheduled environment _mortar sideChat "Rounds fired!";
yeah that's what i wanted to say, you will generally get an error if you are using a sleep in the wrong place
That doesn't mean they're ready to fire the next one.
didnt get it tho.. only when i changed sleep _delay to sleep 5
but it works now
even with sleep _delay
good point, ill check if they can reload a whole magazine and continue it
The last video is a vanilla mortar though. Those work fine anyway.
do we know the setting of ArmA 4 already? If Vanilla wasnt so much weird "futuristic" stuff id use vanilla assets alot more lol
waitUntil unitReady did indeed work with 16 rounds, the AI fired all of them despite receiving the 9th fire order during their reload
thats cool to know - but did the spread work? i had that problem with the RHS mortars that if i didnt delay it theyd not cover the target area, instead just pounding away at the first position
does your mortar come from RHSAFRF or USAF? i happen to have those two installed
welp sure enough, soon as i throw down all the pieces and a vanilla mortar, none of them are firing now :)
oh, blufor setFriend [opfor, 1] was the cause...
this is the fate of anyone touching this game
is it possible to look at scripts inside scenarios you download?
as in get the source code? i think there are ways to unpack the pbo files
Change the file extension to .pbo (scenarios from workshop are just binned but doing that works) and use pbo manager to unpack
where can i find the pbo manager?
i think they are 3rd party tools
https://pbo-manager-v-1-4.software.informer.com/1.4b/
this link is provided by nitrado (https://server.nitrado.net/de-DE/guides/pbo-dateien-oeffnen-oder-bearbeiten-de) but idk if thats the right one
thanks
Got mine from the moddb one, feels safer
yall should probably try out the open source pboman3, if anything because it's newer and looks a bit nicer
https://github.com/winseros/pboman3
true, if u are suspicious of any downloads running them through virus total wouldnt hurt
Ah, good to know
@granite sky sqf this spawn { sleep 2; if (isNull gunner _this) exitWith {}; _name = configOf _this call BIS_fnc_displayName; for "_i" from 1 to 16 do { _pos = [target, 50] call BIS_fnc_randomPosTrigger; _this doArtilleryFire [_pos, currentMagazine _this, 1]; systemChat format ["%1 firing round %2/16", _name, _i]; waitUntil {unitReady _this}; }; systemChat format ["%1 rounds complete", _name]; };
Granted i dont really use it for anything but extraction myself but still
If that works then I'm using it everywhere.
just had to finagle with the dispersion and target positions to make sure they were all in range, otherwise they'd ignore the orders and quickly skip to the next iteration
also running on perf branch so that may differ in stable
rah, i noticed the podnos and m252 skipped several orders anyway ๐
maybe 100m distance + 50m dispersion was a bit too close
Thanks armai
Remember, ai commands are polite pleads for cooperation, not orders ๐
i was thinking about tying the sleep duration to the size of the target area + the reload time
for RHS that is
cause idk if my setup will still work if the target area is like 800m
though thatd be a very large area to shoot at
you don't have to dynamically set a sleep duration, the tests above were with waitUntil {unitReady _this}; which sleeps until the AI completes the artillery order, whether by firing the volley, running out of ammo, or being out of range
but why did they skip some on ur setup?
speaking of which, i moved my target out to 600m + 100m dispersion and now the M252 fired much more consistently, though turned out it only had 12 rounds so it couldn't complete the 16 round order anyway
being out of range + running out of ammo
both
M252 only had 12 shells, and some of the positions around the target were apparently within its minimum range
spamming setAmmo 1 should fix the ammo problem right=
i'd add a Fired event handler to rearm it when it's actually fired, but otherwise sure
does it make a big difference? cause its rearming currently on every loop before it fires
oh you mean once per iteration, ya that should be fine
Anybody have any idea what this marker is called. I have no idea what it is and im trying to find out where its coming from.
Little marker under the car, tracks cursor movement.
What? Do you mean little V? It's an Engine feature to tell wheel direction. It's not a script topic anyways
Uh okay thanks. I guess I've never noticed it. Thanks for informing me, but in my case, I didn't know. Because I just removed a marker script, that was marking the vehicle with the name of the vehicle, and I thought it was related. ๐
For reference ๐
It's been two decades since it was introduced, I guess. Not sure if you can remove it
Yeah i've never noticed it. Thank you for clarifying
I play first person only so its not as noticeable. Probably just never noticed it, but caught my eye while troubleshooting in third person
If you mostly drive with the keyboard then you probably won't see it much. It disappears when freelook is on.
Ahh, just realized the hud hider mod I use has been hiding it.
(Edit, simply steering with keyboard removed it too. ๐ Duh)
For sector control, is there a way to add additional requirements to capture a sector?
I tested an additional condition in the trigger's condition field but it was still captured even when it returned false
I have a modified version of it, for an AAS game style, see if you find anything useful
https://github.com/PiG13BR/Arma-3/tree/main/AAS_PIG.VR
Looking at the mission now, but how did you make it so that you have to capture the previous area before you can capture the next one?
Oh I see, you're updating the trigger conditions each time a sector's captured
_emptyHandle = spawn "HandleName";
_emptyHandle continueWith [{systemChat str [_this, _thisArgs]}, "World"];
_emptyHandle terminate "Hello";
Yeah, it's been a while, but iirc it works by getting the trigger created by the sector module function and messing with it, but I think you're already got the idea
so i guess you cant do foreach on hashmap that you use deleteAt with. i tried but it didnt loop properly
I did ```_hmtoiter = (uiNamespace getVariable "floatingTexts") apply { [_x,_y] };
well doesnt matter which foreach you use at that point
Great stuff, will make a huge difference
What was the code?
ugh long
I think it should be possible. Maybe not when looping hashmap directly. But at least if you loop through array returned by keys.
ya keys probably works
because it should be copy...
if keys would get reference to the HM it wouldnt work because it would change
so you need a copy
keys returns a read only array copy
read only.. didnt know SQF can have those
Same here. All I know is final functions and hashmaps
Even if keys array was changing as you delete pairs from hashmap, then you would just loop it in reverse order
true
Now worried that I'm doing deleteAt on a keys array somewhere
but i meant keys cannot be reference to anything in the hashmap
Aren't some types like numbers or strings passed as values? Which would mean they can't possibly be reference anyway
youd see the script error
no
Numbers and strings are passed as references? Is there way to prove that?
If they're also copied by reference, then I guess if you filled some enormous arrays with a var set to a number it'd use less RAM than if you filled them to random numbers.
There are no commands that change numbers or strings in-place so otherwise it doesn't matter from a practical perspective.
I'm not even sure if they're copied by reference though.
I wanted to test it, but I as you say there are no commands, which would edit strings or numbers. I wanted to try insert, which edits arrays and returns nothing, but for strings it returns new one without editing old one.
isEqualRef
private _var = 1;
private _arr = [_var,_var];
private _arr2 = [1,1];
[_arr#0 isEqualRef _arr#1, _arr2#0 isEqualRef _arr2#1];
=> [true, false]
Until now I thought some types were passed as values(for very long time). Most likely because there no commands to edit some of these types, so it's not apparent if it's passed by reference or not
Passing something by value, means allocating a new script vvalue. That wastes memory and time
Which types are truly value types then?
There aren't any.
I have moved money to server and in order to fix this I just implemented a "server version" for each thing. For example: a job that consists of delivering packages, I check from the server if you deliver the package and all of that:
- Server generates point and sends it to client
- Client calls the function everytime the client is on the point
- Server checks if client is on the point and if it is, it rewards player
Then, I make a client-sided loop that will check if player is teleporting, and it's very important for it to not be terminated in ANY way even by cheats, This way, not even cheaters can do anything about it
And this race condition you are talking about is what I'm most worried about, I really need a mutex or smth
Should only be possible if you have waits in there that allow the scheduler to run the other script?(or running too long) i think? its been a while
I do remoteExecCall for all of my serversided money things
I kinda not understand the concept of scheduler yet
Does the scheduler mean it's not ran on the main thread?
(P.S: Yes I've read the wiki a couple of times but I think It's just a language barrier at this point)
basically a pool/queue of scripts and the scheduler goes through and runs them 1 by 1
with some caveats/conditions described on the wiki (max runtime, what script it decides to run next etc)
1: Basically only one script runs a time, thus only one of the environments is really active at any time.
2: In the unscheduled environment you cannot suspend. The script runs to completion in one go (or errors out, etc).
3: Scripts in the scheduled environment can be suspend if they take too long (3 ms). Basically it stops after some statement, and the scheduler is the one that decides when to rerun. Basically it just runs the one that hasn't run for longest.
So anything that runs in unscheduled does not need mutual exclusion because:
- Only one script runs at a time
- Scripts in unscheduled run to completion (or "crash"), so nothing interferes
What I've just read on the wiki this time around is that, unscheduled code runs instantly and order is ensured (Func A executes completely before Func B executes)
Which, for my money thing, must be great because there are no race conditions because remoteexeccall will start it unscheduled on server and server will run it all without interruptions before running the next one, right? So, even if you spam as quick as possible, no race conditions
The thing is, code runs "instantly" when unscheduled, but
Shit nevermind
What I was gonna say is, new code will run instantly only if the current code being executed unscheduled is efficient and performs well, right?
To be pedantic, code doesn't run "instantly", it still takes time. But code runs without being interrupted.
Say I have a loop that goes from 0 to 65553 or whatever running unscheduled and I also call some code RIGHT NOW, does that code that I just called get ran RIGHT NOW or does the loop finish before code is executed?
The only code that can "call something right now" is your script, running in unscheduled, thus whatever you call runs in the same manner.
Well, or maybe the client does RemoteExecCall
My scenario is remoteexeccall to server
See rule #1 again... There is at any given time only one script running
There is no true parallism in the SQF scripting engine (at least user visible)
if your loop is running from 0 to whatever in unscheduled sqf, sqf is sortof "frozen" until it finishes
no other sqf will run at the same time
It's not like the remoteExecCall arrives from a client and is immediately processed.
Inefficient unscheduled code can for sure block the game. There are very few exceptions to this, like
A while-do loop is limited to (hard-coded) 10,000 iterations in a non-scheduled environment.
Weirdest cases are where you trigger an event handler by running a command.
its also why you dont wanna be doing any database operations in unscheduled code, basically anything that takes significant time you want scheduled
Sounds like your delivery system is great. Truth be told not sure we are that diligent in our checks for individual actions (at least older stuff) like that since we rely on AC to catch it (which isn't great, but is what it is- 12yo mission lol).
Not sure if you're familiar with "heartbeats" but if not I think you will really like and appreciate this info. From 2016 but seems to explain things pretty good on how to secure your mission from cheaters being able to modify memory in your mission undetected. Anyway FWIW ๐
Once I freezed my game just by running couple of lines of code in unscheduled. I was looping through array, while appending it on each iteration ๐คฃ
Oh wow https://community.bistudio.com/wiki/remoteExecCall will take place in unscheduled environment and does not mean it will happen right away. I thought it said it would happen right away ๐
I've seen a cheat that is able to dump a thread, hence why a heartbeat could be replicated ๐ซ
Well, no "hence" because it even happens with BattlEye, some people can emulate the BE heartbeats
But, script kiddies wont get into memory manipulation for a single server, so I'm good with doing anything, but worried about SQF code execution and Killing / Dumping threads. Or I may just move TP detection to the damn serverside and make some calculations with the direction and speed vectors to detect if it's lag or TP
You should always assume all client side data is garbage, BUT heartbeats etc make it way more complicated for a scripter to stay hidden
keep in mind they have to figure out the heartbeat system for every single server that all implement it diffrently
Yeah, I mean you just gotta be able to prevent that- which is much easier said then done.
Although I read most of the guide before sending it- I do think maybe there are a few things they could've worded differently and improved upon. Commands like compileFinal are not surefire and cheaters have modified those. Not sure about sealed maps- but I imagine with a little bit of work nothing would prevent them from modifying those either.
Just really a:
- How do I prevent them from manipulating things undetected
- How do I prevent them from killing detections
- How do I prevent them from spoofing them
and you can also have it change based on other factors
Gotchu
I'm having some ideas now, though, eventually, this serversided approach may be better for 100% accuracy
@radiant lark This is the first draft of a section in a booklet I am writing. It was asciidoc but I ran it through pandoc so I could put it on mediawiki (that is why the formatting is "weird").. It may clarify somethings about the environments or not: https://community.bistudio.com/wiki/User:Muzzleflash
Sure Lou would not be impressed with my formatting, but it is my page.
The guide is really useful, and now that I've read it, I still think any heartbeat could be emulated BUT the timing of those heartbeats is something to really look for. I now consider timing an important factor to distinguish a real heartbeat from an emulated one, because it surely has to alter somehow
I've also thought about making a watchdog thread over the heartbeat one
Taking a look now, tysm
i do not understand the variable always gives "any" for the state even tho i set it
_x is not defined inside the handling code itself
(_this select 0) will give you the unit the event handler is attached to. Use that instead of _x inside the handling code.
that does work, thanks
_x addEventHandler ["HandleDamage", {
params ["_unit", "_selection"];
private _state = _unit getVariable ["dam_state", "balls"];
hint format ["selection: %1 state: %2", _selection, _state];
_unit setVariable ["dam_state", _selection];
}
is the private necessary?
no, not here.
Now that I am reading this, is it too common for the engine to suspend a script because of the 3ms thing? If it's not too common, maybe the info about which scripts have been suspended could be useful for developers to make their code better
Not entirely sure what you are asking. A suspended script is one not running. Scripts in unscheduled don't really count since they run to completion as soon as they start. So the suspended scripts is ALL (scheduled-environment) scripts that is not the one running right now.
always welcome
By the way, the isNil trick is really great, thanks for making me find this out!
The engine will suspend scripts running on the scheduler when they exceed 3ms execution time (I think?)
But they can also be suspended because the scheduler has decided to suspend the script, perhaps because it is taking too long and the scheduler donโt want risk freezing the game and dropping the fps. By suspending the script, the scheduler can run other code, or stop and let the engine complete the game frame, and it will resume the the script in a later frame.
If that ^^ happens too frequently, it's alright, but if it doesn't, it'd be great to know which scripts have been suspended because of that
I don't think the engine offers the ability to determine that. What you can do for true positive, is use diag_frameNo at the very beginning, and very end of your script. If they differ, then the script has run across multiple frames and thus must have been suspended. But that might not be because it took up 3ms that frame.
If I run this in debug editor and monitor Frames~~ I typically get a value between 6 and 12, which indicate each script was suspended 3-6 times~~:
Counter = 0;
Frames = 0;
private _script = {
private _lastFrame = diag_frameno;
for "_i" from 1 to 100000 do {
private _curFrame = diag_frameno;
if (_curFrame != _lastFrame) then {
_lastFrame = _curFrame;
isNil {Frames = Frames + 1;};
};
private _a = Counter;
_a = _a + 1;
Counter = _a;
};
};
[] spawn _script;
[] spawn _script;
That's great
Well, if your script being suspended by engine is a bad signal, maybe we could have a command be added to the game to determine which scripts get suspended because they take >3ms that frame
I reused the diag_frameno instead of _lastframe in the condition. The numbers are much higher and consistent around 67 suspensions, or 33 each.
As I understand it is a total frame time. So you can't attribute cost like that... Consider this frame:
- Scheduler picks script A, runs for 2.7ms and terminates, or waitUntils, etc...
- Scheduler picks script B now, but stops if after 0.3ms.
Oh, doesnt it run script B on next frame?
Wow
It might. I don't know the details. I think it will pick a script that hasn't run in a longer while, but not sure.
https://community.bistudio.com/wiki/diag_activeScripts
Found that at the bottom of the Scheduler page
diag_activeSQFScripts
Well it's just a number isn't it?
oh the bottom one not
By the way, thread id is only set by scriptname right?
I guess, not really used it. But not really an ID either when multiple can set same name.
Damn
Holy damn!
Interesting the debug editor seems to greatly affect the scheduling. Inside the debug editor the last script is run again. Where-as with it closed there is perfect rotation
I wanted to use this function i found on the "switchMove" wiki page.
I tried just copying it into it's own .sqf however i got a "Undefined variable in expression" error
I am not sure if it is a user error (most likely) or if something has changed that breaks the code
Which variable is undefined?
Oh that's the function itself, you need to swap the tag placeholder to whatever tag your mod/mission uses
i am not sure what you mean by tag my mission uses
Like your CfgFunctions in description.ext, or however you define the function
It's good practice to pick a unique short tag (prefix) for any global variables and functions used in your mission. It helps to identify them as yours, and makes the names more unique to avoid conflicts with other scripts.
CfgFunctions functions require a tag as part of their autogenerated naming structure.
i see, i am basically just playing around with scripts for now but i will set up the description.ext
is there a way to make code happen the moment a while loop finishes?
Yeah, call it after loop
does anyone know why i get spam like this in the log? Warning: Cannot evaluate '9 * UI_GRID_H' the error file and line does not make any sense and the only thing i can think of for the reason is ctrlCreate. but thats just a guess
Some UI config did not resolve a preprocessor definition. That UI_GRID_H is not a variable, it fails
but why did it start failing now and not before. i made new script file that uses ctrlCreate?
How does one escape % in formatted string again?
its weird i have seperate mission where i test this and that mission has no dialog definitions but everything is created via ctrlCreate and i still get the warning msg
Ezcoo I just do format ["100%1","%"]; but thats probably not the best ๐
Wasn't there %% added as escape?
Arma 2 though (forgot to mention it)
I've tried \% and %% with no luck, so I guess I'll just use GenCoder's method
probably not in stable yet
"test %% string" didnt work ๐
2.20
hmm didnt work in console
Example says 2.18
// Since Arma 3 v2.18 two consecutive percent symbols will be formatted to a single percent symbol in the final string (%% -> %)
Lawyered
who's the idiot writing doc here
. . . @cosmic lichen ๐คฃ (sorry!) https://community.bistudio.com/wiki?title=format&diff=next&oldid=370166
It is not a string thing, but a format thing.
ah yes, of course ๐
format ["Set phasers to 100%% Mr. %1", "Worf"] -> "Set phasers to 100% Mr. Worf"
. . . @still forum , both changes arrived at the same time, right? 2.18?
What does the 2.18 changelog say?
good call, https://dev.arma3.com/post/spotrep-00115
Tweaked: format script command is no longer limited to 8191 characters (now 8388608)
page fixed, thanks y'all
Who's the idiot now?๐คฃ
us both! that's why we work so well together ๐
Note: Arma 2: OA! Why does this work ```sqf
player addAction ["<t color='#ff0000'>HEAVY ATTACK MODE</t>","Common\Functions\Common_AttackWaveActivate.sqf", (sideJoined) call GetSideSupply];
```sqf
if (!isNull _MHQ) then {
_MHQ addAction ["<t color='#ff6a00'>HEAVY ATTACK MODE</t>","Common\Functions\Common_AttackWaveActivate.sqf", (sideJoined) call GetSideSupply, 1.5, false, false, "", (((sideJoined) Call GetSideSupply) >= 25000)];
};
It gives the following error: ```
Error in expression <r) then {
if (!isNull _MHQ) then {
_MHQ addAction ["<t color='#ff6a00'>HEAVY ATT>
Error position: <addAction ["<t color='#ff6a00'>HEAVY ATT>
Error Type Bool, expected String
I don't understand the error
A2OA addAction:
object addAction [title, script, arguments, prio, showWindow, hideOnUse, shortcut, condition, positionInModel, radius, radiusView, showIn3D, available, textDefault, textToolTip]
A2OA != A3 addAction
Oh my, I didn't notice the tab ๐
i think its this line: (((sideJoined) Call GetSideSupply) >= 25000) that gives you boolean when you need a string for the condition
Thanks! ๐ป
i figured out the log spam, it seems you need to properly include all classes and grid definitions for the warnings to go away. not sure why because the code worked without them
If the definitions are not present then these macros will never have a value
yep
It can't work without them.
You can see that in the config viewer. If any of the macros were not resolved you know some defines are missing. Same for compiled scripts
yeah had a bit of hassle when some of the classes came from another mod ๐
now all dependencies are properly included, it should be good now
Someone mind sanity checking me here, I wrote this at like 1am and I think there's a much better way to do this, but also maybe not?
private _door = (_doorSelection splitString "_") select -1; // "door_1a" -> "1a" or "door_1" -> "1"
if (isNil "_door") exitWith {};
private _digits = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"];
_door = (_door splitString "") select { _x in _digits }; // Only keep the door number
_door = parseNumber (_door joinString ""); // Recombine, since it could be double digits
I could immediately split it by every character and filter, I just can't check if it'd be faster than the current code
Regex?
just regexReplace, to extract the number. Can do all this (besides the parseNumber at end) in one command
The regex will be in cache, so probably fast enough
Forgot about regex tbh, that seems a lot more reasonable
So I'd need to match 1-2 digits + followed by a letter
I don't know if there's a limit on number of doors, but I doubt anything's getting close to 100
This seems to be working, but I don't use regex too much h
https://regex101.com/r/J5lyof/1
Is it only at most one letter at the end?
Is the implementation for Arma a particular "dialect"? Like C++ based regex, or re2, pcre?
std::regex
Using default EcmaScript-like grammar https://en.cppreference.com/w/cpp/regex/ecmascript.html ?
"door_117A" regexReplace [".*_(\d+)\w{0,1}", "$1"] -> 117
Unless a single door has more than 26 parts, no
That looks smart, I only care about the number though if that matters misread
Question: Anyone know a way to make role specific ace arsenals?
Not directly, but you can add/Remove items yourself based on a player's role (however you want to determine that)
Damn how broken scripted infantry transportations are atm on dedicated servers. It is like every other combination you try either differs from SP or doesn't work at all.
ooh, many thanks, will try that
Is there a way to get the positions of these elevation markers or is that impossible?
I got this working and it works perfectly.
I am only using this to play 'injured' animations on ai and i came across 2 issues.
Firstly as this simply checks the current animation doesn't equal the animation it is to loop meaning if certain animations such as ace dragging play it will still override them. I could compare the animation to all animations i do/do not want it to override however I am curious if there is a simpler way.
Secondly whenever the unit dies the function is called without an animation which gets rid of the EventHandler and sets the animation to be nothing, this causes the unit to stand up straight and then ragdoll, how do i make it ragdoll from the point in the animation it was?
You could just exit the eh if the unit is dead
is side (group _unit) the workaround to a playerSide that takes a global argument?
side player won't work if player is dead, playerSide will
shit I should read wiki more frequently
Never knew playerSide was a thing / when you'd want it specifically, but side group unit is also to avoid issues where a unit's side changes from engine
E.g. side unit will be sideEnemy if you kill a bunch of a friendly units
Don't heed this as definitive but think you can have situation where a player join independent slot (lobby), but is put into a "Blufor class unit", but member of a Opfor group, and then, side player, side group player, and playerSide might all be different.
I had figured out a good way to properly close out of the animation, however I am not sure about the first part of the message
What is a foolproof way of creating prop corpses that will not be deleted in a (dedicated) server?
No pose/animation required.
In your event handler, you could add if (!alive _unit) exitWith {}; which wouldn't play an animation and (should) let the unit ragdoll correctly
at some point ... i will create a dialog creator tool for that shit ...
but ye ...
thats still "WIP"
somewhere after the 1.0 OOS and XMS2 release ๐
so "far far far far far far <one hour later> far away future"
is there a way to stop a player rejoining a locked server after they leave?
If I'm getting "Scripting function 'bis_fnc_call' is not allowed to be remotely executed", I need to do this right?: https://community.bistudio.com/wiki/CfgRemoteExec
Testing showed that EPEContactStart actually fires on both Client and Server sides if both subscribed to this EH even after locality has changed. So if event is marked as Ga it's worth a try to test it
(and for me that means unwinding and removing complicated code of client side subscribing ๐ฅณ eeey I guess)
Remains collector may not be useful
createSimpleObject might be
Why to do reload for him though?
Players can reload by themself
I just use mod which allows me to repack my magazines
I can't add scripts into missions I haven't made. Mod adds that feature globally, which makes more sense in this case
Not fan of action menu, especially when it comes to basic stuff like reloading. And it wouldn't be great at all if it didn't work well with teamswitch 
So you losing ammo by deleting half full mags? 
It's kinda nicer, if ammo from half full mags goes to couple of full mags. By deleting you are losing ammo
Same here, except I fixed it by using mod
It's one of the these things which feel like it should have been in vanilla
How remove everything from supply crate cargo?
Run all the clearXCargo commands, e.g. https://community.bistudio.com/wiki/clearMagazineCargo
There's also global versions, depending on how you want to clear it
Ahh, I was looking command starting by remove ๐ฎ
clearBackpackCargoGlobal _containerObject;
clearItemCargoGlobal _containerObject;
clearMagazineCargoGlobal _containerObject;
clearWeaponCargoGlobal _containerObject;
