フォーラムへの返信
-
投稿者投稿
-
JFetch(ふぇっち)参加者
一応できる方法を考えてみましたがアーセナルの仕様上ブラックリストでの管理は難しいように感じられました。
おそらく一番簡単な方法ですが…
["AmmoboxInit", [arsenalBox, true]] call BIS_fnc_arsenal; [arsenalBox, "ACE_Banana"] call BIS_fnc_removeVirtualItemCargo;
コレはできません!
原因はアーセナルの処理の仕様上です。(詳しくは最後)ならばConfigから全アイテムを取得して…と思いましたがBIのアーセナルスクリプトでやっていることをまたやるのは面倒なので…
若干不満は残りますが以下のようにして実現してみました。
※内容を設定するだけなのでアーセナルのアクション項目の追加は別途行ってください。
setArsenalContensByBlackList.sqf/* v1.0.000 Script: setArsenalContensByBlackList.sqf Description: アーセナルの中身をブラックリストを用いて設定する。 ブラックリストとは: 使用、許可するものを指定するホワイトリストに対して、 禁止するものや除くものを指定する方法がブラックリストという。 Parameters: 1: Object: アーセナルを設定するオブジェクト(ブラックリストを用いて) 2: Any: 指定されたタグで結びつけたクラスのリスト NestedArray: [["weapon", []], ["magazine", []], ["backpack", []], ["item", []]] *"weapon"等のタグは大文字小文字を区別するので変更しないように。 String: 上記配列を最後の行に記述したSQFファイル(例: "script\blacklist.sqf") Returns: true */ private ["_obj", "_blacklist"]; _obj = param [0, objNull, [objNull]]; _blacklist = param [1, [], [[], ""]]; // ローカル関数 private _local_fnc_getClass = { private ["_removeClasses"]; params ["_classes", "_blacklist", "_key"]; _removeClasses = ([_blacklist, _key] call BIS_fnc_getFromPairs); if (!isNil "_removeClasses") then {_classes = _classes - _removeClasses}; _classes }; if (_blacklist isEqualType "") then { _blacklist = call (compile preprocessFileLineNumbers _blacklist); }; /* メイン処理 */ private ["_data"]; // アーセナルで取扱うアイテムクラスを取得できるようにする _data = missionNamespace getVariable "bis_fnc_arsenal_data"; if (isNil "_data") then { ["Preload"] call BIS_fnc_arsenal; _data = missionNamespace getVariable ["bis_fnc_arsenal_data", []]; }; // アーセナルの内容設定 for [{private _i = 0}, {_i < count _data}, {_i = _i + 1}] do { private _classes = _data select _i; switch (true) do { case (_i in [0, 1, 2]): { _classes = [_classes, _blacklist, "weapon"] call _local_fnc_getClass; [_obj, _classes, false, false] call BIS_fnc_addVirtualWeaponCargo; }; case (_i in [22, 23, 26]): { _classes = [_classes, _blacklist, "magazine"] call _local_fnc_getClass; [_obj, _classes, false, false] call BIS_fnc_addVirtualMagazineCargo; }; case (_i == 5): { _classes = [_classes, _blacklist, "backpack"] call _local_fnc_getClass; [_obj, _classes, false, false] call BIS_fnc_addVirtualBackpackCargo; }; case (_i > 2): { _classes = [_classes, _blacklist, "item"] call _local_fnc_getClass; [_obj, _classes, false, false] call BIS_fnc_addVirtualItemCargo; }; }; }; true
blacklist.sqf
private ["_wpn", "_mag", "_bpack", "_item"]; _wpn = ["arifle_MX_Black_F"]; _mag = []; _bpack = ["B_AssaultPack_blk", "B_FieldPack_ocamo"]; _item = ["Binocular"]; [["weapon", _wpn], ["magazine", _mag], ["backpack", _bpack], ["item", _item]]
最後に ; が無いのは仕様です。
これをそのまま使うとロード画面が変なタイミングで入る上にスクリプトエラーを吐く(精神衛生上悪いだけ)のでアーセナルの設定時に以下のようなコードをInit欄に書くことをおすすめします。
(それでも予めアーセナルを開いてないのでスクリプトエラー吐くのは内緒)this addAction ["Initialize Arsenal", { private ["_obj", "_script"]; _obj = _this select 0; _script = [_obj, "blacklist.sqf"] execVM "setArsenalContensByBlackList.sqf"; waitUntil {sleep 0.1; scriptDone _script}; ["AmmoboxInit", [_obj, false]] call BIS_fnc_arsenal; (_this select 0) removeAction (_this select 2); }, nil, 6, false];
今回、たいしてデバッグしてないのでアイテムが足りないとかあるかも。
ぁ…アーセナル対象のオブジェクトを一旦初期化(クリア)する処理してないや…別にいいよね|д゚)チラッBIのArsenalスクリプトの仕様(予想)
Preloadの処理の時にConfigから扱えるアイテム類を全て列挙し、そこから各種値(名前とか性能)を取得し、GUIのデータを保持する領域に保存。
プレイヤーがアーセナルのアクションメニューを開いた時もしくは項目タブの切替時に、エディッターが設定したアイテムと比較して、それと合致するやつだけ表示するようにしている…はず。
その処理の際、簡略化のために全てのアイテムを取扱うときにのみ”%ALL”という特殊データを用いるので、全アイテムを使う処理→いらないやつを削除ができない。
なので、BIS_fnc_getVirtual…系で現在アーセナルで取り扱っているアイテム類を取得しようとしても、全てのアイテムを使う設定にしていると”%ALL”が返ってしまう。JFetch(ふぇっち)参加者JFetch(ふぇっち)参加者ミッション中に、自分と同じ装備のAIをすぐ近くにスポーンさせて自分のグループに参加させるscript
/* v1.0.000 *サーバ上で実行する *大量に本スクリプトを呼び出さないようにする Parameters: 1: Unit: 装備の参照元ユニット 2: Group: スポーンするユニットが所属するグループ -> *nilやnullの場合は新規にグループを作成 3: Position: スポーンする場所(座標) -> *未指定の場合はパラメータ1で指定したユニットの近くにスポーン Example: *player1というのはユニットに付けた名前(Variable Name) _nil = [player1] execVM "spawnIdenticalUnit.sqf" // player1と同じ装備のユニットをplayer1の近くにスポーン Other: [player1, group player1] // 同じ装備のユニットを近くに作成し、同じグループに入れる [player1, group player1, getPos player2] // 上記とほぼ同じだが沸く場所がplayer2の近くになる *スポーンしたユニットの値が欲しい時 _spawnedUnit = [player1] call (compile preprocessFileLineNumbers "spawnIdenticalUnit.sqf") Return: Spawned Unit */
spawnIdenticalUnit.sqf
#define VARNAME_SAVED_INV "TRI_savedInventory" if !(isServer) exitWith {}; private ["_unit", "_grp", "_spawnPos"]; _unit = param [0, objNull, [objNull]]; _grp = param [1, grpNull, [grpNull]]; _spawnPos = param [2, [], [[]], [2, 3]]; if (isNull _unit) exitWith {}; private ["_side", "_unitClass", "_clone"]; _side = side _unit; _unitClass = typeOf _unit; // 装備内容の保存 [_unit, [_unit, VARNAME_SAVED_INV]] call BIS_fnc_saveInventory; // スポーンさせるユニットの作成 if (isNull _grp) then {_grp = createGroup [_side, true]}; if (_spawnPos isEqualTo []) then {_spawnPos = getPos _unit}; _clone = _grp createUnit [_unitClass, _spawnPos, [], 0, "FORM"]; // 装備のコピー(反映, 読込) [_clone, [_unit, VARNAME_SAVED_INV]] call BIS_fnc_loadInventory; _clone
JFetch(ふぇっち)参加者Exile Modなんかでセーフゾーンの弾消えるやつどうやってるのかなーって思ってたらイベントハンドラからやっていたんですね。
セーフゾーンに出入り&車両乗車時にも対応できるようにしてみました。
safeZone.sqf/* 2017/06/22 Author: Line File: safeZone.sqf Parameters: 1: String: マーカーもしくはトリガー(inAreaで指定できるパラメータ) セーフゾーンのエリアを表す トリガーの場合は、範囲のみ指定して、それ以外は初期値にする。 どうしてもセーフゾーンの監視を止めたいときはトリガーにする。(deleteVehicleでトリガーを消せば監視が終わる) 2: Array: 適用しないユニット、ビークルのタイプ(isKindOfで指定するパラメータ) Return: None Example: ["marker_0"] execVM "safeZone.sqf"; // グループ: sixGrp に規制区域内で発砲された場合通知する(すべてのクライアントで実行) [true, "TRI_safeZone_fired", { params ["_shooter", "_weapon"]; private "_hintStr"; _hintStr = format ["<<発砲規制区域内での発砲>>\n発砲者: %1\n使用武器: %2\n使用車両: %3", name _shooter, gettext (configfile >> "CfgWeapons" >> _weapon >> "displayName"), if (vehicle _shooter isEqualTo _shooter) then {"無し"} else { gettext (configfile >> "CfgVehicles" >> typeOf (vehicle _shooter) >> "displayName")} ]; _hintStr remoteExec ["hint", sixGrp]; }] call BIS_fnc_addScriptedEventHandler; */ #define FIRED_EH_INDEX "TRI_safeZoneEHIndex" #define EVENT_FIRED "TRI_safeZone_fired" if (isDedicated || !hasInterface) exitWith {}; params [["_target", objNull], ["_exceptType", [], [[]]]]; waitUntil {sleep 1; !isNull player}; /* ローカル関数 */ private _local_fnc_isAnyType = { params ["_obj", "_typeList"]; private _result = false; { if (_obj isKindOf _x) exitWith {_result = true}; } forEach _typeList; _result }; private _local_fnc_disableFiring = { params ["_unit"]; if (isNil {_unit getVariable FIRED_EH_INDEX}) then { private _command_fire = { private _projectile = param [6, objNull, [objNull]]; if (isNull _projectile) exitWith {}; deleteVehicle _projectile; hint "<<発砲規制区域>>\n武器、兵器の使用ができません。"; [missionNamespace, EVENT_FIRED, _this] call BIS_fnc_callScriptedEventHandler; }; systemChat "発砲規制 - 開始"; player setVariable [ FIRED_EH_INDEX, player addEventHandler ["FiredMan", _command_fire] ]; }; }; private _local_fnc_enableFiring = { params ["_unit"]; private _ehIndex = player getVariable FIRED_EH_INDEX; if !(isNil "_ehIndex") then { systemChat "発砲規制 - 停止"; player removeEventHandler ["FiredMan", _ehIndex]; player setVariable [FIRED_EH_INDEX, nil]; }; }; /* メイン処理 */ if (!local player) exitWith {}; // おまじない while {if (_target isEqualType objNull) then {alive _target} else {true}} do { if (player inArea _target) then { systemChat "発砲規制区域に入りました。"; player allowDamage false; while {player inArea _target} do { if ([vehicle player, _exceptType] call _local_fnc_isAnyType) then { // 発砲規制 - 除外タイプ [player] call _local_fnc_enableFiring; } else { // 発砲規制 - 対象 [player] call _local_fnc_disableFiring; }; sleep 2; }; systemChat "発砲規制区域を抜けました。"; [player] call _local_fnc_enableFiring; player allowDamage true; }; sleep 2; };
セーフゾーン複数ある時に効率悪いかなーと思ったけど、1つのファイルで終わらせようとすると見にくくなるし、そんなに沢山セーフゾーンあるわけでもないしなーと思って「セーフゾーン1個につき、1つの監視タスクを実行する仕様」にしました。
(ちなみに、paramsで指定したローカル変数は、privateを付けなくてもちゃんと識別されますよ。)
JFetch(ふぇっち)参加者2、3回読んでも「?」な状態でしたがスペルミスを考慮した所、
ModulesのSupports -> 「Supports Provider: Supply Drop」で
「ドロップされる弾薬箱に対してマップマーカー及びスモークを取り付けたい」と理解しましましたがお間違いないでしょうか。言語は英語を基準としますので、エディッタを日本語表記にしている場合は適当に訳して御覧ください。
【Supports Provider: Supply Drop (Virtual)】
(Virtual)無しの場合でもCrate initの所を一緒にすればいいです。
編集画面解説- Vehicle types: Supportで呼ぶヘリのクラスネームを記載する(複数可)
- Vehicle init: ヘリがスポーンした(湧いた)時に実行する処理(init欄に書くようなこと)
- Crate init: 弾薬箱がスポーンした(投下された)時に実行する処理
(残りはどんな効果があるかわからないので最低限なところだけ書きました。)
initとあるところで注意しないといけないのは、thisではなく、_thisとするところです。ご要望を含めた設定例
- Vehicle types: [“B_Heli_Transport_01_F”]
- Vehicle init:
- Crate init:
["AmmoboxInit",[_this,true]] call BIS_fnc_arsenal;[_this,"SmokeShellYellow"] execVM "supplyDropMarker.sqf"
(Crate init 他の例)
[_this] execVM "supplyDropMarker.sqf" // *スモークなし, マーカー自動作成 [_this,"SmokeShellYellow"] execVM "supplyDropMarker.sqf" // イエロースモーク, マーカー自動作成 [_this,"", "marker_1"] execVM "supplyDropMarker.sqf" // *スモークなし, marker_1と名前を付けたマーカーを使う
_this: マーカーを付けたいオブジェクトの名前(Variable Name)
“SmokeShellYellow”: スモークのクラスネーム(“”にするとスモーク無しになる)
“marker_1”: ドロップしたボックスにつけるマーカーの名前(Variable Name)弾薬箱の位置に好きなマーカーを使用する時
ミッションエディッタでMAP上に好きなマーカーを置いて、Alphaを0%にし、
そのマーカーの名前を上記例の3つ目のように指定するとそのマーカーが投下されたボックスの所に置かれます。supplyDropMarker.sqf
if !(isServer) exitWith {}; params ["_ammoBox", ["_smokeClass", "", [""]], ["_dropMrk", "", [""]]]; /* メイン処理 */ // 弾薬箱が地面に接地するまでマーカーの作成は保留する waitUntil { private "_pos"; _pos = getPos _ammoBox; sleep 3; getPos _ammoBox distance _pos < 1 }; // マーカーの設置 if (_dropMrk isEqualTo "") then { // 予めマーカーが用意されていなかった場合 for "_i" from 0 to 9 do { _dropMrk = format ["FDM_dropMarker_%1", random 10000]; if (markerType _dropMrk isEqualTo "") then {_i = 9}; }; _dropMrk = createMarker [_dropMrk, _ammoBox]; _dropMrk setMarkerShape "ICON"; _dropMrk setMarkerType "hd_objective"; _dropMrk setMarkerColor "ColorGreen"; _dropMrk setMarkerText "Dropped supply"; } else { // マーカーが用意されていた場合は移動させる _dropMrk setMarkerAlpha 1; _dropMrk setMarkerPos (getPos _ammoBox); }; // スモークの生成 //if !(isServer) exitWith {}; if !(_smokeClass isEqualTo "") then { private "_smoke"; _smoke = _smokeClass createVehicle (getPos _ammoBox); _smoke setPos (getPos _ammoBox); };
専用サーバー上でのcreateMarkerの挙動がわからないので、万が一、専用サーバー上でマーカーが作成されなかった場合は、
1行目のif !(isServer) exitWith {};
を削除して、// スモークの生成
直下のスラッシュ2個を削除してください。こんなかんじ
if !(isServer) exitWith {}; if !(_smokeClass isEqualTo "") then { private "_smoke"; _smoke = _smokeClass createVehicle (getPos _ammoBox); _smoke setPos (getPos _ammoBox); };
スモークやマーカーがズレるってのは、パラシュートが風で流されて、
最終的に接地した地点がドロップした地点とズレるって事だったんですね。JFetch(ふぇっち)参加者*createVehicleコマンドの座標指定は、setPosやcreateMarkerコマンドの座標指定とは「ズレ」があります。
*なので、createVehicleのあとに生成したオブジェクトに対してsetPosをしてあげると他のマーカーやオブジェクトと座標を揃えることができます。
【弾薬箱のinit欄】(// ←後のコメントは消してね)["AmmoboxInit",[this,true]] call BIS_fnc_arsenal; // アーセナルをオブジェクト(弾薬箱)に追加する if (isServer) then { _smk="SmokeShellYellow" createVehicle (getPos this); // スモークの生成 _smk setPos (getPos this); // スモークの位置の変更 };
上記コードは投稿されたものを参考に説明用として書きました。
重要なのは「*印」のところなのでそこを参考にしてみてください。(オブジェクトを重ねて生成するとオブジェクトが壊れるため(車だと爆発)それを回避するために座標を自動的に修正しているのがズレの原因。)
- この返信は7年前にJFetch(ふぇっち)が編集しました。理由: init欄なのに_thisにしてた
- この返信は7年前にJFetch(ふぇっち)が編集しました。
- この返信は7年前にJFetch(ふぇっち)が編集しました。
JFetch(ふぇっち)参加者ドライバーのAIを馬鹿にするのも手かも。
disableAI
https://community.bistudio.com/wiki/disableAI“AUTOTARGET”, “TARGET” この2つでいけるかな?
“SUPPRESSION”, “AUTOCOMBAT” も必要かな?- この返信は7年、 6ヶ月前にJFetch(ふぇっち)が編集しました。
JFetch(ふぇっち)参加者michyさんのスクリプトを使わせていただいております。
グットタイミングで助かりました。ダウンロード: [Script]CustomVirtualArsenal.VR.zip
パスワード: tri
(2週間のみ有効)<<オブジェクトのinit欄に書いた例>>
※長くなるのならinit.sqfに書くのがオススメです。setArsenalContents.sqf [this, ["WEST_LWeightBackpack.sqf", "WEST_medicBackpack.sqf"], ["triServer_defaultItems.sqf", "WEST_shortRangeScope.sqf"], ["rhs_USMC_556_basicSet.sqf"], ["%ALL"] ] execVM "scripts\CustomVirtualArsenal\setArsenalContents.sqf"; box1: アーセナルの内容を登録したいオブジェクト [](1つ目): バックパック [](2つ目): アイテム [](3つ目): ウェポン [](4つ目): マガジン 「"%ALL"はゲームに存在する全てのクラス」という意味です。 []の中にはクラスネーム、もしくは、クラスネームが書かれたリストのファイルをダブルクォーテーションで囲って記入してください。 ちなみに、リスト(sqf)の中に更にリスト(sqf)を書けます。(マトリューシカ的な感じで。) あまりリストの中にリスト(以下略、をしちゃうとファイル管理がメンドクサイので細かくせず、なるべくざっくりした感じがオススメです。 setArsenalContents.sqf [this, [this]] execVM "scripts\CustomVirtualArsenal\setArsenal.sqf"; this: アーセナルの項目を表示したいオブジェクト名(この場合、) [this]: アーセナル内容があるオブジェクト名(複数可)
スクリプト公開スレの前に自分の作成したミッションに組み込んで様子を見た後に公開、検討します。
JFetch(ふぇっち)参加者michyさんグッジョブです!
デバックはほぼほぼ済んだんですが、やっぱりリスト作りは軍事関係に詳しいプロのほうがいいですね・・・。
まぁ、それを解消するためにスクリプト書いたんですけどね。4日(今日)中にスクリプト公開スレにて使い方とデモ用のミッションファイルを上げますね。
その際、リスト作りのサポートスクリプトとしてmichyさんのスクリプトも併せて紹介させていただきます。JFetch(ふぇっち)参加者継承できるようにgear.sqf (初期装備スクリプト)も新しく作ろうかなと思ってたのでちょうど良かったです。
現状だと、全てのユニットのinit欄に対してどの処理をするか記入して、かつ、それをswitch文で判定しているのを、init.sqfに一文書くだけで初期装備を登録できるようにしようかなと。実現するには、Role Descriptionの最後に、現状のgear.sqfのように役割を.(ドット)をつけて決めればいいかなと。
Role Description: [Alpha]Team Leader.tl
init.sqf [] execVM "new_gear.sqf"; new_gear.sqf waitUntil {sleep 0.1;!isNull player}; if (player getVariable "装備は初期化済みですか?" isEqualTo true) then { _role = roleDescription player; if (_roleの末尾にドットで役割がありますか?) then { // 処理 }; }; player setVariable ["装備は初期化済みですか?", true, true];
こんな感じかな?
あと、Backpack, Item, Magazine, Weaponをわけないようするのを検討してみます。
JFetch(ふぇっち)参加者ファイル貼るの忘れてました。
旧:
http://www1.axfc.net/u/3713707.zip新:
http://www1.axfc.net/u/3714406.zipパスワード:tri
- この返信は7年、 8ヶ月前にJFetch(ふぇっち)が編集しました。理由: パスワード記載忘れ
- この返信は7年、 8ヶ月前にJFetch(ふぇっち)が編集しました。理由: 修正版アップ
JFetch(ふぇっち)参加者先日私が作成したミッションをプレイしていただいた際にアーセナルに意図してた装備品が入っていないという問題が発生しました。
原因は、エディッタ上でアーセナルの内容をいじっていたため、操作ミスで追加されていなかったようです。そこで、tri鯖で採用されているarsenal.sqfを使おうかなと様々なミッションファイルのarsenal.sqf中身を見たところ、人それぞれ違う点に気づきました。
これを引き継いで自分の好きなように・・・と思いましたが、これからいろいろミッションを作るときにせっかく「作った装備品リストが継承できないのはもったいない」ので、その点を解消できるスクリプトを書いたんですが・・・。デバックするのにいろいろな装備品リストが必要になります。(というか、このスクリプトの真の完成はそのリストあってこそです)
なので・・・そのリスト作成をお手伝いいただけると大変助かります。"任意のファイル名.sqf" [ "arifle_MX_ACO_pointer_F", // コメントも書けます。 "srifle_DMR_02_sniper_F", /* 複数行も */ "MMG_01_tan_F" // 日本語のコメントを書くならファイルフォーマットをUTF-8に! ]
こんな感じに、[]の中にクラスネームを書くだけです。
※ただし、異なるクラスのものを混ぜて書かないでください。1.銃火器本体(Weapon)
2.薬莢(Magazine)
3.バックパック
4.それ以外のアイテム(服やベスト、医薬品に…)この4つの項目で分けてください。
スクリプトが読める人は、現在作成中のスクリプトを貼っておきますのでご助言ございましたらお願いします。
ミッションフォルダのsettingsの中に有るフォルダ構造に関しては深く考えていないので、その点のご指摘ただけると幸いです。
帰宅中にふと思った、わかりやすくて管理しやすい方法。missionFolder ->settings ->VirtualArsenal ->Backpack ->Item ->Magazine ->Weapon
4つのフォルダそれぞれに自由にリストを作成する。
その際、ファイルの命名規則を設け、例えば、作者名_好きな名前.sqfのようにする。
いろいろなアドオンをミックスしてて、もしそのアドオンが入ってなくてもちょっとエラー吐くだけでちゃんと動くからこんな感じでいいかなと。フォルダ構造は自由に変更しても、スクリプト実行の際に指定しますのでご安心ください。
少しだけスクリプトについて解説
setArsenal.sqf null = [アーセナル追加先, [アーセナルの内容があるオブジェクトの名前, ...etc(複数可)]] execVM "scripts\CustomVirtualArsenal\setArsenal.sqf";
機能はアーセナルの項目が出来るようにするのが主機能です。
その際、アーセナルの内容を記録した(アーセナルが追加されている)オブジェクト名を第二引数に配列にして渡しています。
これにより、他のアーセナルの「継承」が出来るようになります。setArsenalContents.sqf null=[ アーセナルの内容を追加(記録)するオブジェクト名, 追加モード, // "i" = アイテム類, "w" = 武器, "m" = 薬莢, "b" = バックパック 検索フォルダ(もしくは上位フォルダ), // "settings\VirtualArsenal\Weapon\A3\" が現在の設定です 検索ファイル名(sqf) // 配列でsqfファイル複数指定できます。クラスネームを直接書いても動作しますが...このスクリプトの目的からそれるので推奨はしません。 省略した場合はsetList.sqfというのが読み込まれます。 ] execVM "scripts\CustomVirtualArsenal\setArsenalContents.sqf";
追加モードに関しては改良予定。
具体的には、上記に示したファイル構造であれば自動的に判別する。setList.sqf [ // 以下のファイルをすべて読み込みます。 "basic.sqf", "special.sqf" ]
- この返信は7年、 8ヶ月前にJFetch(ふぇっち)が編集しました。理由: リストを記録するファイル名指定に不備
- この返信は7年、 8ヶ月前にJFetch(ふぇっち)が編集しました。理由: スクリプトの仕様変更があったため
-
投稿者投稿