@Lein2xx4 さん
CS1061以外についてはおそらく下記2つの内どちらかないし両方が原因です
①参照にUnityEngineがない
②コード先頭にusing UnityEngineがない
それぞれドット以下のない(~.AudioModuleとか~.UnityWebRequestModuleとかの付いてない)やつも別途で参照・記述する必要があります
CS1061については参照にSystem.dllを追加してコード先頭にSystem.IOを追加してください
元々の死亡時とパッシブ消去時の処理は自分で生み出したマネージャーオブジェクトの消去しかしてないのでBGMを戻す動作は行っていませんでした、すみません
パッシブじゃない方を以下に変更してください
(ちなみにコンパイルでDestroyメソッドの元が変わるのは仕様です)
public class てきとうなくらすのなまえ : MonoBehaviour
{
private Coroutine _bgmLoadingCoroutine;
//元々のBGMを保持するためのフィールド追加
private AudioClip[] defaultBGMs;
private string _packageId = "もっどのid";
public bool LoadAudio(string str)
{
bool result = false;
this.ReleaseCoroutine(ref this._bgmLoadingCoroutine);
string modBgmPath = ModUtil.GetModBgmPath(Singleton<ModContentManager>.Instance.GetModPath(this._packageId));
this._bgmLoadingCoroutine = this.StartCoroutine(this.StreamPlayAudioFile(Path.Combine(modBgmPath, str)));
return result;
}
private void ReleaseCoroutine(ref Coroutine coroutine)
{
if (coroutine == null)
return;
this.StopCoroutine(coroutine);
coroutine = (Coroutine)null;
}
IEnumerator StreamPlayAudioFile(string fullpath)
{
using (UnityWebRequest www = UnityWebRequestMultimedia.GetAudioClip("file://" + fullpath, (AudioType)14))
{
yield return (object)www.SendWebRequest();
try
{
AudioClip audioClip = (AudioClip)null;
if (www.downloadHandler is DownloadHandlerAudioClip downloadHandler6 && ((DownloadHandler)downloadHandler6).isDone)
{
audioClip = downloadHandler6.audioClip;
((UnityEngine.Object)audioClip).name = Path.GetFileName(fullpath);
}
AudioClip[] audios = SingletonBehavior<BattleSoundManager>.Instance.SetEnemyTheme(new AudioClip[1] { audioClip });
this.defaultBGMs = new AudioClip[audios.Length];
this.defaultBGMs = audios;
}
catch (Exception ex)
{
}
}
}
//オブジェクト消去時にBGMを元に戻す
void OnDestroy()
{ SingletonBehavior<BattleSoundManager>.Instance.SetEnemyTheme(this.defaultBGMs);
}
}
@プルタブ さん
AddBufはその幕、AddReadyBufは次の幕、AddReadyReadyBufは次の次の幕に(紫の涙のアレ)該当バフを付与するものです。
2. 先程挙げられた解決策とは別にバフ自体にそういうメソッドを準備する、という解決策もあります。参考までにどうぞ
//これが該当バトルページにつける能力
public override void OnSucceedAttack(BattleDiceBehavior behavior)
{
if (this.owner != null)
{
//対象に該当バフがあるか。あるなら変数testbuffに格納
if (!(target.bufListDetail.GetActivatedBufList().Find((Predicate<BattleUnitBuf>)(x => x is BattleUnitBuf_TestBuf)) is BattleUnitBuf_TestBuf testBuf))
{
//ないなら変数格納ついでに新しく付与
testBuf = new BattleUnitBuf_TestBuf();
target.bufListDetail.AddBuf((BattleUnitBuf)testBuf);
}
//その後Addメソッドを起動
testBuf.Add(4);
}
}
public class BattleUnitBuf_TestBuf : BattleUnitBuf
{
public override string bufActivatedText => "説明文";
public override bool independentBufIcon => true;
//アイコンを便宜的に朦朧のそれに設定しています
protected override string keywordIconId => "Blurry";
public override void Init(BattleUnitModel owner)
{
base.Init(owner);
this.stack = 0;
}
public bool Add(int inc)
{
this.stack += this.stack + inc;
}
}
あ、その文は関係ありません(元の構文そのままをコピーしてそのままにしてるだけ)
今試したら自分の環境ではwavは動かずにoggでは動いたのでoggのものを用意して試してみていただけませんか?
いえ、同じクラスです
ぱっと思いつく現象としては
・StoryBGMの中に対象ファイルがない
・形式がサポートされていない(wavかoggのみ)
ですが……
@どこかの老人 さん
using UnityEngine (後ろに何もつけない)をUnityEngine.NetWorkingとは別途で追加してください
@T-Veronica さん
「てきとうなくらすのなまえ」のloadAudio内のModUtil.GetBgmPath内でほぼ全てのパスを取得しているのであとはパッシブの方のloadAudioの呼び出しで引数に"そのBGMのファイル名.拡張子"を入れれば動くはずです
参照する音楽ファイルはStoryBGMの中に入れてください
以下のクラスを用意した後、
public class てきとうなくらすのなまえ : MonoBehaviour
{
private Coroutine _bgmLoadingCoroutine;
private string _packageId = "もっどのid";
public bool LoadAudio(string str)
{
bool result = false;
this.ReleaseCoroutine(ref this._bgmLoadingCoroutine);
string modBgmPath = ModUtil.GetModBgmPath(Singleton<ModContentManager>.Instance.GetModPath(this._packageId));
this._bgmLoadingCoroutine = this.StartCoroutine(this.StreamPlayAudioFile(Path.Combine(modBgmPath, str)));
return result;
}
private void ReleaseCoroutine(ref Coroutine coroutine)
{
if (coroutine == null)
return;
this.StopCoroutine(coroutine);
coroutine = (Coroutine)null;
}
IEnumerator StreamPlayAudioFile(string fullpath)
{
using (UnityWebRequest www = UnityWebRequestMultimedia.GetAudioClip("file://" + fullpath, (AudioType)14))
{
yield return (object)www.SendWebRequest();
try
{
AudioClip audioClip = (AudioClip)null;
if (www.downloadHandler is DownloadHandlerAudioClip downloadHandler6 && ((DownloadHandler)downloadHandler6).isDone)
{
audioClip = downloadHandler6.audioClip;
((UnityEngine.Object)audioClip).name = Path.GetFileName(fullpath);
}
SingletonBehavior<BattleSoundManager>.Instance.SetEnemyTheme(new AudioClip[1] { audioClip });
}
catch (Exception ex)
{
}
}
}
}
下のパッシブを用意してください
public class PassiveAbility_てきとうななまえ : PassiveAbilityBase
{
private うえでつくったくらす _audioManager;
public override void OnWaveStart()
{
GameObject gameObject = new GameObject("うえでつくったくらすのなまえ");
this._audioManager = gameObject.AddComponent<うえでつくったくらす>();
bool result = this._audioManager.LoadAudio("拡張子含むBGMの名前");
}
public override void OnRoundStart()
{
//幕ごとの感情コイン量による敵味方BGMの優劣をごまかす
int emotionTotalCoinNumber = Singleton<StageController>.Instance.GetCurrentStageFloorModel().team.emotionTotalCoinNumber;
Singleton<StageController>.Instance.GetCurrentWaveModel().team.emotionTotalBonus = emotionTotalCoinNumber + 2;
}
public override void OnDestroyed()
{
GameObject.Destroy(this._audioManager);
}
public override void OnDie()
{
GameObject.Destroy(this._audioManager);
}
}
加えて、参照に
UnityEngine.UnityWebRequestAudioModule
UnityEngine.UnityWebRequestModule
UnityEngine.UnityWebRequestWWWModule
を加え、
using Mod
using UnityEngine.Networking
をmodの最初に加えてください。
BGMを入れる場所はStoryBGMです。
(追記)
Boolを返しているのはデバッグ用なので変更して構いません。
LorIdは(string, int)で構成されます。
そのため、_modIdは招待状メーカーのEdit WorkShop Infoで記入するIDを設定する場所となっております(このstringのidによって他のModと区別されます)。
対象のコアペNoの2はUnitIdの0の部分に打ち込んでください
(あとその効果なら専用バフ用意しなくても「幕の開始時に対象生存時対象に今回の幕にてクイック2付与」としてunitにAddKeywordBufThisRoundByETCでもいい気がします。リストカッターなどの効果を嫌うなら専用バフに速度アップを盛り込む形になるかもしれませんが)
public class PassiveAbility_Test : PassiveAbilityBase
{
//ModIdを記入
private static string _modId = "ModId";
//数字は自分で変更(司書用のコアペidは1からスタートではないので注意)
private LorId UnitId = new LorId(_modId, 0);
public override void OnRoundStart()
{
BattleUnitModel unit = BattleObjectManager.instance.GetAliveList(this.owner.faction).Find((Predicate<BattleUnitModel>)(x => x.UnitData.unitData.bookItem.BookId == this.UnitId));
if (unit == null)
return;
unit.bufListDetail.AddBuf((BattleUnitBuf)new PassiveAbility_Test.BattleUnitBuf_TestBuf());
}
public class BattleUnitBuf_TestBuf : BattleUnitBuf
{
public override string bufActivatedText => "説明をここに記入";
public override bool independentBufIcon => true;
protected override string keywordId => "Test";
//便宜的にアイコンを朦朧のアイコンにしています
protected override string keywordIconId => "Blurry";
//効果は適当にやってください
public override void OnRoundEnd() => this.Destroy();
}
}
こんな感じですかね
今バーっと書いたものなのでうまくいかなかったら自分で治すかお気軽にこちらにどうぞ
パッシブスキルの覗き方についてはいろいろグレーな部分もあったりなかったりするのでデコンパイラで調べてください
特定の味方、という部分に着目するなら、とりあえずAliveListをExistメソッドで探すとして、
味方を判別する方法に
①.unitdata.isSephirah(指定司書かどうかを判断)
②舞台開始時にバフを付けてHasBuf<>()メソッドで判断
③.unitdata.bookItem.bookId(装備コアペのId)
なんかがパッと思いつきます
「特定の味方」をどのように想定しているのかで色々変わってくると思うのでそのスキルの詳しい仕様などを教えていただければもう少し踏み込んだアドバイスができると思います
特定の階層のみ使用可能にするならstageInfoに<floorOnly>(追加したい階層のSephirahType)</floorOnly>でいけます。複数階層指定したい場合もそのまま直下にSephirahTypeを変えてコピーで大丈夫です
特定司書のみ参加可能な設定に関しては現状ではおそらくできません。
赤い霧戦、オリヴィエ・楽団アルガリア戦などでの特定司書のみ参加可能の設定はBattleUnitModelのisLockUnitメソッド内のこちらが操作できない条件文によって判断されているためです。
いろいろ試した結果MapManagerはUnity上でプレハブ化されたオブジェクトから呼び出されているのでこちらで下手にいじるのは危険だという結論に達しました(普通にやってもスクリプトが動かず最悪ゲームが停止します)
幻想体セリフのIndexは各MapManagerの中で設定されていますが肝心の呼び出し先がAssetの中のxmlになっているようなのでこちらも私の技術では不可能でした
BGMだけならだいぶ前に上に挙げたように
OnRoundStart()に
int emotionTotalCoinNumber = Singleton<StageController>.Instance.GetCurrentStageFloorModel().team.emotionTotalCoinNumber;
Singleton<StageController>.Instance.GetCurrentWaveModel().team.emotionTotalBonus = emotionTotalCoinNumber + 2;
(感情コインの有利不利で敵のBGMかセフィラBGMか変わるので敵のBGMに固定)
を追加してから、
任意のタイミングで
SingletonBehavior<BattleSoundManager>.Instance.ChangeFinalCreatureTheme_Roland(0);
(ローラン戦第1段階BGMの場合。詳しくはBattleSoundManagerとかEnemyTeamManagerとか覗いてください)
AudioClip[] audio = new AudioClip[1]{SingletonBehavior<BattleSoundManager>.Instance.CurrentPlayingTheme.clip};
AudioClip[] audio2 = SingletonBehavior<BattleSoundManager>.Instance.SetEnemyTheme(audio);
(敵のBGMリスト(戦闘中に急に流れる接待準備画面めいたあのBGM)を変更したBGMに挿げ替える)
でいけます(bool変数などでChange~Themaの部分以降は再起動しないように制御してください)
WorkShopからのサブスクライブ時やゲーム起動時にAudioCripがどこに格納されるかがわかればStoryBGMから読み取って最終文にぶちこめば外部音声も再生できそうです
(追記)
StoryBGMの場所のアクセスの仕方は分かりましたが読み取りにコルーチンを使っているため現在私たちが使えるコードでは処理は難しいと判断しました。一応アクセスパスの詳細を下記に記しておきます
string modId = "TestMod"
string audioName = "test.ogg";
string basePath = Singleton<ModContentManager>.Instance.GetModPath(modId);
string modBgmPath = ModUtil.GetModBgmPath(basePath);
//上記までは作動を確認
//下記が問題のコルーチン。現在作れるパッシブ、バフ、ダイス能力、ページ能力などではMonoBehaviourやEventSystemが継承できないのとそもそもEventSystemを新たに生成するのは危険極まりなさそうなのでこのコルーチンを制御する術が無いと思われます。ちなみにコールバックメソッドは元の記述から変更しています
AudioUtil.LoadAudioCoroutine(Path.Combine(modBgmPath, audioName), (Action<AudioClip>)(c => SingletonBehavior<BattleSoundManager>.Instance.SetEnemyTheme(new AudioClip[1] { c })));
詳細を知りたい方はStoryManagerのLoadAndPlayBackgroundMusicメソッドを参照してください
というかそもそも公式のアプデを待った方がよさそう
公式マニュアルで参照に追加しろと言っていたAssembly-CSharp.dllに大体入ってます
ちなみにキャラクターの位置はStageInfoのformationをいじれば変えられます
どの陣形がいいかはアセット覗くなりして判断してください(1が司書と同じ並びのやつ)
(接待中に変えたいならSingleton<StageController>.Instance.GetCurrentWaveModel().SetFormationPosition(index, new Vector2Int(x, y));という手もあります。詳しいやり方は完全開放戦のenemyteammanager覗くなり元メソッド参照するなりしてください)
あと現在おま環なのか仕様なのかわかりませんが招待状MODのステージだと舞台開始時に2番目の敵と1番目の敵のIndexが入れ替わるのでAddNewUnitや陣形組むときは注意が必要です
ついでにOnDieOtherUnitは生贄職員がよくやるバトペ能力による自爆には反応しないので同様の状況が起こりえるときは避けてOnRoundEndTheLastにGetAliveListするなりした方がよさげ
EmotionCardAbility_〇〇です
その能力ならどちらかというと憎しみの女王の憎悪を参考にした方がいいと思いますが……
以下シャオの揺らぎより抜粋
private int _speedDiceNumAdder = 2;
public override int SpeedDiceNumAdder() => this._speedDiceNumAdder;
public override void OnRoundStart()
{
this._speedDiceNumAdder = 3;
if (Singleton<StageController>.Instance.RoundTurn >= 2)
++this._speedDiceNumAdder;
}
速度ダイスの数は本の初期速度ダイス数(今回はデフォルトの1)、パッシブ・バフ・EmotionDeltailの各SpeedDiceNumAdderで判断されます。
シャオの場合は舞台開始時に1+2=3、その後幕開始で1+3=4。
2幕目以降からは1+3+1=5で、4幕目には感情レベルが4以上になっているはずなので1+3+1+1=6となっているようです
@Yakumohisyo さん
スキンをくっつけたequipPageを事前に作っておいて
BookModel dummyBook = new BookModel(Singleton<BookXmlList>.Instance.GetData(new LorId("modId", 本id)));
UnitDataModel unit = new UnitDataModel();
UnitCustomizingData customizeData = this.owner.UnitData.unitData.customizeData;
GiftInventory giftInventory = this.owner.UnitData.unitData.giftInventory;
unit.EquipBook(dummyBook, force: true);
unit.SetCustomizingData(customizeData);
unit.giftInventory = giftInventory;
ActionDetail currentMotionDetail = this.owner.view.charAppearance.GetCurrentMotionDetail();
this.owner.view.DestroySkin();
this.owner.view.charAppearance = SdCharacterUtil.CreateSkin(unit, this.owner.faction, this.owner.view.characterRotationCenter);
if (customizeData != null)
this.owner.view.ChangeHeight(customizeData.height); this.owner.view.ChangeScale(
SingletonBehavior<BattleSceneRoot>.Instance.currentMapObject.mapSize
);
で自分はやってますね
ただ超無理やりな処理だしEGOとかの一時スキン変更挟むと戻る(そこらへん固定する変数が見た限り軒並みPrivateだった)からOnRoundEndとかOnEndParryingでも毎回呼びださないといけないしでかなり危なげなので大人しくアプデを待った方がいい気がしますね
@T-Veronica さん
コードの中身が分からんから何とも……
(1)パッケージIDの定義はAddNewCardの前に行われているか
(2)そもそもAddNewCardメソッドが定義されているか
(3)AddNewCardを使用しているメソッド内の別の処理でエラー吐いて止まってる
現段階の情報ではこの3つですかね……?
LorIdというクラスで指定しています
詳しくは6つ上の返信をば
(いらんかもな備忘録の共有)
コアペの専用バトペ欄のOnlyPageはBookModelのSetXmlInfo(BookXmlInfo)で読み取られるが、1.1.0.6a6現在、Attributeでstringを設定できるBookPassiveXmlInfo(コアペパッシブ設定欄)とは異なり、OnlyPage欄にはintしか指定できないため(SetXmlInfo中でもintしか想定していない)、元々ある専用ページの共有指定はできるが、MOD由来の専用ページの指定はできない模様。
バトペの方のOptionには使用時消滅のExhaustOnUseとともに専用ページであるOnlyPageも指定でき(階層EGOのEGO、個人EGOのEGOPersonal、個人ページであるPersonal、インベントリに戻せないNoInventry、いまいち分からんEGOchangeは設定できない)、インベントリにて専用ページその他の表示を司るUIInvenCardListScrollのApplyFilterAll()はMODバトペでも普通に動きそうなので、MODの方でXmlをいじって専用ページを作ってもどこにも表示されないだけのバトペができそう