Good Practices for handling DLC equipment and vehicles

Workshop for all Mission Engineer Comrades. Home of the FA Mission Making Template.
Post Reply
User avatar
SuicideKing
Host
Posts: 299
Joined: Wed Nov 27, 2013 1:29 pm
Location: India/Netherlands
Contact:

Good Practices for handling DLC equipment and vehicles

Post by SuicideKing » Fri Dec 08, 2017 12:38 am

Privyet, tovarish Host, kak dela?
Zdravstvuyte, tovarish. Ya ochen kharasho!

Pochemu ty privel menya syuda?
Khoroshiy vopros! There was a discussion in Discord chat over essential DLCs for playing with Folk ARPS. Given that we're in a transitional period with new DLCs being rolled out, and players without the DLC join sessions too, I thought it would be good idea to document scripted solutions to handle non-DLC players in different circumstances. This will become even more important with Tanks DLC round the corner.

Aha! A fight against capitalist forces!
Er... you could say that is a potential side effect... but the motivation here is to make the session more enjoyable for those who may not be in a position to (or not want to) spend more money on Arma DLC for various reasons. This is especially relevant to newer guests. I'm usually not fond of money being a barrier-to-entry. something something capitalism...

Okay, so what are the tools of the revolution?
There are a bunch of script commands that are handy for circumventing vehicle locks, or preventing DLC gear from being given to non-DLC owners.
  • getDLCs- checks whether player has DLCs. All DLC appIDs can be found in RPT file, or at the bottom of the link wiki page.
  • getObjectDLC - Returns the AppID of an object, not a string. Can be used in conjunction with getDLCs.
  • addAction - Adds an action menu action. Can be useful for providing a workaround to DLC-locked crew slots of vehicles.
  • connectTerminalToUAV - useful to allow non-DLC owners to control DLC UAVs.
  • List of various class names
In addition, there is the script initPlayerLocal.sqf which should take care of any locality issues on mission start (or otherwise), and can help exclude playable AI from being affected by the scripts. Useful for overwriting gear assigned via F3's assignGear scripts, which can be executed before a player has loaded/initialised on the server. Also see: Initialisation Order.

WARNING: These scripts run once per player, so take care of things with "global effect".

Inspire us to action, Dear Leader Comrade Host!
:commissar:

Here are a few examples to get you started:

1. Say you want to use those fabulous Basic Helmets from Laws of War. You enter the class name into the assign gear script, so all playable units get it. Then, create a file initPlayerLocal.sqf. Here, you can simply say:

Code: Select all

if ((571710 in getDLCs 2) && {headgear player isEqualTo "H_PASGT_basic_olive_F"}) then {player addHeadgear "H_HelmetB_camo";};
So what's happening here? 571710 is the AppID for Laws of War. We check if the player doesn't have the DLC, and if true, we check if the player is currently assigned the Basic Helmet (Olive). This is so that other potential headgears aren't replaced (like berets). If both conditions are true, we give them a helmet from the base game. Do make sure this replacement helmet is similar in its armour rating as the one you're replacing.

The addition of two curly braces {...} around the second condition is an optimisation - if the first condition is false, the second isn't checked. Therefore, place the condition you expect to be false most frequently first. Here, I know most of the units have the helmet, so it's more likely that a player doesn't have the DLC, than it is that a player doesn't have the helmet equipped. While we're on the subject of optimisation, isEqualTo is faster for string comparison than ==. Finally, I can't use getObjectDLC with the helmet class name, because it's a string not an object.

Note that you don't always need to check for this stuff - if you need a particular Marksmen DLC or Apex DLC weapon in a mission, then that's completely fine. This is more for stuff that is more aesthetic and can be easily replaced without much loss of flavour or any loss in functionality.

2. Now, let's take a look at vehicles. DLC vehicles allow non-DLC owning passengers to get in, but not crew. And by crew I mean driver/pilot/gunner/commander. We want a custom action menu entry that lets a non-DLC player drive/command/be a gunner/loadmaster in a vehicle (driver includes a pilot role, of course). For example, this code can be pasted in the unit's init box, found in the vehicle's editor attributes window.

Code: Select all

this addAction ["Get in DLC Plane", {(_this select 1) moveInDriver (_this select 0)},nil, 6, true, true, "", "(driver _target != _this) && {isNull driver _target} && {601670 in (getDLCs 2)}",10];
While the wiki should help you out with the syntax, it's worth noting that I assigned the priority as 6 to make this the first option instead of the game's own "get in" action menu entry (which won't work for a non-DLC owner). Anyway, let's go over the condition: first, you want to check that the player isn't the driver of the vehicle (this is always false while the player is inside the vehicle, and thus most false, and hence the first condition). Next, you want to check that there's no one in the plane already. This is admittedly more likely to be true than the last condition for a plane, but may not be true for other vehicle types. Finally you check if the player owns the DLC, in this case the DLC in question is the Jets DLC. If they don't own it, then it shows the action, otherwise it hides it (note that if this condition is being checked, the preceding ones were evaluated to true).

Now, it's possible to generalise this a bit with getObjectDLC. For example:

Code: Select all

this addAction ["Drive DLC vehicle", {(_this select 1) moveInDriver (_this select 0)},nil, 6, true, true, "", "(driver _target != _this) && {isNull driver _target} && {(getObjectDLC _target) in (getDLCs 2)}",10];
This should work for any vehicle and any DLC. Not sure what will happen if nil is returned, though, but then again using it with vanilla vehicles is pointless anyway. Should you decide to run this from initPlayerLocal.sqf then replace this at the start with the variable name of the vehicle, for example VehNATO_TH1. Do keep in mind that using getObjectDLC to return the appropriate ID is going to be slower than simply using a hard-coded number.

Note: You may have noticed that this doesn't cover other crew positions, and they're probably best of with their own action menu entries. Also note that this won't prevent "nag screen" adverts from appearing.

Well, I hope this helps.

That's cool and all, but what about UAVs?
Meh I'm too tired to write an example. :P
Experiment! For science! :science101: Use the eloquently named connectTerminalToUAV, either via addAction or initPlayerLocal.sqf. Probably check that the affected player is of class UAV operator, or owns a UAV terminal, is the correct side, has the DLC - or whatever else you can think of.

Kewl. btw I herd u liek mudkips?
:commissar:
themiddlevoid.wordpress.com

Post Reply