応用編

Last-modified: 2024-01-27 (土) 20:43:10

CMOのシナリオを作成するにあたって応用的な事項をまとめたものになります。
加筆予定

https://steamcommunity.com/sharedfiles/filedetails/?id=1312639476

シナリオ作成の手順(大部分マニュアルの受け売り)

シナリオのコンセプト・アイデアを考える

おそらくあなたには、興味を抱いている交戦状況があるはずです。それはかつて見た映画や本の一場面に刺激されたものだったり、あるいは[SP:WAWの]シナリオをプレイして改良しようと考えたかもしれません。

きっかけになる源としては、

  • 自分の蔵書 戦史に興味をもつ人のほとんどは、長年かけて収集した書籍をもっているはずです。これらは必要な史実を提供してくれます。まずはここから始めましょう。
  • ウォーゲーム友達 あなたには本を貸してくれそうな友達がいるでしょう。本は借りたら必ず返しましょう。本を盗むほど最低なことはありません。
  • 図書館 可能ならその地域の図書館に行きましょう。よそでは手に入らない貴重な資料が見つかるでしょう。その中には本当に得難いお宝があるかもしれません。戦史の書棚を見渡して必要なものを探しましょう。
  • テレビ  テレビは常に"「マヌケの見る箱」ではありません。戦争を多角的にみた良質の歴史ドキュメントを放送する局も沢山あります。表層的な番組もありますが、それでもおおまかな興味の指針となることはあります。例えば、"Victory at Sea"、"Battleline"、"World at War"などや、"Battlefield"などの良質の検証シリーズがあげられます。これらの多くは購入することも可能でその価値もあります。
  • 書店 これは最も有効なソースの一つでしょう。あなたの町の本屋に行ってみましょう。電話帳で探して小さな本屋まで網羅しましょう。良い資料がみつかるはずです。通信販売ができる本屋もたくさんあります。カタログを取り寄せるのは無料です。
  • インターネット ウェブ上には無数の戦史サイトがあります。

シナリオを新規作成する+データベースの選択

エディタに移動して適切なデータベースをロードします。期間に依存するそれは、「Cold War」データベースか「DB3K」のどちらかです。CWDB は WWII から 1980年までで、DB3K はそれ以降です。

陣営の作成

・シナリオのサイド(陣営)を作成し、その姿勢(Postures)と状態(Conditions)を
 適切な値に設定します。敵陣営を見えなくするだけではなく、中立の交通も「Blind」
 に設定して CPU 負荷を軽減するべきです。(「5.4.4. Add/Edit Sides」を参照)
・どのサイド(陣営)をプレイヤーにするか決定します。プレイヤー以外のサイド(陣
 営)は「Computer-Only」に設定します

ユニットの追加・ミッションの作成

・ユニットを追加し、必要ならプレイヤーサイド(陣営)のための任務を追加します。敵サイド(陣営)のためのユニットと任務を追加します。これは敵(コンピューター)にとって必要です。

攻撃目標となる敵軍地上施設シナリオの中核となるユニット

ブリーフィング

ブリーフィングは、シナリオプレーヤーの基本的な指針を展開できるようにするべきでし
ょう。そうすれば、何をするべきか思いを巡らし、混乱してさまよう必要がなくなります
(目的が燃料貯蔵施設を攻撃することなら、プレイヤーは防空施設の攻撃に時間を浪費す
るべきではありません。彼らの資材が限られているならば、そのブリーフィングで、その
ことについて言及するべきです)。

仕上げのための最終チェックリスト

・必要なイベントとスコアリングを追加します。(「5.5. events」を参照)
・シナリオをプレイしてテストします。
・最終チェックリストを仕上げます。(後述を参照)
・そのシナリオを提出します。

 シ ナリ オは、 セー ブ・ゲ ーム ( savename.sav) では なく、 シナ リオ・ ファ イル
(scenarioname.scen)として保存されます。
・シナリオに、時間/期間/複雑さ/難易度/場所/条件設定が設定されていること。
・プレイ可能なサイドが多量のセンサーを持っていたら、混乱を軽減するために、マッ
 プ設定の「Merge range-symbols」がオンにされていること。
・プレイ可能サイド(陣営)のための「Scenario description」と「Scenario briefings」
 が記述されていること。
・サイドが追加され、姿勢(Postures)/ROE/認識(Awareness)が設定されている
 こと。プレイ不能サイドは、「Computer only」チェックボックスがチェックされてい
 ること。
