Multiplayer Armory: Difference between revisions
Lou Montana (talk | contribs) m (Text replacement - "{{ExternalLink|" to "{{Link|") |
Lou Montana (talk | contribs) m (Text replacement - "[[Image:" to "[[File:") |
||
(2 intermediate revisions by the same user not shown) | |||
Line 1: | Line 1: | ||
{{TOC|side}} | {{TOC|side}} | ||
[[ | [[File:ARMEX_TANK.jpg|250px]] | ||
The '''Multiplayer Armory''' (ARMEX) enables you to try out all weapons and every single vehicle model from {{arma2}} in procedurally generated missions with up to eight friends online or over LAN! | The '''Multiplayer Armory''' (ARMEX) enables you to try out all weapons and every single vehicle model from {{arma2}} in procedurally generated missions with up to eight friends online or over LAN! | ||
The system allows it to be used on user-made worlds. See the | The system allows it to be used on user-made worlds. See the configuration guide below. | ||
* {{Link| | * {{Link|http://forums.bistudio.com/showthread.php?p{{=}}1777081|Feedback thread}} | ||
This documentation covers the [[Multiplayer Armory]] ('''MPA'''), how to set it up generally and how to configure custom content to work with it. | This documentation covers the [[Multiplayer Armory]] ('''MPA'''), how to set it up generally and how to configure custom content to work with it. | ||
A lot of the [[Armory_configuration|documentation]] regarding the original ''Armory'' is still relevant. | A lot of the [[Armory_configuration|documentation]] regarding the original ''Armory'' is still relevant. | ||
{{Feature | | {{Feature|informative| | ||
* Whenever a code sample shows | * Whenever a code sample shows <syntaxhighlight lang="cpp" inline>// ...</syntaxhighlight>, this means a full config will likely have more content, but this is not shown in these samples because it is not relevant to the MPA. | ||
* The initial release of the MPA does not integrate user-made items such as vehicles, because of low-level engine limitations in the multiplayer environment. | * The initial release of the MPA does not integrate user-made items such as vehicles, because of low-level engine limitations in the multiplayer environment. | ||
* The MPA was built using [[Object_Oriented_scripting_shell|a scripting framework]] which simulates many of the benefits of Object Oriented architectures. | * The MPA was built using [[Object_Oriented_scripting_shell|a scripting framework]] which simulates many of the benefits of Object Oriented architectures. | ||
Line 17: | Line 16: | ||
== | == Configuration == | ||
<syntaxhighlight lang="cpp"> | <syntaxhighlight lang="cpp"> | ||
class CfgMPArmory | class CfgMPArmory | ||
Line 32: | Line 32: | ||
occurAtARMEX = 2; // Can this challenge be triggered at ARMEX? 0: no [default] / 1: yes / 2: yes and only there (Scalar) | occurAtARMEX = 2; // Can this challenge be triggered at ARMEX? 0: no [default] / 1: yes / 2: yes and only there (Scalar) | ||
startAlways = 1; // Should it start always when the conditions are met? 0: no, randomly [default] / 1: yes (Scalar) | startAlways = 1; // Should it start always when the conditions are met? 0: no, randomly [default] / 1: yes (Scalar) | ||
title = "Some Meta-challenge"; | title = "Some Meta-challenge"; // Challenge title text (localized String) | ||
icon = "path\somemetachallenge_icon_ca.paa"; // Meta-challenges use icons in (de)briefings (String) | icon = "path\somemetachallenge_icon_ca.paa"; // Meta-challenges use icons in (de)briefings (String) | ||
script = "path\somemetachallenge.sqf"; | script = "path\somemetachallenge.sqf"; // Path to the meta-challenge script (String) | ||
points = 50; | points = 50; // Points received by the team and players (Scalar) | ||
tidExclusions[] = {2, 6, 7, 8, 9, 10, 11, 12}; // For which [[Armory_configuration#Type_ID.27s|TIDs]] is this challenge excluded? (Array of Scalar) | tidExclusions[] = { 2, 6, 7, 8, 9, 10, 11, 12 }; // For which [[Armory_configuration#Type_ID.27s|TIDs]] is this challenge excluded? (Array of Scalar) | ||
runtimeConditions[] = {"isDriver", "isFlying"}; // What runtime conditions must the item satisfy (see original Armory documentation)? (Array of String) | runtimeConditions[] = { "isDriver", "isFlying" }; // What runtime conditions must the item satisfy (see original Armory documentation)? (Array of String) | ||
chalidExclusions[] = {3, 7, 8, 21, 22}; // For which challenge IDs is this meta-challenge excluded? (Array of Scalar) | chalidExclusions[] = { 3, 7, 8, 21, 22 }; // For which challenge IDs is this meta-challenge excluded? (Array of Scalar) | ||
textLog = "Description ..."; | textLog = "Description ..."; // Text shown as description in the player log (localized String) | ||
// All texts required for the task (Array of localized String) | // All texts required for the task (Array of localized String) | ||
textTask[] = | textTask[] = | ||
Line 46: | Line 46: | ||
"Task ..." | "Task ..." | ||
}; | }; | ||
// All texts required for the debriefing (Array of localized String) | // All texts required for the debriefing (Array of localized String) | ||
textDebriefing[] = | textDebriefing[] = | ||
Line 59: | Line 59: | ||
type = 0; | type = 0; | ||
title = "Some Challenge"; | title = "Some Challenge"; | ||
image = "path\somechallenge_co.paa" | image = "path\somechallenge_co.paa"; // Challenges use images in (de)briefings (String) | ||
script = "path\somechallenge.sqf"; // Special script called as function to return a special respawn position as Array (String) | script = "path\somechallenge.sqf"; // Special script called as function to return a special respawn position as Array (String) | ||
scriptRespawn = "path\somechallenge_Respawn.sqf"; // Special script called as function before the challenge starts (String) | scriptRespawn = "path\somechallenge_Respawn.sqf"; // Special script called as function before the challenge starts (String) | ||
// Used to e.g. override some default parameters with special values for this challenge | // Used to e.g. override some default parameters with special values for this challenge | ||
scriptInit = "path\somechallenge_Init.sqf"; | scriptInit = "path\somechallenge_Init.sqf"; | ||
respawnDelay = 30; | respawnDelay = 30; // Delay before a player respawn in seconds (Scalar) [-1 disables respawn until the challenge ends] | ||
tidExclusions[] = {7, 8}; | tidExclusions[] = { 7, 8 }; | ||
configConditions[] = {"hasWeapon"}; // What config conditions must the items used in this challenge satisfy? (Array of String) | configConditions[] = { "hasWeapon" }; // What config conditions must the items used in this challenge satisfy? (Array of String) | ||
positionMode = 3; | positionMode = 3; // Where to insert? 0: away from target [default] / 1: very close to target / 2: randomly around target / 3: near the target (Scalar) | ||
positionOnRoad = 1; | positionOnRoad = 1; // Find target position on a road? 0: no [default] / 1: yes (Scalar) | ||
useRoadRoute = 1; | useRoadRoute = 1; // Grow a road network route? 0: no [default] / 1: yes - grown to both ends / 2: yes - grown to one end (Scalar) | ||
minimumNodes = 3; | minimumNodes = 3; // Route must have at least this amount of nodes (Scalar) | ||
teamMode = 1; | teamMode = 1; // Team configuration for players. 0: all in one team [default] / 1: all alone (Scalar) | ||
itemMode = 1; | itemMode = 1; // Item mode. 0: all using own item [default] / 1: all using the same random item (Scalar) | ||
points[] = {150}; | points[] = { 150 }; // Amount of points per end state (Array of Scalar) | ||
taskStates[] = {1, 0}; // Task state for each end state (Array of Scalar) | taskStates[] = { 1, 0 }; // Task state for each end state (Array of Scalar) | ||
textLog = "Description ..."; | textLog = "Description ..."; | ||
textTask[] = {"Task ..."}; | textTask[] = { "Task ..." }; | ||
textDebriefing[] = {"Debriefing ..."}; | textDebriefing[] = { "Debriefing ..." }; | ||
// All markers to be created for this challenge | // All markers to be created for this challenge | ||
Line 88: | Line 88: | ||
color = "ColorBlue"; // CfgMarkerColors color entry (String) | color = "ColorBlue"; // CfgMarkerColors color entry (String) | ||
// Text shown with the marker (localized String) | // Text shown with the marker (localized String) | ||
Value "#title" means the challenge title is used | Value "#title" means the challenge's title is used | ||
text = "Some Marker"; | text = "Some Marker"; | ||
Marker position (String) | Marker position (String) | ||
Line 111: | Line 111: | ||
hints[] = | hints[] = | ||
{ | { | ||
{-1, -1, "Hint ..."} | { -1, -1, "Hint ..." } | ||
}; | }; | ||
}; | }; | ||
Line 117: | Line 117: | ||
== Worlds == | === Worlds === | ||
We have introduced a new class ''ARMEX'' in class ''Armory'' of any world that is to be used with the MPA. | We have introduced a new class ''ARMEX'' in class ''Armory'' of any world that is to be used with the MPA. | ||
In it we define where the items are placed and how the special areas are set up. The easiest way to understand these definitions is to look at the ''Takistan'' configs. | In it we define where the items are placed and how the special areas are set up. The easiest way to understand these definitions is to look at the ''Takistan'' configs. | ||
{{Feature | | {{Feature|informative|Entries ''safePositionAnchor'' and ''safePositionRadius'' described for the original Armory are important as well.}} | ||
<syntaxhighlight lang="cpp"> | <syntaxhighlight lang="cpp"> | ||
class CfgWorlds | class CfgWorlds | ||
{ | { | ||
... | // ... | ||
class SomeWorld | class SomeWorld | ||
{ | { | ||
Line 133: | Line 134: | ||
class ARMEX | class ARMEX | ||
{ | { | ||
position[] = {10, 10}; // Centre point of the ARMEX on this world (Array of Scalar) | position[] = { 10, 10 }; // Centre point of the ARMEX on this world (Array of Scalar) | ||
// Radius in meters of a circle with the above centre point (Scalar) | // Radius in meters of a circle with the above centre point (Scalar) | ||
// This circle should encompass the entire ARMEX area | // This circle should encompass the entire ARMEX area | ||
Line 149: | Line 150: | ||
positions[] = | positions[] = | ||
{ | { | ||
{10, 10}, | { 10, 10 }, | ||
{20, 20} | { 20, 20 } | ||
}; | }; | ||
Line 157: | Line 158: | ||
positionsInfo[] = | positionsInfo[] = | ||
{ | { | ||
{11, 11}, | { 11, 11 }, | ||
{21, 21} | { 21, 21 } | ||
}; | }; | ||
Line 177: | Line 178: | ||
}; | }; | ||
... | // ... | ||
}; | }; | ||
Line 185: | Line 186: | ||
class SomeArea | class SomeArea | ||
{ | { | ||
displayName = $STR_EP1_MPA_AREA_SOMEAREA; // Name of the area (localized String) | displayName = "$STR_EP1_MPA_AREA_SOMEAREA"; // Name of the area (localized String) | ||
position[] = {10, 10}; | position[] = { 10, 10 }; // XY-coordinates for this area (Array of Scalar) | ||
positionInfo[] = {11, 11}; | positionInfo[] = { 11, 11 }; // XY-coordinates for an information kiosk [optional] (Array of Scalar) | ||
direction = 0; // Azimuth in degrees for this area (Scalar) | direction = 0; // Azimuth in degrees for this area (Scalar) | ||
directionInfo = 90; // Azimuth in degrees for the information kiosk [optional] (Scalar) | directionInfo = 90; // Azimuth in degrees for the information kiosk [optional] (Scalar) | ||
Line 194: | Line 195: | ||
directionTexture = "direction_sign_area_somearea_ca"; // Texture used for direction signs pointing to this area (String) | directionTexture = "direction_sign_area_somearea_ca"; // Texture used for direction signs pointing to this area (String) | ||
compositionScript = "path\mpa_somearea1.sqf"; // Path to the DynO set script (String) | compositionScript = "path\mpa_somearea1.sqf"; // Path to the DynO set script (String) | ||
compositionPosition[] = {10, 10}; // Anchor position for the set (Array of Scalar) | compositionPosition[] = { 10, 10 }; // Anchor position for the set (Array of Scalar) | ||
}; | }; | ||
}; | }; | ||
Line 211: | Line 212: | ||
compositionAnchors[] = | compositionAnchors[] = | ||
{ | { | ||
{20, 20} | { 20, 20 } | ||
}; | }; | ||
}; | }; | ||
Line 221: | Line 222: | ||
{ | { | ||
{ | { | ||
{10, 10}, | { 10, 10 }, | ||
{20, 20}, | { 20, 20 }, | ||
{30, 30}, | { 30, 30 }, | ||
{40, 40} | { 40, 40 } | ||
} | } | ||
}; | }; | ||
Line 232: | Line 233: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
=== Supported | === Supported Types === | ||
{{Columns|3| | |||
* Tracked | * Tracked | ||
* Wheeled | * Wheeled | ||
Line 243: | Line 246: | ||
* Launchers | * Launchers | ||
* Explosives | * Explosives | ||
}} | |||
=== Factions === | |||
It is possible to define hints randomly shown while using items from a particular faction. | It is possible to define hints randomly shown while using items from a particular faction. | ||
Line 251: | Line 256: | ||
class CfgFactionClasses | class CfgFactionClasses | ||
{ | { | ||
... | // ... | ||
class SomeFaction | class SomeFaction | ||
{ | { | ||
... | // ... | ||
// List of hints specific to this faction (Array of localized String) | // List of hints specific to this faction (Array of localized String) | ||
hints[] = | hints[] = | ||
Line 263: | Line 268: | ||
}; | }; | ||
</syntaxhighlight> | </syntaxhighlight> | ||
{{GameCategory|arma2oa}} | {{GameCategory|arma2oa}} |
Latest revision as of 23:10, 20 November 2023
The Multiplayer Armory (ARMEX) enables you to try out all weapons and every single vehicle model from Arma 2 in procedurally generated missions with up to eight friends online or over LAN! The system allows it to be used on user-made worlds. See the configuration guide below.
This documentation covers the Multiplayer Armory (MPA), how to set it up generally and how to configure custom content to work with it.
A lot of the documentation regarding the original Armory is still relevant.
Configuration
class CfgMPArmory
{
// List of all (meta-)challenges in the MPA
// Can be expanded by user-made add-ons
class Challenges
{
class SomeMetaChallenge
{
id = 0; // Unique challenge identifier (Scalar)
type = 1; // 0: normal, 1: meta (Scalar)
multiplayer = 1; // Is this meta-challenge applied to more than one player? 0: no [default] / 1: yes (Scalar)
occurAtARMEX = 2; // Can this challenge be triggered at ARMEX? 0: no [default] / 1: yes / 2: yes and only there (Scalar)
startAlways = 1; // Should it start always when the conditions are met? 0: no, randomly [default] / 1: yes (Scalar)
title = "Some Meta-challenge"; // Challenge title text (localized String)
icon = "path\somemetachallenge_icon_ca.paa"; // Meta-challenges use icons in (de)briefings (String)
script = "path\somemetachallenge.sqf"; // Path to the meta-challenge script (String)
points = 50; // Points received by the team and players (Scalar)
tidExclusions[] = { 2, 6, 7, 8, 9, 10, 11, 12 }; // For which [[Armory_configuration#Type_ID.27s|TIDs]] is this challenge excluded? (Array of Scalar)
runtimeConditions[] = { "isDriver", "isFlying" }; // What runtime conditions must the item satisfy (see original Armory documentation)? (Array of String)
chalidExclusions[] = { 3, 7, 8, 21, 22 }; // For which challenge IDs is this meta-challenge excluded? (Array of Scalar)
textLog = "Description ..."; // Text shown as description in the player log (localized String)
// All texts required for the task (Array of localized String)
textTask[] =
{
"Task ..."
};
// All texts required for the debriefing (Array of localized String)
textDebriefing[] =
{
"Debriefing ..."
};
};
class SomeChallenge
{
id = 1;
type = 0;
title = "Some Challenge";
image = "path\somechallenge_co.paa"; // Challenges use images in (de)briefings (String)
script = "path\somechallenge.sqf"; // Special script called as function to return a special respawn position as Array (String)
scriptRespawn = "path\somechallenge_Respawn.sqf"; // Special script called as function before the challenge starts (String)
// Used to e.g. override some default parameters with special values for this challenge
scriptInit = "path\somechallenge_Init.sqf";
respawnDelay = 30; // Delay before a player respawn in seconds (Scalar) [-1 disables respawn until the challenge ends]
tidExclusions[] = { 7, 8 };
configConditions[] = { "hasWeapon" }; // What config conditions must the items used in this challenge satisfy? (Array of String)
positionMode = 3; // Where to insert? 0: away from target [default] / 1: very close to target / 2: randomly around target / 3: near the target (Scalar)
positionOnRoad = 1; // Find target position on a road? 0: no [default] / 1: yes (Scalar)
useRoadRoute = 1; // Grow a road network route? 0: no [default] / 1: yes - grown to both ends / 2: yes - grown to one end (Scalar)
minimumNodes = 3; // Route must have at least this amount of nodes (Scalar)
teamMode = 1; // Team configuration for players. 0: all in one team [default] / 1: all alone (Scalar)
itemMode = 1; // Item mode. 0: all using own item [default] / 1: all using the same random item (Scalar)
points[] = { 150 }; // Amount of points per end state (Array of Scalar)
taskStates[] = { 1, 0 }; // Task state for each end state (Array of Scalar)
textLog = "Description ...";
textTask[] = { "Task ..." };
textDebriefing[] = { "Debriefing ..." };
// All markers to be created for this challenge
class Markers
{
class SomeMarker1
{
icon = 1; // Icon instead of an ellipse? 0: no / 1: yes (Scalar)
type = "mil_start"; // CfgMarkers type entry (String)
color = "ColorBlue"; // CfgMarkerColors color entry (String)
// Text shown with the marker (localized String)
Value "#title" means the challenge's title is used
text = "Some Marker";
Marker position (String)
// References an Array stored in a variable with this name in the challenge
// Value "#routeStart" means the challenge route start is used
// Value "#routeEnd" means the challenge route end is used
// Value "#routeNode" means this marker is created for every node in the challenge route
position = "positionInsertion";
};
class SomeMarker2
{
size = 100; // Uniform X and Y scale in meters (Scalar)
color = "ColorRed";
position = "positionInsertion";
};
};
};
};
// Defining generic MPA hints as well as hints specific to certain database tables
// [target table (-1: generic hint, 0: item set, 1: item type) (Scalar), primary key ID in the table (Scalar), hint (localized String)]
hints[] =
{
{ -1, -1, "Hint ..." }
};
};
Worlds
We have introduced a new class ARMEX in class Armory of any world that is to be used with the MPA. In it we define where the items are placed and how the special areas are set up. The easiest way to understand these definitions is to look at the Takistan configs.
class CfgWorlds
{
// ...
class SomeWorld
{
class Armory
{
class ARMEX
{
position[] = { 10, 10 }; // Centre point of the ARMEX on this world (Array of Scalar)
// Radius in meters of a circle with the above centre point (Scalar)
// This circle should encompass the entire ARMEX area
radius = 250;
// Defining all item-specific data per type
// Not defining items of a certain type means they will not be included at ARMEX
class Items
{
// Find the list of all item class names below
class Tracked
{
// List of XY-coordinates where the actual items can be positioned (Array of Array of Scalar)
// The amount of defined positions determines how many items of this type will be randomly included
positions[] =
{
{ 10, 10 },
{ 20, 20 }
};
// List of XY-coordinates where the information signs for these items can be positioned (Array of Array of Scalar)
// This list corresponds to the list of positions above (order and amount)
positionsInfo[] =
{
{ 11, 11 },
{ 21, 21 }
};
// List of azimuths in degrees the items will be oriented with (Array of Scalar)
// This list corresponds to the list of positions above (order and amount)
directions[] =
{
90,
90
};
// List of azimuths in degrees the item information signs will be oriented with (Array of Scalar)
// This list corresponds to the list of positions above (order and amount)
directionsInfo[] =
{
180,
180
};
// ...
};
// Special areas of ARMEX, such as the item displays, Mobility Ranges, Firing Ranges, etc.
class Areas
{
class SomeArea
{
displayName = "$STR_EP1_MPA_AREA_SOMEAREA"; // Name of the area (localized String)
position[] = { 10, 10 }; // XY-coordinates for this area (Array of Scalar)
positionInfo[] = { 11, 11 }; // XY-coordinates for an information kiosk [optional] (Array of Scalar)
direction = 0; // Azimuth in degrees for this area (Scalar)
directionInfo = 90; // Azimuth in degrees for the information kiosk [optional] (Scalar)
markerType = "n_armor"; // CfgMarkers type used to indicate this area (String)
markerColor = "ColorBlue"; // CfgMarkerColors used [ColorBlack is default] (String)
directionTexture = "direction_sign_area_somearea_ca"; // Texture used for direction signs pointing to this area (String)
compositionScript = "path\mpa_somearea1.sqf"; // Path to the DynO set script (String)
compositionPosition[] = { 10, 10 }; // Anchor position for the set (Array of Scalar)
};
};
// List of optional extra DynO sets, used to add ambient scenery
class AmbientObjects
{
// List of paths to DynO scripts (Array of String)
compositionScripts[] =
{
"path\mpa_ambient1.sqf"
};
// List of XY-coordinates as the anchor positions for the above sets (Array of Array)
// Mapped using azimuth 0
compositionAnchors[] =
{
{ 20, 20 }
};
};
};
// One or several pre-defined back-up routes used in challenges which require a route
// These are only used in case a random route could not be found
backUpRoutes[] =
{
{
{ 10, 10 },
{ 20, 20 },
{ 30, 30 },
{ 40, 40 }
}
};
};
};
};
Supported Types
- Tracked
- Wheeled
- Static
- Helicopters
- Airplanes
- Rifles
- Machineguns
- Sidearms
- Launchers
- Explosives
Factions
It is possible to define hints randomly shown while using items from a particular faction.
class CfgFactionClasses
{
// ...
class SomeFaction
{
// ...
// List of hints specific to this faction (Array of localized String)
hints[] =
{
"Some hint!"
};
};
};