約 1,182,581 件
https://w.atwiki.jp/adone2699/pages/48.html
Minecraft ver1.7.10 導入推奨されているMOD 日本語入力MOD 導入禁止されているMOD 地下を見ることのできたり、鉱石の位置がわかるなどするMAPなど、楽しみをつぶすもの
https://w.atwiki.jp/bannerlord/pages/92.html
基本事項用語 実装パターン レイヤー追加パターンの実装例Example UI Opponent Health Bar 基本事項 用語 Gauntlet UI Bannerlord のユーザーインターフェースに用いられているフレームワークです。 Model-View-ViewModel アーキテクチャー Gauntlet UI は Model-View-ViewModel (MVVM) と呼ばれるアーキテクチャーパターンを採用しています。要は、ゲームの領域、UI の領域、その2つを仲介する領域、の3層に分離させることで、情報を整理しやすく、また分業しやすくするという発想のようです。UI の MOD の場合、実装が必要なのはこの内の View と ViewModel になります。 この辺は、WPF や XAML を触ったことのある方ならお馴染みなのかもしれませんが、そうでない方も、あまり深く考えずに概念として何となく把握していれば大丈夫です。 ウィジェット GUI を構成する部品です。TaleWorlds.GauntletUI や TaleWorlds.MountAndBlade.GauntletUI.Widgets あたりに一通り揃っています。基本的にはこれらで事足りるので、自分でウィジェットを定義するということはあまり無いのではないかと思われます。 Prefab GUI のレイアウトを定義する XML ファイルです。プレハブ建築のプレハブと同じで、出来合いの部品 (ウィジェットや他の Prefab) をどういう風に組み合わせて配置するかを指定し、なにがしかの UI 機能を提供する大きめの部品として独立させたものです。 Prefab は TaleWorlds.Engine.GauntletUI.GauntletLayer.LoadMovie() するたびに読み込まれるので、ゲーム起動中にレイアウトを確認しながら編集していくなんてこともできます。(もちろん、構文エラー等があればその時点でクラッシュしますが) Brush GUI のスタイルを定義する XML ファイルです。Prefab と Brush の関係は、HTML と CSS の関係と似たようなものだそうです。 Widget に複数の状態が定義されていれば、それぞれの状態に応じたスプライト画像やフォント等を Brush に持たせることで、Widget に視覚的変化を与えることができます。例えば、Wiget がデフォルト状態にある時のスプライト、マウスオーバー時のスプライト、クリックした時のスプライト、Disable 時のスプライトなどをまとめられる、と言えばわかりやすいでしょうか。 ブラシは、Native 等の公式モジュールの GUI\Brushes に多数定義されています。 実装パターン 一部のパターンでしか実験していません。「たぶんこういうことだろう」レベルの推測が混じっています。 追加 既存の UI スクリーンにレイヤーを追加し、そこに自前の GUI を描画する (AddLayer)。 標準的な方法です。自分で View も ViewModel も用意するので好きなようにデザインできますが、既存の GUI そのものを書き換えることはできません。 モジュールとしての競合は起こりませんが、意図せず他の MOD の GUI と表示位置がかぶってしまうことはあり得ます。 改変 (未検証) 既存の UI スクリーンのレイアウトだけを変更する (XML 改変)。 使用するデータソース (ViewModel) はそのままで、XML の書き換えによって GUI の配置なんかを変える方法です。簡単だと思いますが、おそらくやれることは限定的です。また、MOD の競合が発生しうる方法だと思われます。 上書き (未検証) 既存の UI スクリーン全体をオーバーライドする (OverrideView)。 上書きする UI スクリーンが提供していた機能を自分で実装することになるため難易度は高いでしょう。また、MOD の競合が発生しうる方法だと思われます。 新規作成 自前の UI スクリーンを作成し、何かのイベントに伴ってそのスクリーンを呼び出す (PushScreen)。 Push/Pop のスタック形式なのでモーダルなポップアップとかに向いていると思います。 一部改変 たとえばオプション項目の追加などがこれに当たりますが、現状ではできないようです。 ただ、可能にする方法は検討されているとのこと。 Beyond that, we continue to work on Adding support for adding options to the options screen レイヤー追加パターンの実装例 Example UI ExampleUI プロジェクトSubModule.cs ViewsSampleMapView.cs SampleMissionView.cs ViewModelsTestWindowVM.cs ExampleUI.Window.xml View と ViewModel の関係がはっきりするように階層 (名前空間) を分けています。 ExampleUI.Window.xml は、 [Bannerlord インストールフォルダー]\Modules\ExampleUI\GUI\Prefabs フォルダーを作成し、その中に保存します。 MVVM では疎結合 (各層の結びつきが緩やか) なのが望ましいとされているそうなので、参照はできるだけ一方向になるようにしましょう。 すなわち、 View が ViewModel のインスタンスを持ち、その逆方向のアクセスはしない Model (ゲーム内の要素) に属するデータの加工は View の中では行わず、ViewModel で行う という感じです。 コード +SubModule.cs モジュールのエントリーポイントです。 using ExampleUI.Views;using SandBox.View.Map;using System;using TaleWorlds.Core;using TaleWorlds.Engine.Screens;using TaleWorlds.MountAndBlade;using TaleWorlds.MountAndBlade.View.Missions;using TaleWorlds.MountAndBlade.View.Screen; namespace ExampleUI{ public class SubModule MBSubModuleBase { private MissionView _missionView; private MapView _mapView; // Mission (平たく言えば、キャラクターが動き回ったり攻撃したりできる状況) に対する // MOD の処理 (ビヘイビアー) の登録はこのメソッドで行います。 // OnBeforeMissionBehaviourInitialize() と OnMissionBehaviourInitialize() の違いは // MissionBehaviour.OnBehaviourInitialize() の前に呼ばれるか後によばれるかです。 public override void OnBeforeMissionBehaviourInitialize(Mission mission) { base.OnBeforeMissionBehaviourInitialize(mission); // ViewCreatorManager.CreateMissionView() は一応ファクトリーメソッドっぽいのですが、 // 公式のコードには、これを介さず単に new MissionView() しているものもあったりして // よく分かりません。どっちにしろ動くのは動きます。 _missionView = ViewCreatorManager.CreateMissionView SampleMissionView (false, mission, Array.Empty object ()); mission.AddMissionBehaviour(_missionView); /* mission.AddMissionBehaviour(_missionView = new SampleMissionView()); */ // このサンプルでは、全ての Mission でテスト GUI が表示されてしまいますが、 // 戦闘シーンだけに表示したいなどといった場合、何らかの工夫が必要になるでしょう。 // // ちなみに、OnBeforeMissionBehaviourInitialize() 時点で mission.Mode は MissionMode.StartUp 固定なので、 // 以下の方法は使えませんでした。 /* if (mission.Mode == MissionMode.Battle) { _missionView = ViewCreatorManager.CreateMissionView SampleMissionView (false, mission, Array.Empty object ()); mission.AddMissionBehaviour(_missionView); } */ } // MapScreen (ワールドマップの描画スクリーン) には OnBeforeMissionBehaviourInitialize() に相当する // メソッドが用意されていないので、スクリーンの Push/Pop イベントを利用してレイヤーを挿入しています。 public override void OnGameInitializationFinished(Game game) { base.OnGameInitializationFinished(game); ScreenManager.OnPushScreen += OnScreenManagerPushScreen; // Obsolete /* ScreenManager.OnPopScreen += OnScreenManagerPopScreen; */ } public override void OnGameEnd(Game game) { ScreenManager.OnPushScreen -= OnScreenManagerPushScreen; // Obsolete /* ScreenManager.OnPopScreen -= OnScreenManagerPopScreen; */ base.OnGameEnd(game); } private void OnScreenManagerPushScreen(ScreenBase pushedScreen) { if (pushedScreen is MapScreen mapScreen) { _mapView = mapScreen.AddMapView SampleMapView (Array.Empty object ()); } /* else if (pushedScreen is MissionScreen missionScreen missionScreen.Mission != null) { // MissionScreen は、まず空の MissionScreen を Push してから、ローディング画面を // 表示しつつスクリーンを初期化していく感じなので、MapScreen と同じ手法は使えません。 // // この時点で missionScreen.Mission には中身がないので、CreateMissionView() は失敗します。 _missionView = ViewCreatorManager.CreateMissionView SampleMissionView (false, missionScreen.Mission, Array.Empty object ()); missionScreen.AddMissionView(_missionView); } */ } [Obsolete("1.6.0より前の手法")] private void OnScreenManagerPopScreen(ScreenBase poppedScreen) { if (_mapView != null poppedScreen is MapScreen mapScreen) { // 1.6.0 からは MapScreen が破棄される際に勝手に MapView.OnFinalize() を呼んでくれるようになったので // MapView と MapScreen の寿命を同じにする限りでは、MapScreen.RemoveMapView() をする必要がなくなりました。 mapScreen.RemoveMapView(_mapView); _mapView = null; } else if (_missionView != null poppedScreen is MissionScreen) { // MissionView については、MissionScreen.OnEndMission() が OnMissionScreenFinalize() の呼び出しから // RemoveMissionBehaviour() まで勝手にやってくれます。 _missionView = null; } // したがって、_mapView と _missionView はもはや必要のないフィールドなのですが、説明用に残してあります。 } }} +SampleMapView.cs using ExampleUI.ViewModels;using SandBox.View.Map;using TaleWorlds.Engine.GauntletUI;using TaleWorlds.GauntletUI.Data;using TaleWorlds.InputSystem;using TaleWorlds.Library; namespace ExampleUI.Views{ public class SampleMapView MapView { private TestWindowVM _dataSource; private GauntletLayer _gauntletLayer; private IGauntletMovie _gauntletMovie; protected override void CreateLayout() { base.CreateLayout(); _dataSource = new TestWindowVM(); // localOrder (レイヤーの優先度) が小さいほど、他のレイヤーより下 (画面奥) に描画されます。 // // 例えば、部隊が町などに入った際に左に表示されるメニュー (GauntletMenuBase) のレイヤー優先度は 100 なので、 // それより小さい値に設定すればテストウィンドウがメニューの下に表示されるようになります。 // ESC メニュー (GauntletMapEscapeMenu) のレイヤー優先度が 4400 なので、これよりは小さい値に // した方がよさそうです。あるいは、ESC メニュー表示中は GUI を非表示にする処理を追加しましょう。 _gauntletLayer = new GauntletLayer(4000); Layer = _gauntletLayer; // Movie (= Screen に投影するもの) とは、XML から取得した UI の構造と、ViewModel (表示するデータ) を合わせた概念です。 _gauntletMovie = _gauntletLayer.LoadMovie("ExampleUI.Window", _dataSource); // このレイヤーの描画領域に対して行われた入力のうち、受け取るものをビットフラグによって管理しています。 _gauntletLayer.InputRestrictions.SetInputRestrictions(true, InputUsageMask.MouseButtons); MapScreen.AddLayer(_gauntletLayer); } // MapScreen.OnFinalize() によって呼び出されます。 protected override void OnFinalize() { MapScreen.RemoveLayer(_gauntletLayer); _gauntletLayer.InputRestrictions.ResetInputRestrictions(); _gauntletLayer.ReleaseMovie(_gauntletMovie); _gauntletLayer = null; Layer = null; _dataSource.OnFinalize(); base.OnFinalize(); } // 毎ティック行う処理を記述します。 // // dt デルタタイム。前回のティックからの経過時間です。 protected override void OnFrameTick(float dt) { base.OnFrameTick(dt); if (MapScreen.Input.IsKeyPressed(InputKey.Home)) { _dataSource.IsVisible ^= true; // bool 反転 } } }} +SampleMissionView.cs SampleMapView とは使用するメソッドが違うだけで、やっていることは全く同じです。 using ExampleUI.ViewModels;using TaleWorlds.Engine.GauntletUI;using TaleWorlds.GauntletUI.Data;using TaleWorlds.InputSystem;using TaleWorlds.MountAndBlade.View.Missions; namespace ExampleUI.Views{ public class SampleMissionView MissionView { private TestWindowVM _dataSource; private GauntletLayer _gauntletLayer; private IGauntletMovie _gauntletMovie; public override void OnMissionScreenInitialize() { base.OnMissionScreenInitialize(); _dataSource = new TestWindowVM(); // localOrder (レイヤーの優先度) が小さいほど、他のレイヤーより下 (画面奥) に描画されます。 // // ESC メニュー (GauntletMissionEscapeMenu) のレイヤー優先度が 50 なので、 これよりは小さい // した方がよさそうです。あるいは、ESC メニュー表示中は GUI を非表示にする処理を追加しましょう。 _gauntletLayer = new GauntletLayer(40); // Movie (= Screen に投影するもの) とは、XML から取得した UI の構造と、ViewModel (表示するデータ) を合わせた概念です。 _gauntletMovie = _gauntletLayer.LoadMovie("ExampleUI.Window", _dataSource); // このレイヤーの描画領域に対して行われた入力のうち、受け取るものをビットフラグによって管理しています。 /* _gauntletLayer.InputRestrictions.SetInputRestrictions(true, InputUsageMask.MouseButtons); */ // Mission 中はマウスを視点移動や攻撃に使うため、ポインティングデバイスとして使うには、 // 戦闘結果画面において、Tab を押す - リザルトとマウスカーソル表示 - ボタンが押せるようになる // とやっているような感じで、キーボード操作を挟んで切り替える必要があります。 // 今回はそこまで実装していないため、Mission 中は閉じるボタンをクリックできません。 MissionScreen.AddLayer(_gauntletLayer); } // MissionScreen.OnEndMission() によって呼び出されます。 public override void OnMissionScreenFinalize() { MissionScreen.RemoveLayer(_gauntletLayer); _gauntletLayer.ReleaseMovie(_gauntletMovie); _gauntletLayer = null; _dataSource.OnFinalize(); base.OnMissionScreenFinalize(); } // 毎ティック行う処理を記述します。 // // dt デルタタイム。前回のティックからの経過時間です。 public override void OnMissionScreenTick(float dt) { base.OnMissionScreenTick(dt); if (Input.IsKeyPressed(InputKey.Home)) { _dataSource.IsVisible ^= true; // bool 反転 } } }} +TestWindowVM.cs ViewModel とは View を抽象化したものです。今回の例では、 画面左上にウィンドウを表示 ウィンドウの中には閉じるボタン1つだけ 閉じるボタンを押すとウィンドウが閉じる Home キーでも開いたり閉じたりできる というモデルで行きます。 TestWindowVM は View から完全に分離されているので、今回使う2つの View どちらにもそのまま使用できます。 using TaleWorlds.Core;using TaleWorlds.Library;// View-ViewModel の参照を一方向にするため using ExampleUI.Views をやっていません。 namespace ExampleUI.ViewModels{ // ViewModel は全て TaleWorlds.Library.ViewModel を継承して作ります。 // クラス名に VM を付けなければならないという決まりがあるわけではないのですが、 // 公式の ViewModel は全て VM を付けているようなので踏襲しています。 public class TestWindowVM ViewModel { private bool _isVisible; public TestWindowVM() { IsVisible = true; } // ViewModel のプロパティやメソッドは、View の LoadMovie で関連付けられた XML Prefab から参照できます。 // XML の方を見てもらえば、それらがどのように使われているか分かるかと思います。 [DataSourceProperty] public bool IsVisible { get = _isVisible; set { if (_isVisible != value) { _isVisible = value; // このメソッドを呼ぶことで、TestWindowVM にバインディングされた View に対して // TestWindowVM.IsVisible プロパティの変更通知が行き、プロパティを参照している // ウィジェットの方も状態が変化するという仕組みです。 OnPropertyChangedWithValue(value, "IsVisible"); } } } // こちらは値の変更がない固定ラベルなので、set アクセサーや OnPropertyChangedWithValue() は使っていません。 [DataSourceProperty] public string WindowTitle = "Test Window"; // 以前はラベルにも日本語が使えたのですが、1.6.0 から文字化けするようになってしまいました。 [DataSourceProperty] public string CloseButtonLabel = "Close"; // ButtonWidget のクリックイベントに応じて呼ばれるよう、ExampleUI.Window.xml に記述してあります。 public void OnCloseButtonClick() { IsVisible = false; InformationManager.DisplayMessage(new InformationMessage("ウィンドウを閉じました。\n再度開くには Home キーを押してください。")); } }} DataSourceProperty 属性 公式の ViewModel 派生クラスのプロパティにはこの属性を与えられたものが多く見受けられますが、ソースコードを見ても特に何か定義されているわけでもなく、実際、属性を付けても付けなくても動作は変わらないように見えます。唯一、ViewModel.Properties プロパティで DataSourceProperty のリストを作るのに使われているようですが、このプロパティは他からは特に参照されていないようです。一応、XML から参照されるプロパティには全てこの属性を付けてあります。 +ExampleUI.Window.xml ExampleUI で使うウィンドウの Prefab です。 Prefab Window Widget WidthSizePolicy="Fixed" HeightSizePolicy="Fixed" SuggestedWidth="400" SuggestedHeight="300" IsVisible="@IsVisible" Children Standard.Window Parameter.Title="@WindowTitle" Children Standard.PopupCloseButton Parameter.ButtonText="@CloseButtonLabel" Parameter.ButtonAction="OnCloseButtonClick" / /Children /Standard.Window /Children /Widget /Window /Prefab Widget TaleWorlds.GauntletUI.Widget クラスです。Widget クラスは基底クラスとしてデータを保持しているだけで、UI としての機能はありません。ここでは、他の UI をまとめるコンテナとして使っています。 SizePolicy Fixed 指定の幅にしますStretchToParent 親要素の幅に合わせますCoverChildren 子要素を全て表示できる幅にします IsVisible="@IsVisible" 名前が同じで分かりにくいですが、最初の方が Widget クラスのプロパティ、@付きの方がデータソースとなる ViewModel 派生クラス (今回の例で言えば TestWindowVM) のプロパティとなります。このように指定することで、TestWindowVM.IsVisible の中で呼んである ViewModel.OnPropertyChangedWithValue() によって発せられたイベントが Widget に届くようになり、TestWindowVM.IsVisible と Widget.IsVisible が連動するわけです。 Standard.Window と Standard.PopupCloseButton 公式の Prefab を使っています。公式の Prefab も大半は各シチュエーションに特化した大型のものばかりで、そのままでの再利用はしにくいですが、Native\GUI\Prefabs\Standard にあるものは比較的小型で汎用性が高くなっています。 Parameter Standard.Window 等の Prefab では Parameter が宣言されているものがあり、Widget のプロパティに値を渡すのと同じ感覚で、Prefab 自体に値を渡すことができます。Prefab 側では、自分の中の Widget に受け取った値を渡すよう記述されています。 結果 MapScreen MissionScreen 左上にウィンドウっぽいものが表示されています。Prefab を適当に選んだのでデザインがめちゃくちゃですが、画面上にとりあえず何かを表示する例ということで大目に見てください。 手順をおおまかにまとめると、 作りたい UI を考える その構想に沿った GUI の構造 (Prefab) と表示するデータ (ViewModel) を用意する 用意したものを、表示先がワールドマップなら MapView、戦闘などの Mission なら MissionView で LoadMovie() する View をスクリーンに追加する となります。 Opponent Health Bar 今度はもう少し実践的な MOD を作っていきます。見出しが示す通り、戦っている相手の HP バーを表示する MOD です。 イメージとしてはこんな感じ。 OpponentHealthBar プロジェクトSubModule.cs MissionOpponentHealthBar.cs OpponentHealthVM.cs OpponentHealthBar.xml OpponentHealthBar.xml は、 [Bannerlord インストールフォルダー]\Modules\OpponentHealthBar\GUI\Prefabs の中に保存します。 バージョン1 それでは、とりあえず簡単に文字で表示するところから始めてみます。 +SubModule.cs using System;using TaleWorlds.MountAndBlade;using TaleWorlds.MountAndBlade.View.Missions; namespace OpponentHealthBar{ public class SubModule MBSubModuleBase { public override void OnBeforeMissionBehaviourInitialize(Mission mission) { base.OnBeforeMissionBehaviourInitialize(mission); mission.AddMissionBehaviour( ViewCreatorManager.CreateMissionView MissionOpponentHealthBar (false, mission, Array.Empty object ())); } }} +MissionOpponentHealthBar.cs using TaleWorlds.Core;using TaleWorlds.Engine.GauntletUI;using TaleWorlds.GauntletUI.Data;using TaleWorlds.MountAndBlade;using TaleWorlds.MountAndBlade.View.Missions; namespace OpponentHealthBar{ public class MissionOpponentHealthBar MissionView { private OpponentHealthVM _dataSource; private GauntletLayer _gauntletLayer; private IGauntletMovie _gauntletMovie; public MissionOpponentHealthBar() { ViewOrderPriorty = 20; } public override void OnMissionScreenInitialize() { base.OnMissionScreenInitialize(); _dataSource = new OpponentHealthVM(); _gauntletLayer = new GauntletLayer(ViewOrderPriorty); _gauntletMovie = _gauntletLayer.LoadMovie("OpponentHealthBar", _dataSource); MissionScreen.AddLayer(_gauntletLayer); } public override void OnMissionScreenFinalize() { MissionScreen.RemoveLayer(_gauntletLayer); _gauntletLayer.ReleaseMovie(_gauntletMovie); _gauntletLayer = null; _dataSource.OnFinalize(); base.OnMissionScreenFinalize(); } // 画面中央 (マウスカーソルの位置) と、一番手前にある IFocusable なオブジェクトとが交差した瞬間に呼ばれます。 // // agent フォーカスした Agent。シングルプレイだと、おそらく常に Agent.Main (プレイヤーキャラクター) です。 // focusableObject フォーカスされたもの // isInteractable Talk や Use などのインタラクトが可能か // // フォーカスが 10m までしか利かないのは MissionMainAgentInteractionComponent.FocusTick() で // 決められた仕様なのでどうしようもありません。 public override void OnFocusGained(Agent agent, IFocusable focusableObject, bool isInteractable) { base.OnFocusGained(agent, focusableObject, isInteractable); _dataSource.OnFocusChanged(focusableObject); } // 今までフォーカスされていた IFocusable なオブジェクトから、フォーカスが外れた瞬間に呼ばれます。 // // agent フォーカスしていた Agent。シングルプレイだと、おそらく常に Agent.Main (プレイヤーキャラクター) です。 // focusableObject フォーカスされていたもの public override void OnFocusLost(Agent agent, IFocusable focusableObject) { base.OnFocusLost(agent, focusableObject); _dataSource.OnFocusChanged(focusableObject); } // Agent が何らかの攻撃を受けた際に呼ばれます。 // // affectedAgent 攻撃を受けた Agent // affectorAgent 攻撃を行った Agent // damage ダメージ量 // affectorWeapon 使用された武器 public override void OnAgentHit(Agent affectedAgent, Agent affectorAgent, int damage, in MissionWeapon affectorWeapon) { base.OnAgentHit(affectedAgent, affectorAgent, damage, affectorWeapon); _dataSource.OnAgentHit(affectedAgent); } // Agent が戦闘不能になった際に呼ばれます。 // // affectedAgent 攻撃を受けた Agent // affectorAgent 攻撃を行った Agent // agentState Agent の状態 // blow とどめの一撃の内容 // // 似たようなメソッドに OnAgentDeleted がありますが、そちらは // 戦闘不能になって倒れている Agent が時間経過や表示限界により消滅する際に呼ばれるようです。 public override void OnAgentRemoved(Agent affectedAgent, Agent affectorAgent, AgentState agentState, KillingBlow blow) { base.OnAgentRemoved(affectedAgent, affectorAgent, agentState, blow); _dataSource.OnAgentRemoved(affectedAgent); } }} +OpponentHealthVM.cs 今度のモデルは、 Agent (Mission 中に動きうるもの) の HP 現在値/最大値 を文字で表示する Agent にフォーカスが合うと表示、フォーカスが外れると非表示 とします。 using System;using TaleWorlds.Library;using TaleWorlds.MountAndBlade; namespace OpponentHealthBar{ public class OpponentHealthVM ViewModel { private Agent _opponent; private string _strValues; private bool _isVisible; private const string ValueFormat = "{0} / {1}"; public OpponentHealthVM() { _opponent = null; _strValues = string.Empty; _isVisible = false; } [DataSourceProperty] public string StrValues { get = _strValues; private set { if (_strValues != value) { _strValues = value; OnPropertyChangedWithValue(value, "StrValues"); } } } [DataSourceProperty] public bool IsVisible { get = _isVisible; set { if (_isVisible != value) { _isVisible = value; OnPropertyChangedWithValue(value, "IsVisible"); } } } // GUI に表示するデータの更新はこのメソッドで行います。 // ただし、ここに記述すればあとは勝手に更新されていくというものではないので、 // 自分が必要な場所では自分で呼び出さなければなりません。 public override void RefreshValues() { base.RefreshValues(); int currentValue = (int)Math.Ceiling(_opponent?.Health ?? 0f); int maxValue = (int)Math.Ceiling(_opponent?.HealthLimit ?? 0f); StrValues = string.Format(ValueFormat, currentValue, maxValue); IsVisible = _opponent != null; } public void OnFocusChanged(IFocusable focusableObject) { if (focusableObject is Agent possibleOpponent) { _opponent = (_opponent == null || _opponent != possibleOpponent) ? possibleOpponent null; RefreshValues(); } } public void OnAgentHit(Agent affectedAgent) { if (_opponent == affectedAgent) { RefreshValues(); } } public void OnAgentRemoved(Agent removedAgent) { if (_opponent == removedAgent) { // 先にフォーカスロストが発生してここには入らないかも。 OnFocusChanged(removedAgent); } } }} +OpponentHealthBar.xml Prefab Window Widget WidthSizePolicy="Fixed" HeightSizePolicy="Fixed" SuggestedWidth="430" SuggestedHeight="50" HorizontalAlignment="Center" VerticalAlignment="Top" MarginTop="250" IsVisible="@IsVisible" Children TextWidget Text="@StrValues" WidthSizePolicy="CoverChildren" HeightSizePolicy="CoverChildren" HorizontalAlignment="Center" VerticalAlignment="Center" Brush="Tooltip.Text" Brush.FontSize="24" / /Children /Widget /Window /Prefab Alignment 親要素の領域内のどちら側に寄せるかです。親要素より幅が小さい場合にしか効果がありません。この例の TextWidget で言うと、親要素は幅 430、自身は CoverChildren、つまり StrValues が入りきるだけの幅なので機能していますが、これを StretchToParent とかにすると、左寄せや右寄せが機能しなくなります。 Margin Left, Top, Right, Bottom のマージンです。幅+マージンが要素の実際の幅になります。 以上を実行した状態が下の画像です。 ちょっと見にくいですが、画面上部中央に相手の HP 100/100 が表示されていますね。フォーカスを外せば数字は消えます。しかし、今のところ町人だろうが馬だろうが Agent なら何にでも表示されてしまいますので、そこは改良が必要です。 バージョン2 次はバーの導入とその他の改良を行っていきたいと思います。 バー表示に使うのは FillBarWidget です。ソースコードや、FillBarWidget を使用している公式の Prefab を見てみると、FillBarWidget.MaxAmount プロパティと FillBarWidget.InitialAmmount プロパティに値を渡せばとりあえず動きそうです。よって、ViewModel 側でその値を用意してやる必要があります。 +OpponentHealthVM.cs [DataSourceProperty] public int CurrentValue { get = _currentValue; private set { if (_currentValue != value) { _currentValue = value; OnPropertyChangedWithValue(value, "CurrentValue"); } } } [DataSourceProperty] public int MaxValue { get = _maxValue; private set { if (_maxValue != value) { _maxValue = value; OnPropertyChangedWithValue(value, "MaxValue"); } } } // GUI に表示するデータの更新はこのメソッドで行います。 // ただし、ここに記述すればあとは勝手に更新されていくというものではないので、 // 自分が必要な場所では自分で呼び出さなければなりません。 public override void RefreshValues() { base.RefreshValues(); // 元々ローカル変数だったものを、View から参照できるようにプロパティに昇格しました。 CurrentValue = (int)Math.Ceiling(_opponent?.Health ?? 0f); MaxValue = (int)Math.Ceiling(_opponent?.HealthLimit ?? 0f); StrValues = string.Format(ValueFormat, CurrentValue, MaxValue); IsVisible = _opponent != null; } public void OnFocusChanged(IFocusable focusableObject) { // 適切な相手に表示されるよう条件を追加しました。 if (focusableObject is Agent possibleOpponent possibleOpponent.IsHuman possibleOpponent.IsEnemyOf(Agent.Main)) { _opponent = (_opponent == null || _opponent != possibleOpponent) ? possibleOpponent null; RefreshValues(); } } ViewModel にプロパティを追加したので、今度は Prefab を通じてそれらを FillBarWidget に渡します。 +OpponentHealthBar.xml Prefab Window FillBarWidget WidthSizePolicy="Fixed" HeightSizePolicy="Fixed" SuggestedWidth="430" SuggestedHeight="50" HorizontalAlignment="Center" VerticalAlignment="Top" MarginTop="250" ContainerWidget="FillBarContainer" FillWidget="FillVisualParent\FillVisual" MaxAmount="@MaxValue" InitialAmount="@CurrentValue" IsVisible="@IsVisible" Children Widget Id="FillVisualParent" WidthSizePolicy="Fixed" HeightSizePolicy="StretchToParent" SuggestedWidth="400" HorizontalAlignment="Center" VerticalAlignment="Center" MarginTop="10" MarginBottom="10" Sprite="BlankWhiteSquare" Color="#202020A0" Children BrushWidget Id="FillVisual" WidthSizePolicy="Fixed" HeightSizePolicy="StretchToParent" SuggestedWidth="400" HorizontalAlignment="Left" Brush="Mission.MainAgentHUD.HeroHealthBar.Fill" / /Children /Widget Widget Id="FillBarContainer" WidthSizePolicy="StretchToParent" HeightSizePolicy="StretchToParent" Sprite="options_memory_progress_frame" / TextWidget Text="@StrValues" WidthSizePolicy="CoverChildren" HeightSizePolicy="CoverChildren" HorizontalAlignment="Center" VerticalAlignment="Center" PositionYOffset="3" Brush="Tooltip.Text" Brush.FontSize="24" / /Children /FillBarWidget /Window /Prefab FillBarWidget バージョン1ではただの Widget だったトップレベルのウィジェットを FillBarWidget に変更してあります (3行目)。 FillVisual 赤ゲージの Brush を保持した BrushWidget の ID です (9行目)。このように、Widget には任意の ID がつけられます。それによって、他のウィジェットを操作するタイプのウィジェットに対し、操作対象がどれなのか伝えることができます。 ここでは、FillBarWidget.FillWidget プロパティに渡して、FillBarWidget が "FillVisual" の幅を操作できるようにしています。 親要素の "FillVisualParent" はゲージが減った部分を埋める背景画像です。"BlankWhiteSquare" という無地画像を、暗い半透明に着色・透過させて使っています。 FillBarContainer 14行目にある、スプライト画像を保持した Widget の ID です。これを FillBarWidget.ContainerWidget プロパティに渡してバーの枠としています。 ところで、Mission 用の GUI はそのままだとフォトモード中でも表示されてしまいます。構図を決めている間に GUI が表示されてしまうのは邪魔ですから、MissionView を使うときは、フォトモード中 GUI を非表示にする処理を追加しておきましょう。 +MissionOpponentHealthBar.cs // フォトモードで構図を決めている最中に GUI が表示されないようにするための処理です。 // この処理を入れても入れなくても、どちらにしろ出力される画像ファイルに GUI は写りません。 public override void OnPhotoModeActivated() { base.OnPhotoModeActivated(); _gauntletLayer._gauntletUIContext.ContextAlpha = 0f; } public override void OnPhotoModeDeactivated() { base.OnPhotoModeDeactivated(); _gauntletLayer._gauntletUIContext.ContextAlpha = 1f; } 結果 攻撃前 攻撃後 どうでしょう、一応 HP バーらしくなったのではないでしょうか。 他にも、与えたダメージ分のバーをスライドさせる視覚効果とか、フォーカスが外れてからバーが消えるまでに時間差を設けるとか、改良はいろいろ考えられますが、サンプルではここまでです。興味があったら自分の MOD として実装してみてください。 +コード最終形 SubModule.cs using System;using TaleWorlds.MountAndBlade;using TaleWorlds.MountAndBlade.View.Missions; namespace OpponentHealthBar{ public class SubModule MBSubModuleBase { public override void OnBeforeMissionBehaviourInitialize(Mission mission) { base.OnBeforeMissionBehaviourInitialize(mission); mission.AddMissionBehaviour( ViewCreatorManager.CreateMissionView MissionOpponentHealthBar (false, mission, Array.Empty object ())); } }} MissionOpponentHealthBar.cs using TaleWorlds.Core;using TaleWorlds.Engine.GauntletUI;using TaleWorlds.GauntletUI.Data;using TaleWorlds.MountAndBlade;using TaleWorlds.MountAndBlade.View.Missions; namespace OpponentHealthBar{ public class MissionOpponentHealthBar MissionView { private OpponentHealthVM _dataSource; private GauntletLayer _gauntletLayer; private IGauntletMovie _gauntletMovie; public MissionOpponentHealthBar() { ViewOrderPriorty = 20; } public override void OnMissionScreenInitialize() { base.OnMissionScreenInitialize(); _dataSource = new OpponentHealthVM(); _gauntletLayer = new GauntletLayer(ViewOrderPriorty); _gauntletMovie = _gauntletLayer.LoadMovie("OpponentHealthBar", _dataSource); MissionScreen.AddLayer(_gauntletLayer); } public override void OnMissionScreenFinalize() { MissionScreen.RemoveLayer(_gauntletLayer); _gauntletLayer.ReleaseMovie(_gauntletMovie); _gauntletLayer = null; _dataSource.OnFinalize(); base.OnMissionScreenFinalize(); } // 画面中央 (マウスカーソルの位置) と、一番手前にある IFocusable なオブジェクトとが交差した瞬間に呼ばれます。 // // agent フォーカスした Agent。シングルプレイだと、おそらく常に Agent.Main (プレイヤーキャラクター) です。 // focusableObject フォーカスされたもの // isInteractable Talk や Use などのインタラクトが可能か // // フォーカスが 10m までしか利かないのは MissionMainAgentInteractionComponent.FocusTick() で // 決められた仕様なのでどうしようもありません。 public override void OnFocusGained(Agent agent, IFocusable focusableObject, bool isInteractable) { base.OnFocusGained(agent, focusableObject, isInteractable); _dataSource.OnFocusChanged(focusableObject); } // 今までフォーカスされていた IFocusable なオブジェクトから、フォーカスが外れた瞬間に呼ばれます。 // // agent フォーカスしていた Agent。シングルプレイだと、おそらく常に Agent.Main (プレイヤーキャラクター) です。 // focusableObject フォーカスされていたもの public override void OnFocusLost(Agent agent, IFocusable focusableObject) { base.OnFocusLost(agent, focusableObject); _dataSource.OnFocusChanged(focusableObject); } // Agent が何らかの攻撃を受けた際に呼ばれます。 // // affectedAgent 攻撃を受けた Agent // affectorAgent 攻撃を行った Agent // damage ダメージ量 // affectorWeapon 使用された武器 public override void OnAgentHit(Agent affectedAgent, Agent affectorAgent, int damage, in MissionWeapon affectorWeapon) { base.OnAgentHit(affectedAgent, affectorAgent, damage, affectorWeapon); _dataSource.OnAgentHit(affectedAgent); } // Agent が戦闘不能になった際に呼ばれます。 // // affectedAgent 攻撃を受けた Agent // affectorAgent 攻撃を行った Agent // agentState Agent の状態 // blow とどめの一撃の内容 // // 似たようなメソッドに OnAgentDeleted がありますが、そちらは // 戦闘不能になって倒れている Agent が時間経過や表示限界により消滅する際に呼ばれるようです。 public override void OnAgentRemoved(Agent affectedAgent, Agent affectorAgent, AgentState agentState, KillingBlow blow) { base.OnAgentRemoved(affectedAgent, affectorAgent, agentState, blow); _dataSource.OnAgentRemoved(affectedAgent); } // フォトモードで構図を決めている最中に GUI が表示されないようにするための処理です。 // この処理を入れても入れなくても、どちらにしろ出力される画像ファイルに GUI は写りません。 public override void OnPhotoModeActivated() { base.OnPhotoModeActivated(); _gauntletLayer._gauntletUIContext.ContextAlpha = 0f; } public override void OnPhotoModeDeactivated() { base.OnPhotoModeDeactivated(); _gauntletLayer._gauntletUIContext.ContextAlpha = 1f; } }} OpponentHealthVM.cs using System;using TaleWorlds.Library;using TaleWorlds.MountAndBlade; namespace OpponentHealthBar{ public class OpponentHealthVM ViewModel { private Agent _opponent; private int _currentValue; private int _maxValue; private string _strValues; private bool _isVisible; private const string ValueFormat = "{0} / {1}"; public OpponentHealthVM() { _opponent = null; _strValues = string.Empty; _isVisible = false; } [DataSourceProperty] public int CurrentValue { get = _currentValue; private set { if (_currentValue != value) { _currentValue = value; OnPropertyChangedWithValue(value, "CurrentValue"); } } } [DataSourceProperty] public int MaxValue { get = _maxValue; private set { if (_maxValue != value) { _maxValue = value; OnPropertyChangedWithValue(value, "MaxValue"); } } } [DataSourceProperty] public string StrValues { get = _strValues; private set { if (_strValues != value) { _strValues = value; OnPropertyChangedWithValue(value, "StrValues"); } } } [DataSourceProperty] public bool IsVisible { get = _isVisible; set { if (_isVisible != value) { _isVisible = value; OnPropertyChangedWithValue(value, "IsVisible"); } } } // GUI に表示するデータの更新はこのメソッドで行います。 // ただし、ここに記述すればあとは勝手に更新されていくというものではないので、 // 自分が必要な場所では自分で呼び出さなければなりません。 public override void RefreshValues() { base.RefreshValues(); // 元々ローカル変数だったものを、View から参照できるようにプロパティに昇格しました。 CurrentValue = (int)Math.Ceiling(_opponent?.Health ?? 0f); MaxValue = (int)Math.Ceiling(_opponent?.HealthLimit ?? 0f); StrValues = string.Format(ValueFormat, CurrentValue, MaxValue); IsVisible = _opponent != null; } public void OnFocusChanged(IFocusable focusableObject) { // 適切な相手に表示されるよう条件を追加しました。 if (focusableObject is Agent possibleOpponent possibleOpponent.IsHuman possibleOpponent.IsEnemyOf(Agent.Main)) { _opponent = (_opponent == null || _opponent != possibleOpponent) ? possibleOpponent null; RefreshValues(); } } public void OnAgentHit(Agent affectedAgent) { if (_opponent == affectedAgent) { RefreshValues(); } } public void OnAgentRemoved(Agent removedAgent) { if (_opponent == removedAgent) { // 先にフォーカスロストが発生してここには入らないかも。 OnFocusChanged(removedAgent); } } }} OpponentHealthBar.xml Prefab Window FillBarWidget WidthSizePolicy="Fixed" HeightSizePolicy="Fixed" SuggestedWidth="430" SuggestedHeight="50" HorizontalAlignment="Center" VerticalAlignment="Top" MarginTop="250" ContainerWidget="FillBarContainer" FillWidget="FillVisualParent\FillVisual" MaxAmount="@MaxValue" InitialAmount="@CurrentValue" IsVisible="@IsVisible" Children Widget Id="FillVisualParent" WidthSizePolicy="Fixed" HeightSizePolicy="StretchToParent" SuggestedWidth="400" HorizontalAlignment="Center" VerticalAlignment="Center" MarginTop="10" MarginBottom="10" Sprite="BlankWhiteSquare" Color="#202020A0" Children BrushWidget Id="FillVisual" WidthSizePolicy="Fixed" HeightSizePolicy="StretchToParent" SuggestedWidth="400" HorizontalAlignment="Left" Brush="Mission.MainAgentHUD.HeroHealthBar.Fill" / /Children /Widget Widget Id="FillBarContainer" WidthSizePolicy="StretchToParent" HeightSizePolicy="StretchToParent" Sprite="options_memory_progress_frame" / TextWidget Text="@StrValues" WidthSizePolicy="CoverChildren" HeightSizePolicy="CoverChildren" HorizontalAlignment="Center" VerticalAlignment="Center" PositionYOffset="3" Brush="Tooltip.Text" Brush.FontSize="24" / /Children /FillBarWidget /Window /Prefab 名前
https://w.atwiki.jp/fuyuuutuly/pages/21.html
覚えてる範囲でべたべたと。 おすすめできるmod prelude アクション ★★★★★ 謎解き ★★★★★ http //www.moddb.com/mods/portal-prelude 言わずと知れた名作 Glados完成前のストーリーが描かれているがとんでもなく難易度が高い 半ポータル使ってもあんまり簡単にならないので遠慮なく使おう ※日本語化できます flash mappack アクション ★★★☆☆ 謎解き ★★★☆☆ http //www.moddb.com/mods/portal-the-flash-version-mod flash版の2DPortalを再現したmodということになっているが もはや全然ちがう作品に仕上がっている。 シンプルでありながらちゃんと驚きもあっておすすめです。 gamma energy アクション ★★★☆☆ 謎解き ★★★★☆ http //www.moddb.com/mods/gamma-energy 大ボリュームのmod 難易度もそこそこで面白いです。 ただ上級チェンバーは絶対クリアできないと思っています portalpro アクション ★★★★☆ 謎解き ★★★★★ http //www.moddb.com/mods/portal-pro 謎解き難易度がすごく高い素晴らしいmod シークレットケーキの隠し場所が秀逸で、 またそれを集めるとボーナスマップまで遊べる! rexaura アクション ★★★☆☆ 謎解き ★★★★★ http //www.moddb.com/mods/rexaura これも謎解き重視のmod 永続ボールの使い方がうまい! その他 conundrum lovegrados ABtest(面白いです!) portal unity(う、うーん) blue portal(お、おう) aperture dejavu(バグだらけで諦めた) portal new adventure(短いしつまんない) the projex(グラフィックはすごい) Hetzchase Nailway(バグだらけだ) portality(微妙) CWTH(これはひどい)
https://w.atwiki.jp/akasatanahama/pages/143.html
概要 メタデータを付与したアイテムを追加する。 ソースコード AluminiumMod.java package com.tntmodders.tutorial; import net.minecraft.block.Block; import net.minecraft.client.renderer.block.model.ModelResourceLocation; import net.minecraft.item.Item; import net.minecraft.item.ItemBlock; import net.minecraft.util.ResourceLocation; import net.minecraftforge.client.event.ModelRegistryEvent; import net.minecraftforge.client.model.ModelLoader; import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.event.RegistryEvent; import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.common.event.FMLConstructionEvent; import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; @Mod(modid = "aluminiummod", version = "1.0", name = "AluminiumMod") public class AluminiumMod { @Mod.Instance("aluminiummod") public static AluminiumMod aluminiumInstance; public static final Item COLOR_ALUMINIUM = new ItemColorAluminium(); @Mod.EventHandler public void construct(FMLConstructionEvent event) { MinecraftForge.EVENT_BUS.register(this); } @SubscribeEvent public void registerItems(RegistryEvent.Register Item event) { event.getRegistry().register(COLOR_ALUMINIUM); } @SubscribeEvent @SideOnly(Side.CLIENT) public void registerModels(ModelRegistryEvent event) { //メタデータの分だけモデルを登録する。 for(int i = 0; i 16; i++){ ModelLoader.setCustomModelResourceLocation(COLOR_ALUMINIUM, i, new ModelResourceLocation(new ResourceLocation("aluminiummod", "color_aluminium_" + i), "inventory")); } } ItemColorAluminium.java package com.tntmodders.tutorial; import net.minecraft.creativetab.CreativeTabs; import net.minecraft.item.EnumDyeColor; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.util.NonNullList; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; public class ItemColorAluminium extends Item { public ItemColorAluminium() { super(); this.setRegistryName("aluminiummod", "color_aluminium"); this.setCreativeTab(CreativeTabs.MATERIALS); this.setUnlocalizedName("color_aluminium"); //メタデータありのアイテムとして登録する。 this.setHasSubtypes(true); this.setMaxDamage(0); } //翻訳名を変更する。後ろに.nameが着くためその前まで。 public String getUnlocalizedName(ItemStack stack) { int i = stack.getMetadata(); return "item.color_aluminium." + i; } //クリエイティブタブに複数のアイテムを登録する。 @SideOnly(Side.CLIENT) public void getSubItems(CreativeTabs tab, NonNullList ItemStack items) { if (this.isInCreativeTab(tab)) { for (int i = 0; i 16; ++i) { items.add(new ItemStack(this, 1, i)); } } } } アセット color_aluminium_0.json メタデータ0のもののみサンプルとして示す。今回はテクスチャはアルミニウムと同じものを使う。 メタデータを変更したモデルも作る必要があり、これは最後の数字をメタデータに対応させれば良い。 src/main/resources/assets/aluminiummod/models/item/に配置する { "parent" "item/generated", "textures" { "layer0" "aluminiummod items/color_aluminium_0" } } en_US.lang src/main/resources/assets/aluminiummod/lang/に配置する #AluminiumMod English Langage File item.color_aluminium.0.name=white colored aluminium item.color_aluminium.1.name=orange colored aluminium item.color_aluminium.2.name=magenta colored aluminium item.color_aluminium.3.name=light blue colored aluminium item.color_aluminium.4.name=yellow colored aluminium item.color_aluminium.5.name=lime colored aluminium item.color_aluminium.6.name=pink colored aluminium item.color_aluminium.7.name=gray colored aluminium item.color_aluminium.8.name=sliver colored aluminium item.color_aluminium.9.name=cyan colored aluminium item.color_aluminium.10.name=purple colored aluminium item.color_aluminium.11.name=blue colored aluminium item.color_aluminium.12.name=brown colored aluminium item.color_aluminium.13.name=green colored aluminium item.color_aluminium.14.name=red colored aluminium item.color_aluminium.15.name=black colored aluminium ja_JP.lang src/main/resources/assets/aluminiummod/lang/に配置する #アルミニウムMOD 日本語言語ファイル item.color_aluminium.0.name=白色アルミニウム item.color_aluminium.1.name=橙色アルミニウム item.color_aluminium.2.name=紅紫色アルミニウム item.color_aluminium.3.name=空色アルミニウム item.color_aluminium.4.name=黄色アルミニウム item.color_aluminium.5.name=黄緑色アルミニウム item.color_aluminium.6.name=桃色アルミニウム item.color_aluminium.7.name=灰色アルミニウム item.color_aluminium.8.name=銀色アルミニウム item.color_aluminium.9.name=青緑色アルミニウム item.color_aluminium.10.name=紫色アルミニウム item.color_aluminium.11.name=青色アルミニウム item.color_aluminium.12.name=茶色アルミニウム item.color_aluminium.13.name=緑色アルミニウム item.color_aluminium.14.name=赤色アルミニウム item.color_aluminium.15.name=黒色アルミニウム 解説 AluminiumMod.java ここはだいたいアイテム追加と一緒。モデルの登録だけメタデータ分やろう。 ItemColorAluminium.java setHasSubtypes(boolean hasSubTypes) メタデータを持つアイテムということを登録する。デフォルトでfalseになっているため、コンストラクターでtrueにしてやる。 public String getUnlocalizedName(ItemStack stack) 翻訳名を指定するメソッド。 ここでは"item. 翻訳名 .name"の中の".name"を除いた文字列を返す。 その為、翻訳名をメタデータに依存するものにする場合はItemStackから取ったメタデータを使って末尾に数値をつける。 public void getSubItems(CreativeTabs tab, NonNullList ItemStack items) アイテムをクリエイティブに登録する。ここでメタデータを含むアイテムスタックを登録することが出来る。 因みに、ここでアイテムスタックに対してエンチャントやデータを付与できる。 +ここではシルクタッチのエンチャントを付与し、更にクリエイティブタブで64個スタックされた状態にしている。 @SideOnly(Side.CLIENT) public void getSubItems(CreativeTabs tab, NonNullList ItemStack items) { if (this.isInCreativeTab(tab)) { for (int i = 0; i 16; ++i) { ItemStack itemStack = new ItemStack(this, 1, i); itemStack.addEnchantment(Enchantments.SILK_TOUCH,1); itemStack.setCount(64); items.add(itemStack); } } } color_aluminium_ メタデータ .json 各メタデータごとにテクスチャを指定するモデルを作る。 コメント この項目に関する質問などをどうぞ。 名前
https://w.atwiki.jp/protot/pages/92.html
MOD導入方法 はじめに MOD導入方法 はじめに PC版Prototypeを日本語化することが可能になりました。 日本語化は現在進行形です。実質的に停止(最終更新:2010年12月30日) 未完成、一部のみ翻訳済みです。 スクリーンショット MOD導入方法 日本語化MODをダウンロードし、同梱されているScarfaceExplorer.exeを起動する。 Prototypeがインストールされたフォルダにある以下のデータファイルを開き、[Extract]→[All Files...]を選択、Prototypeのインストールフォルダを指定して[OK]を押すと、ファイル内のデータが展開される。 00audio.rcf 00woi.rcf 01audio.rcf 01woi.rcf 02woi.rcf 03woi.rcf art.rcf movies.rcf 上記のファイルを全て展開し、art、audio(最初からあるので、フォルダ内にファイルが追加されているかどうか確認)、moviesというフォルダが生成されていればOK。 各ファイルを展開したら、元の~.rcfのファイル名を全て変更する。(例:~.rcf_bakなど) 元のファイルが無いと、Prototypeは各art、audio、moviesなどのフォルダの中身を読み込んで動作するようになる。 日本語MODに同梱されている fonts_latin.gfx を、Prototype内の art\hud\ フォルダにコピー(上書き)する。 これでゲーム内の表示が日本語フォントに置き換わり、文字の形が変わればOK。 最後に、日本語に翻訳されたデータファイルを各フォルダ(art、audio、movies)内へコピー(上書き)すれば、ゲーム内の表示が日本語化される。 ■2011/8/21追記 日本語MOD同梱のfonts_latin.gfxでは一部文字化けが発生するようです。 翻訳作業中に文字化けが判明した文字をいくらか修正(追加)したものがアップされました。 このファイルを解凍し、中にあるfonts_latin.gfxと差し替えて下さい。 ※これは「ゲームに関する質問」2011-08-20 14 43 32の書き込みと同じものです。
https://w.atwiki.jp/darwinian/pages/29.html
公式MOD製作フォーラム http //forums.introversion.co.uk/darwinia/viewforum.php?f=12? The Next Game http //thenextgame.co.uk/? Nihils Darwinia Modding Pages http //www.nihilesthetics.info/DarwiniaModding/ModdingDarwinia.htm? stellarmatter.net http //stellarmatter.net/? Darwinia Shape Marker List http //www.cyberdyne.homecall.co.uk/shape_index.htm? darwikia http //freepgs.com/trickfred/darwikia/index.php?
https://w.atwiki.jp/ukwindom/pages/33.html
■MODって何ぞや? MOD(モッド,Modification)とは主にパーソナルコンピュータ用ゲームソフトの簡易拡張パックのこと。 MODを導入することによって、そのゲームソフトのグラフィックエンジン、 物理エンジンなどの基本システムを用いて、本編とは別のシナリオや グラフィック、モデル、システムのゲームを楽しむことができる。(ウィキペディア引用) ■結局何が出来るの? 簡単に言えばウィンダムXPでガンダムや他のロボットアニメのパイロットや機体を使って遊ぼうという事です。 どうですか、楽しそうでしょ? imageプラグインエラー ご指定のURLはサポートしていません。png, jpg, gif などの画像URLを指定してください。 現在、機体のモーションやパラメーターまで変更できるようになり、モデルの入れ替え以上のことが出来るようになってる。 ただそれを行える人は少なく、既存のMODは変更されていないものが多い。可能性は未知数である。 ■どうやるの? 左のメニューから好きなものを選んで指示通りの場所に入れるだけ! なんと簡単。でもバックアップはしっかりとね!
https://w.atwiki.jp/00ads/pages/15.html
ここでは、戦闘に役に立つ・・・かもしれないオヌヌメMODを紹介します Metal Gear Solid 6th sense with sounds http //www.curse.com/wot-mods/worldoftanks/metal-gear-solid-6th-sense-sound 「第六感」スキルが発動すると、メタルギアソリッドの発見マークと音(プイン!)と鳴るMOD。 XVMがない場合は、発見マークのみだがXVMを導入していると音までなるので、バカでも発見状態が即座にわかります。 発見されまくると、鳴り止まないのでちょっとイラッ!と来るのがポイント(´・ω・`) ・・・だが、それがいい!(`・ω・´)b 日本戦車用デカール変更MOD http //forum.worldoftanks.asia/index.php?/topic/29039-%E6%97%A5%E6%9C%AC%E6%88%A6%E8%BB%8A%E7%94%A8%E3%83%87%E3%82%AB%E3%83%BC%E3%83%AB%E5%A4%89%E6%9B%B4mod/ 日本戦車の国籍デカールを日本国旗から変更できるMOD お手軽かつ士気があがります・・・たぶん
https://w.atwiki.jp/mod-jplang/pages/75.html
Industrial Craft 2 Classic mod説明 工業要素追加 IC2Cの日本語langファイル置き場です。 下にバージョンのリンクがあるのでそこから飛んでください。 ↓リンク↓ MC1.7.10 MC1.19.2 wiki_ja_jp.json
https://w.atwiki.jp/hotspas/pages/1334.html
川内温泉をお気に入りに追加 くちこみリンク #blogsearch #technorati キャッシュ 使い方 サイト名 URL 掲示板 名前(HN) カキコミ すべてのコメントを見る 報道 ライトアップ、鹿児島県日置市とJシステム(助成金自動診断システム)のOEM提供による、中小企業の共同支援を開始 - PR TIMES 地元特産品の魅力を再確認!株式会社WIN-WIN(新潟県阿賀野市)がおすすめする「ふるさと納税」返礼品 - にいがた経済新聞 福島で初氷 県内冷え込む - 読売新聞 〈理沙のスプリングス日記(8)〉ユーチューブ配信に挑戦 - 佐賀新聞LiVE 鹿児島県で作る愛犬のための究極ごはん”Buddy FOOD”、鹿児島県薩摩川内市のふるさと納税返礼品に - PR TIMES ワールドシェアセリングは、熊本県・津奈木町のワーケーション事業「いろいろ旅の宿and温泉まがりオフィス」の『トレーラーハウス』を担当します - 西日本新聞 <7>福島に魅了され移住 - 読売新聞 いい湯だな 渋柿だって甘くなる温泉パワー | 鹿児島のニュース - 南日本新聞 熊本県津奈木町で様々な宿泊体験とワーケーションの実証事業「いろいろ旅の宿and温泉まがりオフィス」 を開始! - 西日本新聞 嬉野温泉旅館「和多屋別荘」7施設同時開業/リニューアル 2021.11.3(水・祝)午前9時 同時オープン!! - 西日本新聞 『ラジエーションハウス』第5話 “唯織”窪田正孝、“杏”本田翼ら温泉付き高級旅館でトラブル (2021年11月1日) - エキサイトニュース 鹿児島県と鹿児島県オールトヨタ(※)によるプロジェクト「フォトドラ~かごしまフォトドライブプロジェクト~」鹿児島の観光資源を再発見・発掘するフォトドラアワード認定発足より2年で100スポット達成! - アットプレス(プレスリリース) 玄海原発「停止を」6割 世論調査、自民支持層も「目標時期決め」最多 - 西日本新聞 台湾の若者ら福島第1原発を視察 復興状況を発信(共同通信) - Yahoo!ニュース - Yahoo!ニュース 新駅効果どこまで…活性化策手探り 西九州新幹線、協議難航 - 西日本新聞 寒さじわり 秋色もうすぐ|愛媛新聞ONLINE - 愛媛新聞 札幌創成、全道高校駅伝札幌創成の6連覇阻むぞ「チームベストを目指して」 - ニッカンスポーツ 東武特急スペーシア「JR八王子乗り入れ」再び 鬼怒川温泉発着 冬の臨時列車で (2021年10月15日) - エキサイトニュース 九州電力、川内原発の「特別点検」実施へ…40年超の運転延長申請に向け - 読売新聞 温泉磨いて心を磨く- これぞ「浴育」 霧島で児童がボランティア清掃 | 鹿児島のニュース - 南日本新聞 先生の保養所さよなら 宇奈月・ホテル渓仙 来年3月閉館 利用減、44年の歴史に幕(北國新聞社) - Yahoo!ニュース - Yahoo!ニュース 京都でシャンパーニュと天然温泉を楽しみ尽くす「HOTEL THE MITSUI KYOTO」宿泊プラン (2021年10月10日) - エキサイトニュース 北陸新幹線 加賀温泉駅 アンベール! (2021年10月9日) - エキサイトニュース 足場解体作業の休憩中、作業服のまま川で泳ぎ溺れる 男性死亡 鹿児島・薩摩川内市(南日本新聞) - Yahoo!ニュース - Yahoo!ニュース 宮崎県日南市で震度4 - 日南テレビ! 【鹿児島】大島がサヨナラ勝ち! 川内、鹿児島玉龍は逆転勝ち<3日の結果>(高校野球ドットコム) - Yahoo!ニュース - Yahoo!ニュース 高校生は見た! うまいもの、名所 「鹿児島盛り上げ隊」がインスタ発信 鹿児島情報高 | 鹿児島のニュース - 南日本新聞 濁流に襲われた昭和の共同浴場…解体決意一転、活用の道探る3代目 - 西日本新聞 京セラが半導体関連部品に1000億円投資。その全容(ニュースイッチ) - Yahoo!ニュース - Yahoo!ニュース 「川内大綱引 来年こそ」 開催願い神事 - 読売新聞 日本酒どころで広がるワインづくり 県産ブドウ使い地域興し狙う - 朝日新聞デジタル 歴史豊か 明日香駆けて - 読売新聞 飲酒運転し死亡事故、自衛官を懲戒免職 陸自川内駐屯地 鹿児島 - 47NEWS 「かわうち恵の水」完成 福島・川内村の自然を広く発信 - 47NEWS 新幹線の新たな最西端、ホームから港が見える駅デザインの妙 | 鉄道コラム - 鉄道チャンネル 「久しぶり。気持ちよか」泉源復活で再起誓う 雲仙温泉街に湯煙戻る - 西日本新聞 その狭さ、独房レベル 有馬温泉の「訳アリ」客室が超人気→なぜこんな部屋が?支配人に聞いた - ニフティニュース 愛媛のおすすめパワースポット5選!運気アップはここ - DO?GO!愛媛 JR九州、嬉野に温泉宿泊施設開発へ 新幹線との相乗効果期待 23年度の開業目指す - 西日本新聞 「大きな固まり」になれない…旧立民と旧国民が平行線、立民県連組織を設立できず - 読売新聞 【京都市場】サウナ付日帰り温泉併設☆長雨に備え地産地消の旬野菜「じねんと市場」 (2021年8月21日) - エキサイトニュース 大雨とコロナのダブルパンチ…キャンセル相次ぐ観光地 - 西日本新聞 雲仙老舗ホテル止まった泉源…予約100組に断りの電話 - 西日本新聞 茶畑や温泉宿で被害 のり面崩落や浴場土砂流入 嬉野 /佐賀 - 毎日新聞 JR線 19日も始発から運休・減便多数 九州・四国・中国 依然つづく大雨で 新幹線は通常運行 - 乗りものニュース 【2021年9月グランドオープン】関西初のプライベートプール付テント、コネクトドームを配置した「琵琶湖グランピング グランピングヴィレッジ滋賀今津浜」オープンのお知らせ - PR TIMES 2021春夏 鹿児島おでかけスポットコレクション by フェリアインスタ | Felia! - 南日本新聞 競技5日目、個人戦男子ダブルスのベスト8が出揃う [総体テニス](テニスマガジンONLINE) - Yahoo!ニュース - Yahoo!ニュース 複合拠点施設「川内駅パーク」開業 - 読売新聞 【銭湯 湯悠散歩】バラエティー豊かな風呂に、ドライサウナも 東京・有明「泉天空の湯 有明ガーデン」 - ZAKZAK JR九州の西九州新幹線 来年秋開業、懸案抱えたまま工事急ピッチ - 日経ビジネスオンライン 九州各県在住者限定!『やまが温泉郷 湯ったりキャンペーン』2021年7月20日(火)からスタート! - 西日本新聞 鵜飼い「もう限界」豪雨、コロナ…漁に出られず1年超 - 西日本新聞 「ほうじょう温泉 ふじ湯の里」×「九州筑豊ラーメン山小屋ふじ湯の里店」コラボレーション企画! - 西日本新聞 西日本各地でゲリラ雷雨 激しい雨や雷、雹の所も(ウェザーニュース) - Yahoo!ニュース - Yahoo!ニュース 川内優輝、5000mで13分台の力走…マラソン「2時間5分台目指したい」 - 読売新聞 熊本豪雨1年、熊本地震5年、雲仙火砕流30年を迎え、火山地域の防災を考える(福和伸夫) - 個人 - Yahoo!ニュース - Yahoo!ニュース 大雨 被害に関する情報まとめ 鹿児島 宮崎 熊本 - NHK NEWS WEB 自宅前は「まるで海」、斜面崩れて大岩ゴロゴロ…不安と恐怖の九州大雨 - 読売新聞 4温泉地「一緒ににぎわい取り戻す」 大分の記録的豪雨から1年 - 西日本新聞 天ケ瀬の旅館、進むために壊した“わが家”に「ありがとう」 - 西日本新聞 再稼働はどうなる?泊原発の審査の行方 - nhk.or.jp 青学・近藤が男子5000で日本人トップ…ホクレンDC開幕 - 読売新聞 児童11人の個人情報入りDVD、不要パソコンに挿入したまま回収業者に - 47NEWS 【話の肖像画】ジャパネットたかた創業者・高田明(72)(13)大一番で始まった佐世保の生活 - 産経ニュース 古民家、温泉で休んで働く うきは市、「ワーケーション」を売り込む - 西日本新聞 石炭火力計画停止解除 夏の電力逼迫備え…九電・苅田新1号機 - 読売新聞 西九州新幹線、動かぬまま1年 国と佐賀県、フル規格巡り平行線続く - 西日本新聞 黒部のウナギを特産に 会議所、地元企業が実行委 温泉水で養殖、加工品開発へ |経済|富山のニュース|富山新聞 - 北國新聞 【復刻】〝灰熱地獄〟に看護師絶叫「今、水を飲んじゃだめ」 普賢岳大火砕流 - 西日本新聞 新しい「地獄」の名前、募集中です - 西日本新聞 「温泉効果」科学で立証へ 九大、別府市、旅館ホテル組合が協定 - 西日本新聞 河合郁人を「温泉知識」と「バキバキボディ」で公開処刑した後輩 (2021年5月19日) - エキサイトニュース 武雄温泉―長崎間の名称は「西九州新幹線」 - 西日本新聞 川内原発1・2号機の「40年超運転」、九電が延長申請手続きへ - 読売新聞 川内優輝選手、こだわり捨て厚底靴に…「現状打破」の挑戦続く - 読売新聞 老舗宿5年ぶり再起の一歩 ライバルに支えられ日帰り湯に転換 - 西日本新聞 村上仁一「地下鉄日記」展がNAKANO GINZA GALLERYと森岡書店にて開催 | NEWS - IMA ONLINE 写真で楽しむ九州の国立公園(北部編):活火山と青い海、島々が織りなす絶景 - Nippon.com ホテルに迷路が出現? 実は… 日田温泉・ひなのさと【動画】 - 西日本新聞 べっぴんの湯、温泉成分を確認 来春一部再開目指す/久慈・新山根温泉 - 47NEWS 写真家・川内倫子が撮る、アイスランドの大地とは?〈日本橋三越本店〉にて個展開催。 - カーサ ブルータス 「旅行客でなく住人として」断捨離のやましたひでこさんが南国・指宿に移り住んだワケ ホテル一室で実践する人生リフレッシュ構想 | 鹿児島のニュース - 南日本新聞 源泉より熱い!温泉街「OKM8」 大分の女将、踊って観光PR - 西日本新聞 「サブ20」100回、ギネス世界記録…川内優輝のマラソンヒストリー - 読売新聞 世界を制した川内優輝 次に目指すは「地域振興型プロランナー」 - 月刊「事業構想」 「芸舞温泉」温泉旅館がゲーム会社のオフィスに - 西日本新聞 福島県・宮城県で震度6強の地震 若干の海面変動あり 震源は福島県沖 M7.3 - ウェザーニュース 九州新幹線、開業10周年で記念きっぷ発売 | RailLab ニュース - レイルラボ 星野リゾート、温泉旅館「界 霧島」を29日開業 鹿児島 - 日本経済新聞 遊郭のどんちゃん騒ぎが聞こえる夜。翌朝、決まって3機編隊の飛行機が基地から飛び立った。早起きした母は空を仰ぐ。手を合わせ、子どもたちに「拝まんか」〈証言 語り継ぐ戦争〉 | 鹿児島のニュース - 南日本新聞 主な施設の年末年始 休園・休館日 - 南日本新聞 ANAに聞く「鹿児島県」。歴史から絶景、温泉まで見どころ豊富。“銭湯+ガストロノミー”を楽しむイベントも - トラベル Watch 〝見えたらラッキー〟虹かかる20メートルの湯柱 - 西日本新聞 五輪延期 大塚祥平がマラソン補欠で前向きになれたわけ - 朝日新聞デジタル “温泉俳優”原田龍二が鹿児島の温泉に全集中!「鹿児島温泉天国 原田龍二の一湯入魂」の第2弾を11月13日に放送! - アットプレス(プレスリリース) 佐賀にあった「幻の鉄道」 運行わずか16年…面影をたどってみた - 西日本新聞 【鹿児島県・川内高城温泉】500円で絶景&グルメ&温泉を満喫できる神イベントに参加してきた! - https //onsenbu.net/ あの西郷隆盛が愛した温泉。鹿児島・霧島の名湯秘湯7選 - 南日本新聞 先代は「幽霊」とまで言われ…西郷どん、たくましく復活 - 朝日新聞デジタル版 成分解析 川内温泉の92%は汗と涙(化合物)で出来ています。川内温泉の4%は波動で出来ています。川内温泉の2%は怨念で出来ています。川内温泉の1%はマイナスイオンで出来ています。川内温泉の1%は勇気で出来ています。 ウィキペディア 川内温泉 Amazon.co.jp ウィジェット ページ先頭へ 愛媛県/川内温泉 このページについて このページは川内温泉のインターネット上の情報を集めたリンク集のようなものです。ブックマークしておけば、日々更新される川内温泉に関連する最新情報にアクセスすることができます。 情報収集はプログラムで行っているため、名前が同じであるが異なるカテゴリーの情報が掲載される場合があります。ご了承ください。 リンク先の内容を保証するものではありません。ご自身の責任でクリックしてください。