・あるサイドが AI と人間の両方でプレイされるなら、AI のために作成された任務より
 ほかに「Scrub」(中止)任務を持つこと。「Mission editor」で、人間サイドが「Human」
 チェックボックスをチェックされていたら、(訳注:意味不明)
・環境(漁船/商船)のためだけのサイドが含まれていたら、不要なセンサー計算を最
 小限に抑えるために、認識(Awareness)レベルを「Blind」に設定すること。
・ユニットは命名され、任務に割り当てられていること。
・そのシナリオの機能と設定が、設計者が意図したものに設定されていること。
・航空機を収容する空軍基地と艦船には、マガジンが存在すること。または、「Unlimited
 ordnance at bases」オプションが、デフォルトでオンに設定されていること。
・航空機は、武装されているか予備(Reserve)に設定されていること。プレイヤーが、
 弾 薬 が 追 加 で き る こ と を 知 っ て い る こ と 。 使 用 さ れ な い 航 空 機 は 、 整 備 中
 (Maintenance)に設定されていること。
・舟艇/上陸艇/UUV が、適切な場所に追加されていること。
・グループは命名され、フォーメーションが「Formation editor」で設定されていること。
・選択状態にしておきたくない全てのリファレンス・ポイントが、未選択にされている
 こと。それらがプレイヤーに移動されたくなければ、ロックされていること。
・進入禁止領域(No-Navigation zones)が追加され、必要に応じてロックされているこ
 と。
・任務領域と排他領域(Exclusion zones)が、リファレンス・ポイントを共有していな
 いこと。同様に、任務領域と進入禁止領域も共有していないこと。
・「Event editor」で作成された全てのイベントは、トリガ(Trigger)とアクション
 (Action)を持っていること。
・(追加されていれば)「Special actions」は、適切かつ効果的に機能すること。
・シナリオで得点(Point)を使用していたら、正確に構成された「Scoring dialog」を
 持っていること。
・そのゲームがユニット・ビューになっていたら、Page Up ボタンを押してグループ・
 ビューに戻しておくこと。
・レイヤ(レリーフ/緯度/経度)は、(それらを使用したいと思っていたら)マップ設
 定で有効化されていること。
・「God’s eye view」がオフにされていること(使用していたら)。
・メッセージが表示されていたら、「Game」ドロップダウン・メニューの「Message Log」
 で「Clear」を選択して消去しておくこと。
・「Losses and Expenditures report」(損失と消耗の報告)を消去しておくこと。エラ
 ー項目は、「Reset All」ボタンをクリックすることで消去されます。
・そのシナリオの要素が適切に作動し、ゲーム内で問題を引き起こさないこと(例えば、
 決して活性化しないミサイル攻撃:バグやシナリオ・エディタの欠陥のためではなく、
 単に目標が時間内に発見されなかったため)。
・そのシナリオをプレイするのが楽しいと感じられること。非常に困難なシナリオ(勝
 利条件がごく稀にしか満たされない)、または簡単すぎるシナリオ(プレイヤー側がス
 タンドオフ兵器で楽々と勝利できる)は、全てが技術的に適正であったとしても、や
 り直す必要があるかもしれません。

シナリオ説明等に画像を張る:

書きかけ

インターネット上の画像URLを直接貼るのが一番簡単(当然インターネット接続がないと画像表示されない)

シナリオ説明と陣営ブリーフィングの場合
[LOADDOC] ファイル名 [/LOADDOC] と記述するとテキストの代わりにファイル(htmlファイルあるいは画像ファイル)が読み込まれる.キャンペーンシナリオのブリーフィングはこれを利用している
path relative to the scenario file to a html file, such that say your html was in a Assets sub folder [LOADDOC]Assets\Some_Blue_Briefing.html[/LOADDOC].

特別メッセージの場合
ファイルのフルパスを得る必要があるためまずVP_GetScenario().FileNamePath関数でシナリオファイルのパスを得てからファイル位置を指定する
src= VP_GetScenario().FileNamePath .. '\\nameofimage'
src= 'file:///' .. VP_GetScenario().FileNamePath .. '\\nameofimage.png'

