From 56d3001eec7b14a2efa2e9cc24f255b1beeb2dc6 Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Sat, 16 May 2026 16:50:49 +0000 Subject: [PATCH 1/3] docs(role): update technical reference for methods and interfaces Updated `07_interfaces.md` and `08_methods.md` to include missing interfaces and virtual methods from the codebase. Each entry now includes method signatures, detailed argument/return value descriptions, and practical code examples. Additionally, corrected broken or outdated links across the role development documentation. Co-authored-by: yukieiji <40425798+yukieiji@users.noreply.github.com> --- doc/dev/role/01_overview.md | 6 +- doc/dev/role/02_role_class.md | 2 +- doc/dev/role/04_ability_handler.md | 2 +- doc/dev/role/07_interfaces.md | 229 ++++++++++++++++++++++------- doc/dev/role/08_methods.md | 182 +++++++++++++++-------- 5 files changed, 302 insertions(+), 119 deletions(-) diff --git a/doc/dev/role/01_overview.md b/doc/dev/role/01_overview.md index 303eb48b1..2d73d4741 100644 --- a/doc/dev/role/01_overview.md +++ b/doc/dev/role/01_overview.md @@ -39,8 +39,8 @@ ExtremeRoles/Roles/Solo/Crewmate/MyRole/ 2. **オプションの実装**: [03_option_factory.md](./03_option_factory.md) 3. **能力の実装**: [04_ability_handler.md](./04_ability_handler.md) 4. **状態管理の実装**: [05_status_model.md](./05_status_model.md) -5. **インターフェースの活用**: [06_interfaces_and_methods.md](./06_interfaces_and_methods.md) -6. **役職の登録**: [07_registration_and_selector.md](./07_registration_and_selector.md) -7. **翻訳の追加**: [08_translation.md](./08_translation.md) +5. **インターフェースの活用**: [07_interfaces.md](./07_interfaces.md) / [08_methods.md](./08_methods.md) +6. **役職の登録**: [98_registration.md](./98_registration.md) +7. **翻訳の追加**: [99_translation.md](./99_translation.md) 各ステップの詳細は、番号順の各ドキュメントを参照してください。 diff --git a/doc/dev/role/02_role_class.md b/doc/dev/role/02_role_class.md index bb3ccafb5..2662405e3 100644 --- a/doc/dev/role/02_role_class.md +++ b/doc/dev/role/02_role_class.md @@ -89,4 +89,4 @@ public MyRole() : base( ## 重要なメソッドとインターフェース -利用可能な主要メソッドや拡張インターフェースについては、[重要なメソッドとインターフェース](./06_interfaces_and_methods.md) を参照してください。 +利用可能な主要メソッドや拡張インターフェースについては、[インターフェース](./07_interfaces.md) および [主要なメソッドとプロパティ](./08_methods.md) を参照してください。 diff --git a/doc/dev/role/04_ability_handler.md b/doc/dev/role/04_ability_handler.md index 812252f0d..15c7ee2df 100644 --- a/doc/dev/role/04_ability_handler.md +++ b/doc/dev/role/04_ability_handler.md @@ -82,4 +82,4 @@ public bool Execute(byte targetId) ## 便利なインターフェース -AbilityHandler で活用できるインターフェースについては、[重要なメソッドとインターフェース](./06_interfaces_and_methods.md) を参照してください。 +AbilityHandler で活用できるインターフェースについては、[インターフェース](./07_interfaces.md) を参照してください。 diff --git a/doc/dev/role/07_interfaces.md b/doc/dev/role/07_interfaces.md index ff7c6ad05..fdd5654be 100644 --- a/doc/dev/role/07_interfaces.md +++ b/doc/dev/role/07_interfaces.md @@ -2,55 +2,180 @@ 役職作成において頻繁に使用する機能拡張のためのインターフェースについて説明します。 -## 機能拡張インターフェース - -特定のインターフェースを実装することで、様々なゲームイベントにフックできます。**`IRole` から始まる名前のインターフェースは、主に `SingleRoleBase` (Roleクラス) に実装することを目的としています。** - -### Roleクラス (SingleRoleBase) 向け -これらのインターフェースは通常、役職の定義である Role クラスに実装します。 - -- **`IRoleUpdate`** - - `Update(PlayerControl rolePlayer)`: 毎フレーム呼ばれます。 -- **`IRoleResetMeeting`** - - `ResetOnMeetingStart()`: 会議開始時に呼ばれます。 - - `ResetOnMeetingEnd(NetworkedPlayerInfo? exiledPlayer)`: 会議終了時に呼ばれます。 - -#### 投票・会議 -- **`IRoleVoteModifier`** - - `ModifiedVote(...)`: 投票結果を書き換えます。 - - `GetModdedVoteInfo(...)`: 投票の演出を書き換えます。 -- **`IRoleMeetingButtonAbility`** - - 会議中の投票画面に特殊なボタンを追加したい場合に実装します。 - -#### フック・割り込み -- **`IRoleReportHook`** - - `HookReportButton(...)`: 緊急会議ボタンが押された時に割り込みます。 - - `HookBodyReport(...)`: 死体レポート時に割り込みます。 -- **`IRolePerformKillHook`** - - キルを実行する瞬間に割り込みます。 -- **`IRoleMurderPlayerHook`** - - プレイヤーが殺害される処理に割り込みます。 - -### 能力・ロジック (AbilityHandler) 向け -能動的な能力や詳細なロジックを担う `AbilityHandler` に実装できるインターフェースです。 - -- **`IKilledFrom`** - - `IKilledFrom(PlayerControl rolePlayer, PlayerControl fromPlayer)`: `fromPlayer`が`rolePlayer`に対してキルボタンを押した時に呼ばれます。`true`を返すとキルされます - -- **`IInvincible`** - - `IsValidKillFromSource(byte source)` : `source`からキルの対象になるかどうかの判定 - - `IsValidAbilitySource(byte source)` : `source`から能力の対象になるかどうかの判定 - - `IsBlockKillFrom(byte? fromTarget)`: `fromTarget`からのキルをブロックするかどうかを判定します。 - -- **`IExiledAnimationOverrideWhenExiled`** - - `OverrideInfo`: 追放時のメッセージやアニメーションを上書きします。 - -- **`IVoteCheck`** - - `VoteTo(byte target)`: `target`へ投票した時のフック - -### ビジュアル (IVisual) 向け -役職のビジュアル向けのロジックを担う `Visual` に実装することされるインターフェースです。 -- **`IVisual`** - - `UpdateVisual(PlayerControl rolePlayer)`: プレイヤーの見た目(色やエフェクト)を更新します。 -- **`ILookedTag`** - - 他のプレイヤーから見た時のタグを制御します。 +## 機能拡張インターフェースの概要 + +特定のインターフェースを実装することで、様々なゲームイベントにフックできます。 +- **`IRole` から始まる名前**: 主に `SingleRoleBase` (Roleクラス) に実装することを目的としています。 +- **それ以外の名前**: 主に `AbilityHandler` や `StatusModel` に実装することを目的としています。 + +--- + +## Roleクラス (SingleRoleBase) 向け + +### 基本イベント +#### `IRoleUpdate` +毎フレームの更新処理を実装します。 +- `void Update(PlayerControl rolePlayer)` + - `rolePlayer`: この役職を持つプレイヤーのインスタンス。 + +#### `IRoleResetMeeting` +会議の開始時と終了時のリセット処理を実装します。 +- `void ResetOnMeetingStart()` + - 会議が開始された瞬間に呼ばれます。 +- `void ResetOnMeetingEnd(NetworkedPlayerInfo? exiledPlayer)` + - 会議が終了し、追放が確定した後に呼ばれます。 + - `exiledPlayer`: 追放されたプレイヤーの情報(誰も追放されなかった場合は `null`)。 + +#### `IRoleSpecialSetUp` +役職の導入(イントロ)演出に関するセットアップを行います。 +- `void IntroBeginSetUp()` + - イントロ演出が開始される直前に呼ばれます。 +- `void IntroEndSetUp()` + - イントロ演出が終了した直前に呼ばれます。 + +--- + +### 投票・会議 +#### `IRoleVoteModifier` +投票結果を動的に書き換えます。 +- `int Order { get; }` + - 変更の優先順位。`ModOrder` 列挙型を使用して指定します。 +- `void ModifiedVote(byte rolePlayerId, ref Dictionary voteTarget, ref Dictionary voteResult)` + - `rolePlayerId`: 役職保持者のプレイヤーID。 + - `voteTarget`: 誰が誰に投票したかの辞書。 + - `voteResult`: 各プレイヤーが獲得した票数の辞書。 +- `IEnumerable GetModdedVoteInfo(VoteInfoCollector collector, NetworkedPlayerInfo rolePlayer)` + - 投票の演出(投票画面のバッジ等)を書き換えます。 +- `void ResetModifier()` + - 会議終了後などに内部状態をリセットします。 + +#### `IRoleMeetingButtonAbility` +会議中の投票画面に特殊なボタンを追加します。 +- `bool IsBlockMeetingButtonAbility(PlayerVoteArea instance)`: ボタンを無効化するかどうか。 +- `void ButtonMod(PlayerVoteArea instance, UiElement abilityButton)`: ボタンの見た目をカスタマイズ。 +- `Action CreateAbilityAction(PlayerVoteArea instance)`: ボタンが押された時の動作を返します。 +- `Sprite AbilityImage { get; }`: ボタンのアイコン画像。 + +#### `IRoleHookVoteEnd` +投票結果が確定した直後に呼ばれます。 +- `void HookVoteEnd(MeetingHud instance, NetworkedPlayerInfo rolePlayer, IReadOnlyDictionary voteIndex)` + - `voteIndex`: 各プレイヤーが得た最終的な票数。 + +--- + +### フック・割り込み +#### `IRoleReportHook` +レポートや緊急会議ボタンの挙動に割り込みます。 +- `void HookReportButton(PlayerControl rolePlayer, NetworkedPlayerInfo reporter)` + - `reporter`: ボタンを押したプレイヤー。 +- `void HookBodyReport(PlayerControl rolePlayer, NetworkedPlayerInfo reporter, NetworkedPlayerInfo reportBody)` + - `reportBody`: 通報された死体の情報。 + +#### `IRolePerformKillHook` +キルアニメーションの開始時と終了時に呼ばれます。 +- `void OnStartKill()` +- `void OnEndKill()` + +#### `IRoleMurderPlayerHook` +プレイヤーが殺害される瞬間の処理に割り込みます(キルボタン押下時ではなく、実際の死亡処理時)。 +- `void HookMuderPlayer(PlayerControl source, PlayerControl target)` + - `source`: 加害者, `target`: 被害者。 + +--- + +### 特殊状態・ライフサイクル +#### `IRoleWinPlayerModifier` +勝利条件や勝利チームの判定を書き換えます。 +- `void ModifiedWinPlayer(NetworkedPlayerInfo rolePlayerInfo, GameOverReason reason, in WinnerContainer winner)` + - `winner`: 勝利者リストを含むコンテナ。この内容を書き換えることで勝利者を操作できます。 + +#### `IRoleAwake` +「覚醒」などの状態変化を持つ役職で使用します。 +- `bool IsAwake { get; }`: 覚醒しているかどうか。 +- `T NoneAwakeRole { get; }`: 未覚醒状態のID。 +- `string GetFakeOptionString()`: オプション画面での表示。 + +#### `IRoleOnRevive` / `IRoleReviveHook` +蘇生に関する処理を実装します。 +- `void ReviveAction(PlayerControl player)`: 自身が蘇生した時の処理。 +- `void HookRevive(PlayerControl revivePlayer)`: 誰かが蘇生した時に呼ばれるフック。 + +#### `IRoleFakeIntro` +イントロ画面で別のチームとして表示させたい場合に実装します。 +- `ExtremeRoleType FakeTeam { get; }`: 表示上のチーム(Crewmate, Impostorなど)。 + +#### `IRoleSpecialReset` +役職が剥奪されたり、特殊なリセットが必要な場合に実装します。 +- `void AllReset(PlayerControl rolePlayer)` + +--- + +## 能力・ロジック (AbilityHandler) 向け + +#### `IKilledFrom` +キルボタンが押された瞬間の判定を行います。 +- `bool TryKilledFrom(PlayerControl rolePlayer, PlayerControl fromPlayer)` + - `true` を返すと、通常のキル処理を続行(殺害を許可)します。 + +#### `IInvincible` +無敵状態やキル・能力の対象外判定を行います。 +- `bool IsBlockKillFrom(byte? fromPlayer)`: `fromPlayer` からのキルをブロックするか。 +- `bool IsValidKillFromSource(byte source)`: 指定されたソースからのキルが有効か。 + +#### `IExiledAnimationOverrideWhenExiled` +追放時のアニメーションテキストなどを上書きします。 +- `OverrideInfo? OverrideInfo { get; }`: `ExiledPlayer` と `AnimationText` を含むレコード。 + +#### `IVoteCheck` +投票を行った時のフックです。 +- `void VoteTo(byte target)`: 投票先のプレイヤーID。 + +#### `ITryKillTo` +自分が誰かをキルしようとした時の判定です。 +- `bool TryRolePlayerKillTo(PlayerControl rolePlayer, PlayerControl targetPlayer)` + +--- + +## 状態管理 (StatusModel) 向け + +#### `IDeadBodyReportOverrideStatus` +死体の通報可否を制御します。 +- `bool CanReport { get; }` + +#### `IFakeImpostorStatus` +ゲームシステム上でインポスターとして扱われるかどうか(通報画面の赤文字など)。 +- `bool IsFakeImpostor { get; }` + +#### `IStatusMovable` +移動可能かどうかを制御します。 +- `bool CanMove { get; }` + +#### `ISubTeam` +第三陣営内での所属チーム(例:ジャッカルチーム等)を定義します。 +- `NeutralSeparateTeam Main { get; }` +- `NeutralSeparateTeam Sub { get; }` + +#### `IUsableOverrideStatus` +ボタンの有効化状態を制御します。 +- `bool EnableUseButton { get; }` +- `bool EnableVentButton { get; }` + +--- + +## 実装例 + +```csharp +public sealed class MyRoleAbilityHandler : IAbility, IKilledFrom +{ + // キルボタンを押された時の処理 + public bool TryKilledFrom(PlayerControl rolePlayer, PlayerControl fromPlayer) + { + // 50%の確率でキルを回避 + if (UnityEngine.Random.value > 0.5f) + { + return false; // キルを阻止 + } + return true; // キルを許可 + } +} +``` diff --git a/doc/dev/role/08_methods.md b/doc/dev/role/08_methods.md index d36f20a7b..900f845e8 100644 --- a/doc/dev/role/08_methods.md +++ b/doc/dev/role/08_methods.md @@ -1,65 +1,123 @@ -# 重要なメソッドとインターフェース - -役職作成において頻繁に使用する `SingleRoleBase` のメソッドと、機能拡張のためのインターフェースについて説明します。 - -## SingleRoleBase の主要メソッド - -Roleクラスでオーバーライドして使用する主なメソッドです。 - -- **`RoleSpecificInit()`** - - 役職がプレイヤーにアサインされた直後に一度だけ呼ばれます。`AbilityHandler` や `StatusModel` の生成・初期化、オプション値のロードに最適です。 -- **`ExiledAction(PlayerControl rolePlayer)`** - - 自身が追放された時に呼ばれます。 -- **`GetRolePlayerNameTag(SingleRoleBase targetRole, byte targetPlayerId)`** - - プレイヤーのネームタグ(頭上の名前)をカスタマイズしたい場合にオーバーライドします。 -- **`GetFullDescription()`** - - 役職説明画面のテキストを動的に変更したい場合にオーバーライドします(例:現在のカウントを表示するなど)。 - -## 機能拡張インターフェース - -特定のインターフェースを実装することで、様々なゲームイベントにフックできます。**`IRole` から始まる名前のインターフェースは、主に `SingleRoleBase` (Roleクラス) に実装することを目的としています。** - -### Roleクラス (SingleRoleBase) 向け -これらのインターフェースは通常、役職の定義である Role クラスに実装します。 - -- **`IRoleUpdate`** - - `Update(PlayerControl rolePlayer)`: 毎フレーム呼ばれます。 -- **`IRoleResetMeeting`** - - `ResetOnMeetingStart()`: 会議開始時に呼ばれます。 - - `ResetOnMeetingEnd(NetworkedPlayerInfo? exiledPlayer)`: 会議終了時に呼ばれます。 - -### 能力・ロジック (AbilityHandler) 向け -能動的な能力や詳細なロジックを担う `AbilityHandler` に実装することが推奨されるインターフェースです。 - -- **`IInvincible`** - - `IsBlockKillFrom(byte? fromTarget)`: キルをブロックするかどうかを判定します。 -- **`IExiledAnimationOverrideWhenExiled`** - - `OverrideInfo`: 追放時のメッセージやアニメーションを上書きします。 -- **`IKilledFrom`** - - `IKilledFrom(PlayerControl killer, PlayerControl victim)`: キルされた瞬間に呼ばれます。 - -### 投票・会議 -- **`IRoleVoteModifier`** - - `ModifiedVote(...)`: 投票結果を書き換えます。 - - `GetModdedVoteInfo(...)`: 投票の演出を書き換えます。 -- **`IRoleMeetingButtonAbility`** - - 会議中の投票画面に特殊なボタンを追加したい場合に実装します。 - -### フック・割り込み -- **`IRoleReportHook`** - - `HookReportButton(...)`: 緊急会議ボタンが押された時に割り込みます。 - - `HookBodyReport(...)`: 死体レポート時に割り込みます。 -- **`IRolePerformKillHook`** - - キルを実行する瞬間に割り込みます。 -- **`IRoleMurderPlayerHook`** - - プレイヤーが殺害される処理に割り込みます。 - -### 視覚効果 -- **`IVisual`** - - `UpdateVisual(PlayerControl rolePlayer)`: プレイヤーの見た目(色やエフェクト)を更新します。 -- **`ILookedTag`** - - 他のプレイヤーから見た時のタグを制御します。 +# 主要なメソッドとプロパティ + +`SingleRoleBase` を継承して役職を作成する際、オーバーライドして挙動をカスタマイズできる主要なメソッドとプロパティについて説明します。 + +--- + +## ライフサイクル・初期化 + +#### `void RoleSpecificInit()` +役職がプレイヤーにアサインされた直後に一度だけ呼ばれます。 +- **用途**: `AbilityHandler` や `StatusModel` の生成、オプション値のロード。 +- **実装例**: + ```csharp + protected override void RoleSpecificInit() { + this.status = new MyRoleStatusModel(); + this.ability = new MyRoleAbilityHandler(this.status); + } + ``` + +#### `SingleRoleBase Clone()` +役職インスタンスの複製を作成します。 +- **戻り値**: 複製された `SingleRoleBase` インスタンス。 +- **注意**: 通常は `MemberwiseClone()` を使用しますが、深いコピーが必要な場合はオーバーライドします。 + +--- + +## 勝利条件・判定 + +#### `bool IsTeamsWin()` +自身のチームが勝利したかどうかを判定します。 +- **戻り値**: チームが勝利条件を満たしていれば `true`。 + +#### `bool IsSameTeam(SingleRoleBase targetRole)` +対象の役職と同じチームかどうかを判定します。 +- `targetRole`: 比較対象の役職。 +- **戻り値**: 同じチームであれば `true`。 + +#### `bool IsAssignGhostRole` +幽霊状態のプレイヤーにこの役職をアサイン可能かどうか。 +- **デフォルト**: `true` + +--- + +## アクション・イベント + +#### `void ExiledAction(PlayerControl rolePlayer)` +自身が会議で追放された時に呼ばれます。 +- `rolePlayer`: 追放されたプレイヤー(自身)。 + +#### `void RolePlayerKilledAction(PlayerControl rolePlayer, PlayerControl killerPlayer)` +自身が殺害された時に呼ばれます。 +- `rolePlayer`: 殺害されたプレイヤー(自身)。 +- `killerPlayer`: 加害者のプレイヤー。 + +--- + +## ビジュアル・情報表示 + +#### `string RoleName` +役職の表示名を返します。 +- **用途**: 翻訳キーを指定することが一般的です。 + +#### `Color GetNameColor(bool isTruthColor = false)` +プレイヤー名の色を取得します。 +- `isTruthColor`: 真実の色を要求されているか(偽装を考慮するか)。 +- **戻り値**: 表示する `Color`。 + +#### `Color GetTargetRoleSeeColor(SingleRoleBase targetRole, byte targetPlayerId)` +特定のプレイヤー(`targetRole`)から見た時の、自身(`targetPlayerId`)の名前の色を決定します。 +- `targetRole`: 閲覧者の役職。 +- `targetPlayerId`: 自身のプレイヤーID。 +- **用途**: インポスター同士で名前を赤く見せる、特定の役職からのみ色を変える等。 + +#### `string GetRoleTag()` +名前の横に表示される短縮タグ(例:`[M]`)を返します。 +- **戻り値**: 表示する文字列。 + +#### `string GetRolePlayerNameTag(SingleRoleBase targetRole, byte targetPlayerId)` +他プレイヤー(`targetRole`)から見た時の自身のネームタグ(頭上の表示)をカスタマイズします。 +- **用途**: 役職名の表示や、特殊な状態の表示。 + +#### `string GetImportantText(bool isContainFakeTask = true)` +役職説明画面の「重要事項」セクションのテキストを生成します。 +- `isContainFakeTask`: 偽タスクの案内を含めるか。 +- **戻り値**: 装飾された文字列。 + +#### `string GetIntroDescription()` +ゲーム開始時のイントロ画面で表示される説明文を返します。 + +#### `string GetFullDescription()` +役職説明画面で表示される詳細な説明文を返します。 +- **用途**: 現在の残り回数やカウントなどを動的に表示したい場合にオーバーライドします。 + +#### `bool IsBlockShowMeetingRoleInfo()` / `IsBlockShowPlayingRoleInfo()` +会議中やプレイ中に役職情報を表示するのを制限するかどうか。 +- **戻り値**: `true` で非表示。 + +--- + +## オプション設定 + +#### `AutoParentSetOptionCategoryFactory CreateSpawnOption()` (abstract) +役職の出現率や人数のオプションを生成します。 + +#### `void CreateSpecificOption(AutoParentSetOptionCategoryFactory factory)` (abstract) +役職固有のオプション(例:クールタイム、使用回数など)を生成します。 + +#### `void CreateVisionOption(AutoParentSetOptionCategoryFactory factory, bool ignorePrefix = true)` +視界に関するオプションを生成します。 + +--- ## 実装のポイント -これらのインターフェースは、Roleクラス自体に実装することも可能ですが、ロジックの肥大化を防ぐために **AbilityHandler に実装し、Roleクラスから呼び出す** か、**Roleクラスが保持する AbilityClass にそのインターフェースを実装したインスタンスを割り当てる** 設計が推奨されます。 +`SingleRoleBase` は多くの `virtual` プロパティ(`CanUseAdmin`, `UseVent` など)を持っています。これらをコンストラクタや `RoleSpecificInit` で適切に設定することで、役職の基本的な能力を定義できます。 + +```csharp +public MyRole(RoleArgs arg) : base(arg) { + this.CanKill = true; + this.UseVent = true; + this.HasTask = false; +} +``` From b89c72d9d6c3e07b4186b8cbf62d651577bdd5ff Mon Sep 17 00:00:00 2001 From: yukieiji <40425798+yukieiji@users.noreply.github.com> Date: Sun, 17 May 2026 15:54:16 +0900 Subject: [PATCH 2/3] fix: typo --- ExtremeRoles/Patches/Player/MurderPlayerPatch.cs | 4 ++-- ExtremeRoles/Roles/API/Interface/IRoleMurderPlayerHook.cs | 4 ++-- .../Roles/Combination/InvestigatorOffice/Assistant.cs | 2 +- .../Roles/Combination/InvestigatorOffice/Investigator.cs | 2 +- ExtremeRoles/Roles/Combination/Sharer.cs | 2 +- ExtremeRoles/Roles/Solo/Crewmate/CurseMaker.cs | 2 +- ExtremeRoles/Roles/Solo/Crewmate/Whisper.cs | 2 +- ExtremeRoles/Roles/Solo/Impostor/Hypnotist.cs | 2 +- ExtremeRoles/Roles/Solo/Liberal/Leader.cs | 2 +- ExtremeRoles/Roles/Solo/Neutral/Eater.cs | 2 +- ExtremeRoles/Roles/Solo/Neutral/IronMate/IronMate.cs | 2 +- ExtremeRoles/Roles/Solo/Neutral/Jackal/FurryRole.cs | 2 +- ExtremeRoles/Roles/Solo/Neutral/Queen/QueenRole.cs | 2 +- ExtremeRoles/Roles/Solo/Neutral/Queen/ServantRole.cs | 2 +- ExtremeRoles/Roles/Solo/Neutral/Yandere/YandereRole.cs | 2 +- 15 files changed, 17 insertions(+), 17 deletions(-) diff --git a/ExtremeRoles/Patches/Player/MurderPlayerPatch.cs b/ExtremeRoles/Patches/Player/MurderPlayerPatch.cs index d9c555c12..80fe56392 100644 --- a/ExtremeRoles/Patches/Player/MurderPlayerPatch.cs +++ b/ExtremeRoles/Patches/Player/MurderPlayerPatch.cs @@ -231,12 +231,12 @@ private static void invokeRoleHookAction( if (localPlayerRole is IRoleMurderPlayerHook hookRole) { - hookRole.HookMuderPlayer(killer, target); + hookRole.HookMurderPlayer(killer, target); } if (localPlayerRole is MultiAssignRoleBase multiAssignRole && multiAssignRole.AnotherRole is IRoleMurderPlayerHook multiHookRole) { - multiHookRole.HookMuderPlayer(killer, target); + multiHookRole.HookMurderPlayer(killer, target); } } diff --git a/ExtremeRoles/Roles/API/Interface/IRoleMurderPlayerHook.cs b/ExtremeRoles/Roles/API/Interface/IRoleMurderPlayerHook.cs index 476022112..a51f4c87e 100644 --- a/ExtremeRoles/Roles/API/Interface/IRoleMurderPlayerHook.cs +++ b/ExtremeRoles/Roles/API/Interface/IRoleMurderPlayerHook.cs @@ -1,8 +1,8 @@ -namespace ExtremeRoles.Roles.API.Interface +namespace ExtremeRoles.Roles.API.Interface { public interface IRoleMurderPlayerHook { - void HookMuderPlayer( + void HookMurderPlayer( PlayerControl source, PlayerControl target); } diff --git a/ExtremeRoles/Roles/Combination/InvestigatorOffice/Assistant.cs b/ExtremeRoles/Roles/Combination/InvestigatorOffice/Assistant.cs index 376ef2441..2fd3dd5f8 100644 --- a/ExtremeRoles/Roles/Combination/InvestigatorOffice/Assistant.cs +++ b/ExtremeRoles/Roles/Combination/InvestigatorOffice/Assistant.cs @@ -24,7 +24,7 @@ public void AllReset(PlayerControl rolePlayer) downgradeDetective(); } - public void HookMuderPlayer( + public void HookMurderPlayer( PlayerControl source, PlayerControl target) { if (MeetingHud.Instance == null) diff --git a/ExtremeRoles/Roles/Combination/InvestigatorOffice/Investigator.cs b/ExtremeRoles/Roles/Combination/InvestigatorOffice/Investigator.cs index a7f1ef483..4795d92a4 100644 --- a/ExtremeRoles/Roles/Combination/InvestigatorOffice/Investigator.cs +++ b/ExtremeRoles/Roles/Combination/InvestigatorOffice/Investigator.cs @@ -289,7 +289,7 @@ this.searchInfo is null || this.searchInfo.AllTarget.Add(crime, reporter.PlayerId); } - public void HookMuderPlayer( + public void HookMurderPlayer( PlayerControl source, PlayerControl target) { this.status?.AddCrime(source, target); diff --git a/ExtremeRoles/Roles/Combination/Sharer.cs b/ExtremeRoles/Roles/Combination/Sharer.cs index c4ddb75cd..193f85bcb 100644 --- a/ExtremeRoles/Roles/Combination/Sharer.cs +++ b/ExtremeRoles/Roles/Combination/Sharer.cs @@ -88,7 +88,7 @@ public Sharer() : base( OptionTab.CombinationTab) { } - public void HookMuderPlayer( + public void HookMurderPlayer( PlayerControl source, PlayerControl target) { diff --git a/ExtremeRoles/Roles/Solo/Crewmate/CurseMaker.cs b/ExtremeRoles/Roles/Solo/Crewmate/CurseMaker.cs index f63001018..914463381 100644 --- a/ExtremeRoles/Roles/Solo/Crewmate/CurseMaker.cs +++ b/ExtremeRoles/Roles/Solo/Crewmate/CurseMaker.cs @@ -381,7 +381,7 @@ public void ResetOnMeetingEnd(NetworkedPlayerInfo exiledPlayer = null) return; } - public void HookMuderPlayer(PlayerControl source, PlayerControl target) + public void HookMurderPlayer(PlayerControl source, PlayerControl target) { if (MeetingHud.Instance != null || this.isDeadBodySearchUsed || diff --git a/ExtremeRoles/Roles/Solo/Crewmate/Whisper.cs b/ExtremeRoles/Roles/Solo/Crewmate/Whisper.cs index 3eaffedb2..aef677d73 100644 --- a/ExtremeRoles/Roles/Solo/Crewmate/Whisper.cs +++ b/ExtremeRoles/Roles/Solo/Crewmate/Whisper.cs @@ -71,7 +71,7 @@ public void ResetOnMeetingStart() } } - public void HookMuderPlayer( + public void HookMurderPlayer( PlayerControl source, PlayerControl target) { diff --git a/ExtremeRoles/Roles/Solo/Impostor/Hypnotist.cs b/ExtremeRoles/Roles/Solo/Impostor/Hypnotist.cs index ef4e4c77a..b2f276a12 100644 --- a/ExtremeRoles/Roles/Solo/Impostor/Hypnotist.cs +++ b/ExtremeRoles/Roles/Solo/Impostor/Hypnotist.cs @@ -419,7 +419,7 @@ public void Update(PlayerControl rolePlayer) } } - public void HookMuderPlayer( + public void HookMurderPlayer( PlayerControl source, PlayerControl target) { if (this.doll.Contains(source.PlayerId) && diff --git a/ExtremeRoles/Roles/Solo/Liberal/Leader.cs b/ExtremeRoles/Roles/Solo/Liberal/Leader.cs index 2bdc44da7..3de34122d 100644 --- a/ExtremeRoles/Roles/Solo/Liberal/Leader.cs +++ b/ExtremeRoles/Roles/Solo/Liberal/Leader.cs @@ -286,7 +286,7 @@ public void Update(PlayerControl rolePlayer) this.reviver.Update(); } - public void HookMuderPlayer(PlayerControl source, PlayerControl target) + public void HookMurderPlayer(PlayerControl source, PlayerControl target) { if (!( ExtremeRoleManager.TryGetRole(source.PlayerId, out var role) && diff --git a/ExtremeRoles/Roles/Solo/Neutral/Eater.cs b/ExtremeRoles/Roles/Solo/Neutral/Eater.cs index 3008e41cf..ace8bd6c0 100644 --- a/ExtremeRoles/Roles/Solo/Neutral/Eater.cs +++ b/ExtremeRoles/Roles/Solo/Neutral/Eater.cs @@ -101,7 +101,7 @@ public void CreateAbility() activatingBehavior.ActiveTime)); } - public void HookMuderPlayer( + public void HookMurderPlayer( PlayerControl source, PlayerControl target) { if (MeetingHud.Instance || diff --git a/ExtremeRoles/Roles/Solo/Neutral/IronMate/IronMate.cs b/ExtremeRoles/Roles/Solo/Neutral/IronMate/IronMate.cs index f56ec1580..623337274 100644 --- a/ExtremeRoles/Roles/Solo/Neutral/IronMate/IronMate.cs +++ b/ExtremeRoles/Roles/Solo/Neutral/IronMate/IronMate.cs @@ -173,7 +173,7 @@ public void ModifiedWinPlayer(NetworkedPlayerInfo rolePlayerInfo, GameOverReason } } - public void HookMuderPlayer(PlayerControl source, PlayerControl target) + public void HookMurderPlayer(PlayerControl source, PlayerControl target) { if (PlayerControl.LocalPlayer.IsInValid() || target == null || diff --git a/ExtremeRoles/Roles/Solo/Neutral/Jackal/FurryRole.cs b/ExtremeRoles/Roles/Solo/Neutral/Jackal/FurryRole.cs index 2f3f2c56e..50cc3eb8b 100644 --- a/ExtremeRoles/Roles/Solo/Neutral/Jackal/FurryRole.cs +++ b/ExtremeRoles/Roles/Solo/Neutral/Jackal/FurryRole.cs @@ -39,7 +39,7 @@ public FurryRole() : base( RolePropPresets.OptionalDefault)) { } - public void HookMuderPlayer(PlayerControl _, PlayerControl target) + public void HookMurderPlayer(PlayerControl _, PlayerControl target) { if (this.isUpdate || target == null || diff --git a/ExtremeRoles/Roles/Solo/Neutral/Queen/QueenRole.cs b/ExtremeRoles/Roles/Solo/Neutral/Queen/QueenRole.cs index fe5498feb..8dad4d040 100644 --- a/ExtremeRoles/Roles/Solo/Neutral/Queen/QueenRole.cs +++ b/ExtremeRoles/Roles/Solo/Neutral/Queen/QueenRole.cs @@ -243,7 +243,7 @@ public void RemoveServantPlayer(byte servantPlayerId) this.servantPlayerId.Remove(servantPlayerId); } - public void HookMuderPlayer( + public void HookMurderPlayer( PlayerControl source, PlayerControl target) { if (source.PlayerId != target.PlayerId && diff --git a/ExtremeRoles/Roles/Solo/Neutral/Queen/ServantRole.cs b/ExtremeRoles/Roles/Solo/Neutral/Queen/ServantRole.cs index cc249e92e..b9f1c6dcc 100644 --- a/ExtremeRoles/Roles/Solo/Neutral/Queen/ServantRole.cs +++ b/ExtremeRoles/Roles/Solo/Neutral/Queen/ServantRole.cs @@ -96,7 +96,7 @@ public void SelfKillAbility(float coolTime) Button.OnMeetingEnd(); } - public void HookMuderPlayer( + public void HookMurderPlayer( PlayerControl source, PlayerControl target) { diff --git a/ExtremeRoles/Roles/Solo/Neutral/Yandere/YandereRole.cs b/ExtremeRoles/Roles/Solo/Neutral/Yandere/YandereRole.cs index 52049b9d6..c1bac9057 100644 --- a/ExtremeRoles/Roles/Solo/Neutral/Yandere/YandereRole.cs +++ b/ExtremeRoles/Roles/Solo/Neutral/Yandere/YandereRole.cs @@ -306,7 +306,7 @@ public void Update(PlayerControl rolePlayer) checkRunawayNextMeeting(); } - public void HookMuderPlayer( + public void HookMurderPlayer( PlayerControl source, PlayerControl target) { if (this.target.IsContain(target.PlayerId)) From d3b84f1b09375042594d3cb80252e1da3a42d015 Mon Sep 17 00:00:00 2001 From: yukieiji <40425798+yukieiji@users.noreply.github.com> Date: Sun, 17 May 2026 16:06:13 +0900 Subject: [PATCH 3/3] refactor --- ExtremeRoles/Roles/API/SingleRoleBase.cs | 2 -- doc/dev/role/07_interfaces.md | 24 ++++++++++++++---------- doc/dev/role/08_methods.md | 17 ++++++----------- 3 files changed, 20 insertions(+), 23 deletions(-) diff --git a/ExtremeRoles/Roles/API/SingleRoleBase.cs b/ExtremeRoles/Roles/API/SingleRoleBase.cs index 4313d88f0..4bf094eb4 100644 --- a/ExtremeRoles/Roles/API/SingleRoleBase.cs +++ b/ExtremeRoles/Roles/API/SingleRoleBase.cs @@ -111,8 +111,6 @@ public virtual SingleRoleBase Clone() return role; } - public virtual bool IsTeamsWin() => this.IsWin; - protected override void CommonInit() { var baseOption = GameOptionsManager.Instance.CurrentGameOptions; diff --git a/doc/dev/role/07_interfaces.md b/doc/dev/role/07_interfaces.md index fdd5654be..d1fc43b81 100644 --- a/doc/dev/role/07_interfaces.md +++ b/doc/dev/role/07_interfaces.md @@ -56,11 +56,6 @@ - `Action CreateAbilityAction(PlayerVoteArea instance)`: ボタンが押された時の動作を返します。 - `Sprite AbilityImage { get; }`: ボタンのアイコン画像。 -#### `IRoleHookVoteEnd` -投票結果が確定した直後に呼ばれます。 -- `void HookVoteEnd(MeetingHud instance, NetworkedPlayerInfo rolePlayer, IReadOnlyDictionary voteIndex)` - - `voteIndex`: 各プレイヤーが得た最終的な票数。 - --- ### フック・割り込み @@ -77,10 +72,20 @@ - `void OnEndKill()` #### `IRoleMurderPlayerHook` -プレイヤーが殺害される瞬間の処理に割り込みます(キルボタン押下時ではなく、実際の死亡処理時)。 -- `void HookMuderPlayer(PlayerControl source, PlayerControl target)` +プレイヤーが殺害される瞬間の処理(キルボタン押下時ではなく、実際の死亡処理時)。 +- `void HookMurderPlayer(PlayerControl source, PlayerControl target)` - `source`: 加害者, `target`: 被害者。 +#### `IRoleHookVoteEnd` +投票結果が確定した直後に呼ばれます。 +- `void HookVoteEnd(MeetingHud instance, NetworkedPlayerInfo rolePlayer, IReadOnlyDictionary voteIndex)` + - `voteIndex`: 各プレイヤーが得た最終的な票数。 + +#### `IRoleReviveHook` +誰かが組成した瞬間の処理 +- `void HookRevive(PlayerControl revivePlayer)`: 誰かが蘇生した時に呼ばれるフック。 + + --- ### 特殊状態・ライフサイクル @@ -95,10 +100,9 @@ - `T NoneAwakeRole { get; }`: 未覚醒状態のID。 - `string GetFakeOptionString()`: オプション画面での表示。 -#### `IRoleOnRevive` / `IRoleReviveHook` +#### `IRoleOnRevive` 蘇生に関する処理を実装します。 - `void ReviveAction(PlayerControl player)`: 自身が蘇生した時の処理。 -- `void HookRevive(PlayerControl revivePlayer)`: 誰かが蘇生した時に呼ばれるフック。 #### `IRoleFakeIntro` イントロ画面で別のチームとして表示させたい場合に実装します。 @@ -113,7 +117,7 @@ ## 能力・ロジック (AbilityHandler) 向け #### `IKilledFrom` -キルボタンが押された瞬間の判定を行います。 +キルボタンが押された瞬間の判定を行います。キルボタンを押したプレイヤーから呼ばれます - `bool TryKilledFrom(PlayerControl rolePlayer, PlayerControl fromPlayer)` - `true` を返すと、通常のキル処理を続行(殺害を許可)します。 diff --git a/doc/dev/role/08_methods.md b/doc/dev/role/08_methods.md index 900f845e8..09edf0704 100644 --- a/doc/dev/role/08_methods.md +++ b/doc/dev/role/08_methods.md @@ -26,10 +26,6 @@ ## 勝利条件・判定 -#### `bool IsTeamsWin()` -自身のチームが勝利したかどうかを判定します。 -- **戻り値**: チームが勝利条件を満たしていれば `true`。 - #### `bool IsSameTeam(SingleRoleBase targetRole)` 対象の役職と同じチームかどうかを判定します。 - `targetRole`: 比較対象の役職。 @@ -62,7 +58,7 @@ #### `Color GetNameColor(bool isTruthColor = false)` プレイヤー名の色を取得します。 -- `isTruthColor`: 真実の色を要求されているか(偽装を考慮するか)。 +- `isTruthColor`: この役職のプレイヤー等が死亡時等に`true`になります。覚醒役職等で色を隠したい時に`override`して分岐を実装します - **戻り値**: 表示する `Color`。 #### `Color GetTargetRoleSeeColor(SingleRoleBase targetRole, byte targetPlayerId)` @@ -92,30 +88,29 @@ - **用途**: 現在の残り回数やカウントなどを動的に表示したい場合にオーバーライドします。 #### `bool IsBlockShowMeetingRoleInfo()` / `IsBlockShowPlayingRoleInfo()` -会議中やプレイ中に役職情報を表示するのを制限するかどうか。 +死亡時に会議中やプレイ中に役職情報を表示するのを制限するかどうか。 - **戻り値**: `true` で非表示。 --- ## オプション設定 -#### `AutoParentSetOptionCategoryFactory CreateSpawnOption()` (abstract) -役職の出現率や人数のオプションを生成します。 - #### `void CreateSpecificOption(AutoParentSetOptionCategoryFactory factory)` (abstract) 役職固有のオプション(例:クールタイム、使用回数など)を生成します。 +`override`して役職特有のオプション作成します #### `void CreateVisionOption(AutoParentSetOptionCategoryFactory factory, bool ignorePrefix = true)` 視界に関するオプションを生成します。 +基本的には使用しないですが、状態に応じて視界に関するオプションを追加したい時に使用します --- ## 実装のポイント -`SingleRoleBase` は多くの `virtual` プロパティ(`CanUseAdmin`, `UseVent` など)を持っています。これらをコンストラクタや `RoleSpecificInit` で適切に設定することで、役職の基本的な能力を定義できます。 +`SingleRoleBase` は多くの は多くのフィールドやプロパティ(`CanUseAdmin`, `UseVent`など)を持っています。これらを `RoleSpecificInit` で適切に設定することで、役職の基本的な能力を定義できます。 ```csharp -public MyRole(RoleArgs arg) : base(arg) { +protected override void RoleSpecificInit() { this.CanKill = true; this.UseVent = true; this.HasTask = false;