ペンタブ使用中にクリスタで描画できなくなる不具合と対処法

検索しても同様の問題/解決策は見当たらなかったので。備忘録です

症状

  • CLIP STUDIO PAINTでペンタブを使用中、突然キャンバスが反応しなくなる。カーソル移動やツール選択、ペンサイズの変更は可能だが、線を描画できない
  • ウィンドウ切り替え、Windowsタスクバーやサブモニタの操作など、クリスタ範囲外の操作が一切できなくなる
  • 一度発症すると、マウスによる操作も効かなくなる
  • Alt+Ctrl+Delでタスクマネージャーを開くと一時的に解消する

解決策

ワコムタブレットのプロパティ

余談

インターネットで調べても「ドライバ入ってる?」「USBポートが(略」「ネットワークが」みたいな内容しか存在しない。虚無
思い返してみると、ペンタブとマウスの操作が重複した時に発症していた気もする。何らかの原因でアクティブウィンドウの取得に失敗してる?

絵 描き方 わからん

WoWS - 推力バーモント: 最速転舵、減速不要です

バーモント+推力UGについて、「減速→加速転舵すると通常より高い速力で旋回できる」という話を聞いたので
これ、減速いりません。

現象

推力UGバーモントで転舵を行うと、(推力なしと比較して)旋回中の速力が上下する。

どうやら元の話だと

  • 加速中に転舵すると速力増加
  • トップスピードから転舵すると速力低下
  • 減速してから転舵+加速することで速力を維持

という結論になっているようですが、これは正確ではありません

速力を維持したまま転舵する方法

  • 船が旋回し始めた時に、一瞬だけ速力設定を変化させる

実際の速力調整は一切不要です。一瞬3/4とFullを切り替えるだけでOK

動画

youtu.be

WoWS - 観測機でズームすると視点が飛んでしまうバグの対処法

対処法

ターゲットをロックオンした状態で空を見上げてズームイン(標準ではShiftキー)します

なぜ視点が"飛ぶ"のか

ズームイン時の照準点が、ロック補正の掛からない遠くの海面になっているのが原因です。
実際、この現象は観測機がないときも発生しています。ただし、カメラの俯角が小さくエイム修正も容易なため知覚されづらいです。
youtu.be

WoWS - UI Mod作成の基本 2: Modをゲームに認識させる

前回
kawaii-14.hatenablog.com

はじめに

UnboundまたはUnbound2で作成したModは、ゲームが自動的に認識してくれるわけではありません。
Modファイルのパスと表示したい要素をXMLに指定して読み込ませる必要があります。
ただし、Python+Unboundの場合は例外です。(PythonのメソッドからUnboundをロードする)
また、既存の要素を置き換える場合と、新規要素を増やす場合では若干操作が異なります。

Unbound/Unbound2共に

  • Modファイルを読み込むと、記述された各要素がUnbound系グローバルスコープにロードされる
  • グローバルスコープに存在するだけではUIとして機能しない
  • 表示する要素は別途指定する必要がある

といった大まかなイメージを持っておくとよいです。

これらの操作はゲームのアップデート毎(ゲームフォルダが変わる度)に必ず要求されますが、半自動的に管理するためのModも存在します。

Modをクライアントに読み込ませる方法

ファイルとフォルダ

省略のため、頻出するパスは以下のように表します。res_mods内で途中のディレクトリが欠けている場合は適宜作成してください

  • gui: (World_of_Warships)\bin\(最新バージョン)\res_mods\guiフォルダ
  • uss_settings: gui\uss_settings.xml Modのパスを指定するファイルです。存在しない場合はUnpackerから抽出してください
  • battle_elements: gui\battle_elements.xml 表示する要素を指定するファイルです。存在しない場合はUnpackerから抽出してください

編集するファイル

既存要素を置き換えるMod 新規要素を追加するMod
Unbound uss_settings uss_settings, battle_elements
Unbound2 なし battle_elements

新規要素を追加するModの場合、battle_elementsは必ず編集することになります。
また、UnboundではModファイルパスを必ず指定する必要があります。
Unbound2ではファイルが自動的に読み込まれるため、uss_settingsを改変する必要はありません。

uss_settingsの設定

uss_settings.xmlを開き、<mods>要素の下に作成したModのファイルパスを記述します。

<mods>
    <swffile>../unbound/mods/ModFileName.swf</swffile>
    <xmlfile>../unbound/mods/ModFileName.xml</xmlfile>
</mods>

例: gui\unbound\modsTestMod.xmlTestMod.swfがある場合

uss_settingsにパスを通す例

battle_elementsの設定

重要: 既存の要素を置き換えるModの場合、このファイルを編集する必要はありません。

パラメータ
  • hitTest: UIの当たり判定を制御します。クリックやD&Dを利用する場合はtrueに、それ以外はfalseを指定します
  • tempModName: 他のModと競合しない自由な名前を設定してください。慣例ではunboundModNameになっていることが多いです
  • rootElementName(Unbound)またはelementName(Unbound2): Modとして読み込む要素の名前です。
<element>要素

<elementList>の内側に追加します

  • Unboundの場合
<elementList forceHideAll="false">
    <element class="lesta.libs.unbound.UnboundElement" name="tempModName" url="battle_stats.swf">
        <properties hitTest="true|false" rootElementId="rootElementName"/>
    </element>
</elementList>
  • Unbound2の場合
<elementList forceHideAll="false">
    <element class="lesta.unbound2.UbElement" elementName="rootElementName" name="tempModName" url="battle_stats.swf">
        <properties hitTest="true|false"/>
    </element>
</elementList>
<controller>要素

<controllers>の内側に追加します
Unbound2では不要です。

<controllers>
    <controller class="lesta.dialogs.battle_window_controllers.UnboundElementController" clips="tempModName"/>
</controllers>

例: Hello Worldを表示するMod
下記画像だとrootElementId="TestModRoot"またはelementName="TestModRoot"になります

例: Unboundの場合
例: Unbound2の場合

半自動でModを登録する方法

ModsInstallerというPython Modによって、これらの作業を自動化することができます。
使い方の説明は配布元のマニュアルに譲りますが、編集するファイルや内容等、この記事の知識が前提として必要になります。作者: Monstrofil, Roslich
drive.google.com

WoWS - UI Mod作成の基本 1: UnboundとDataHub

はじめに

World of Warshipsは複数のプログラミング言語で構成されており、それぞれ以下のような役割を担っています

  1. ゲームの中核(オブジェクトのレンダリングやダメージ処理など): Python, C++
  2. UI(ダメージポップアップや艦艇名表示など): ActionScript3, Unbound, Unbound2, Gameface

ゲーム中核とUIの間でデータを橋渡しするのがDataHubというオブジェクトです。

詳細は公式ドキュメントにもありませんが、UI系Modの作成ではほぼ必須の知識になります。
今までのModderは公式のマークアップや他人のModを見て独学してます。この狂った連鎖を断ち切りたい
具体例なんかは次回以降(SoonTM)にします

必要なもの

  • やる気と時間: 作ったModが思い通りに動かないこと多数。公式ドキュメントに記載されている手法も特定条件では動かなかったり(しかも条件書いてない)。Modテストのためにクライアント複数回起動するだけで1時間失ったりします。これはマジです
  • FlashDevelop: .swcファイルを読み込めるFlash IDEなら他のものでもOKです
  • SWCファイル: 下記リンクから最新バージョンのフォルダを選択、as3_library.zipをダウンロードしてください

drive.google.com

ダウンロードした.swcファイルのパスをIDEに通してください。
FlashDevelopであれば、画面上部のProject→Properties...→Compiler Options→SWC Librariesから設定できます

SWC Libraries

この手順が完了すると、FlashDevelopのProjectカラムにあるRefences→Classesより、各Component(後述)の持つプロパティやイベントが確認できるようになります。

例: AccountNameコンポーネントの持つ要素

DataHubのデータ構造

全体図(要拡大)

定数について

Unbound系に共通する定数としてCC(ComponentClass)が存在し、Component(後述)のクラスIDが保存されています。
例として、AccountNameコンポーネント(プレイヤーの名前が保持されている)のクラスIDはCC.accountNameのようにアクセスできます。

Collectionsについて

Collectionを格納するオブジェクトです。クラスID(CC.something)を使用して特定のCollectionを取得できます。

Collectionについて

特定のComponentを持ったEntityへの参照を格納する配列です。
配列インデックスを指定して任意のEntityを取り出せます。
また、コレクションから要素を選択し、新たなコレクションを作成することも可能です。
例えばAccountNameコレクションには、AccountNameコンポーネントを含むEntityが全て保存されています。

Entityについて

Componentを格納するコンテナです。
全てのEntityはユニークなIDを持ち、これを用いて直接参照することができます。

Componentについて

数値、文字列、イベントなど、実態のあるデータを保持するオブジェクトです。
前出のAccountNameコンポーネントであれば

  • name: プレイヤー名(IGN)
  • nickName: ニックネーム(クランタグを含むIGN)
  • evChanged: 上記どちらか変更された際トリガーされるイベント

が保存されています。
また、primaryKeyメソッドが存在する場合はユニークIDを持ちます。
ユニークIDは1つまたは複数の要素で構成されており、前者の場合は数値や文字列、後者の場合は'element1_element2'のようにアンダーバーで各要素を結合した文字列がキーとなります。

オブジェクトの取得方法

Collection

variableNameCC.somethingのコレクションを代入します。
variableName[index]で任意のインデックスにあるEntityを取り出すことができます

Unbound <bind name="collectionDH" value="CC.something; 'variableName'"/>
Unbound2 (var variableName:gfx = "$datahub.getCollection(CC.something)")

Entity

variableNameに任意のEntityを代入します。

EntityのユニークID(entity.id)から
Unbound <bind name="entityDH" value="'variableName'; entityId"/>
Unbound2 (var variableName:gfx = "$datahub.getEntity(entityId)")
ComponentのユニークIDから

複数の要素からなるIDの場合、自分で文字列を作成してgetPrimaryEntityを使用するか、getPrimaryCompositeEntityの引数に結合前の要素を与えることでEntityを得ることができます。
例1: ownSquadronのユニークIDは、飛行中隊のインデックス(ロケット:0, 雷撃機:1, 爆撃機:2等)です。getPrimaryEntity(CC.ownSquadron, index)
例2: battleConsumableのユニークIDは、消耗品タイプと飛行中隊インデックス(艦消耗品の場合-1)の結合文字列type_squadronIdです。
getPrimaryCompositeEntity(CC.battleConsumable, consumableType, squadronId)getPrimaryEntity(CC.battleConsumable, 'consumableType_squadronId')と等価です。

Unbound <bind name="primaryEntityDH" value="'variableName'; CC.something; index"/>
Unbound2 (var variableName:gfx = "$datahub.getPrimaryEntity(CC.something, index)")
(var variableName:gfx = "$datahub.getPrimaryCompositeEntity(CC.something, *args)")
コレクションの最初のEntity

collections[CC.something][0]と等価です。

Unbound <bind name="firstEntityDH" value="'variableName'; CC.something"/>
Unbound2 (var variableName:gfx = "$datahub.getSingleEntity(CC.something)")

Component

コレクション最初のEntityにあるComponent

collections[CC.something][0].somethingまたはgetSingleEntity(CC.something).somethingと等価です。

Unbound2 (var variableName:gfx = "$datahub.getSingleComponent(CC.something)")

WoWS - 艦載機の飛行速度と照準の拡大

TLDR

ロケットと爆弾の照準は、艦載機の飛行速度から影響を受けて進行方向に延伸します。
ほぼ戦闘に影響しませんが、減速するほどレティクルが縮み命中精度が向上します。

仕組み

関連するGameParams
  • attackInterval[s]: 弾体の発射間隔
  • attackCount: 弾体の発射回数
  • outerSalvoSize[BW]: 最大散布界(詳細は以下記事を参照)
  • minSpread, maxSpread: 拡散率(詳細は以下記事を参照)

kawaii-14.hatenablog.com

計算式

レティクルが伸びる長さ[BW] = v × (attackInterval × (attackCount - 1 ))
ただしv[BW/s]は艦載機の速度です
一応単位換算を載せておくと

  • 1[knots] = 2.6854[m/s]
  • 1[m/s] = 1/30[BW/s]

になります

これは軸長全体の増加量なので、実際の散布界半径に加算するときは0.5倍してください。
半軸の長さ[BW] = outerSalvoSize * minSpread + レティクルが伸びる長さ * 0.5

WoWS - 抗堪スキルが区画HPへ与える影響

割と最近実装された仕様。何か検証するときに役立つかもしれない。フランス駆逐で抗堪を取ると被ダメージが増えたバグの元凶(現在は修正済み)

概要

艦艇の最大HP変更(抗堪、軍拡のバフ等)は、各区画のHPおよび最大HPを同時に変化させる。
恐らく、軍拡競争などで区画飽和が異常に強くなることを防ぐための仕様。

例: Marceau (青: 通常, 赤: 抗堪+4000)

区画HPの計算

対象となる区画

影響を受けるのはモジュールでない区画のみ。GameParamsで言うとHitLocation.hlTypeが以下に該当するもの

hlType 具体例
simple_hitlocation 艦首, 艦尾, 船体(砲殻), 補助区画
citadel_hitlocation バイタル
casemate_hitlocation ケースメイト(駆逐艦の中央部等)
hull_hitlocation 艦全体
supersctructure_hitlocation 上部構造物
パラメータ

アンダーバー以降の単語は説明のために追加したもの。値を検索するときは無視すること。
currentHPを除く全パラメーターはGameParams内に存在する

  • health_base: デフォルトの艦艇最大HP
  • health: スキルやアップグレードにより変化した後の艦艇の最大HP
  • healthHullCoeff: 軍拡のバフなどで得られる、艦艇の最大HPに対する係数
  • maxHP_base: デフォルトの区画最大HP
  • maxHP: 変化後の区画最大HP
  • currentHP: 現在の区画HP
最大区画HP(maxHP)の計算式

ceil(maxHP_base * healthHullCoeff * (health / health_base) / 50) * 50

簡単に言うと、HPの増加割合とおよそ同じだけ区画最大HPを増加させる。
問題にはならないものの、ceil(切り上げ)を使っているため区画HPは本来より若干多く配分される。

区画HP(currentHP)の計算式

min(currentHP * max((maxHP / maxHP_base), 1.0), maxHP)

最大区画HPの増加に応じて現在の区画HPも増加する。現在値が最大区画HPを超えた場合はキャップが入るものの、基本的に減少することはない。(min、max関数部分が該当)