--console example setup
 local gKH = {}; gKH.Message={}; gKH.SceneGlobals={}; gKH.SceneGlobals.SceneMessages={};
 gKH.SceneGlobals.SceneMessages.InitialMsg={};

 --little function to convert whats in Message.Text (xml escaped) back to html.
 function gKH.Message.EscapedToHTML(s)
   s = s:gsub('<',"<"):gsub('>',">"):gsub(' '," "):gsub('&',"&"):gsub(''',"'");
   return s;
 end

 --this returns the Message.Text field from a specified existing action name or guid.
 function gKH.Message:GetActionMessageText(actionName)
   local r, ea = pcall(ScenEdit_SetAction,{Description=actionName, Mode='list'});
   if ((((r==true) and ea ~=nil) and ea.actions ~= nil) and ea.actions[1].Message ~=nil) and ea.actions[1].Message.Text ~=nil then
     return gKH.Message.EscapedToHTML(ea.actions[1].Message.Text); --unescape it first.
   end
   return nil;
 end
 --gets the existing action text, does a search and replace for everything in the table and returns the result.
 function gKH.Message:MessageFromTemplate(actionName,valuesTable,bChangeAction)
   if bChangeAction == nil then bChangeAction = false; end
   local txt = gKH.Message:GetActionMessageText(actionName)
   if ((txt ~= nil) and valuesTable ~=nil) and type(valuesTable) == 'table' then
     for k,v in pairs(valuesTable) do
       txt = txt:gsub(k,v); --replace k with v
     end
     if bChangeAction == true then ScenEdit_SetAction({Description=actionName, Mode='update',type="Message",Text=txt}) end
     return txt;
   else return nil; end
 end
 --wraps the send adding default body start and default body end html if not otherwise provided.
 function gKH.Message:SendHTMLMessageBlackOnWhite2(theSide,msgOpen,theMsg,msgClose,lat1,lon1)
      if(theSide == nil) then return;end
      if (msgOpen == nil) or msgOpen =='' then
      msgOpen = '<HTML><style>body {background-color: #FFFFFF; font-family: """New Times Roman""",arial,verdana,san-serif; color:#000000;}</style><body>'; end
      if (msgClose ==nil) or msgClose =='' then msgClose ='</body></HTML>' ; end
      if(lat1 ==nil or lon1==nil) then
           ScenEdit_SpecialMessage(theSide,string.format('%s%s%s',msgOpen,theMsg,msgClose) );
      else
           ScenEdit_SpecialMessage(theSide,string.format('%s%s%s',msgOpen,theMsg,msgClose),{lat=lat1,lon=lon1});
      end
 end
 --sample vars
 --sample header.
 gKH.SceneGlobals.SecureCommsHeader =
 '<p style="color: #000000; background-color: #cccccc"><IMG src="%s" style="vertical-align:middle" height="45" width="45"></IMG>    Secure Communication</p>';
 gKH.SceneGlobals.SceneMessages.InitialMsg.uri =
 "https://upload.wikimedia.org/wikipedia/commons/thumb/0/09/Seal_of_the_United_States_Department_of_the_Navy.svg/240px-Seal_of_the_United_States_Department_of_the_Navy.svg.png"
 -- you will manually have to add this file to the same folder as scene for this exact test
 gKH.SceneGlobals.SceneMessages.InitialMsg.filepath =
 VP_GetScenario().FileNamePath .. '\\240px-Seal_of_the_United_States_Department_of_the_Navy.png'
 -- sample msg.
 gKH.SceneGlobals.SceneMessages.InitialMsg.text =
 '<p>Commander,</p><p>This is some couple line message. Here is the text for me to look at, hello world. Ok this should be enough to test with for now. Good Luck.</p>';

 --Example when building text yourself, swap values based on if user has internet.
 gKH.SceneGlobals.InternetEnabled = false; local tmpstr = gKH.SceneGlobals.SceneMessages.InitialMsg.uri
 if gKH.SceneGlobals.InternetEnabled ==false then tmpstr = gKH.SceneGlobals.SceneMessages.InitialMsg.filepath; end
 gKH.Message:SendHTMLMessageBlackOnWhite2('playerside',nil,string.format(gKH.SceneGlobals.SecureCommsHeader,tmpstr) .. gKH.SceneGlobals.SceneMessages.InitialMsg.text)

 --Example when using an existing message in this case with images in subfolder images in a subfolder MyCoolScenarioNameAssets.
 --This presumes there is a action called test containing something like:
 --<BODY scroll=auto><P>Testies 1 2 <IMG alt=testimage src="__URL1__"> </P><P>Side: __PLAYERSIDE__</P></BODY>
 ScenEdit_SpecialMessage('playerside',gKH.Message:MessageFromTemplate('test',{__URL1__=VP_GetScenario().FileNamePath ..
 '\\MyCoolScenarioNameAssets\\images\\MyCool_ScenarioName_Yellow.png',__PLAYERSIDE__=ScenEdit_PlayerSide()},false))
 }}