ゲーム好きな豚のしっぽ

筆者の下手の横好きなゲーム日記、情報メモです。主にプレイするのはtrophymanager、WoT、WoWS、洋モノSLGなどの予定。

EntityDataManager

注意事項

このリファレンスは筆者が記述した時点での拙い知識で翻訳、解釈したもののメモです。
誤訳や理解不足の可能性を多分に含みます。ご覧になる際はご注意ください。
ソースは1.9-12.16.0.1797-1.9-snapshotのものを使用しています。

EntityDataManager

Minecraft1.9からDataWatcherに変わって導入されたデータ同期のためのオブジェクトです。
DataWatcherの問題点であった、クラスごとにIDの指すオブジェクトの型や意味が違う、アクセス時にタイプを特定しないため、キャストが必要となり最悪の場合エラーの原因になる、IDでのみアクセスするため、そのアクセスが何を意図したものかわかりづらい、などを解決しています。以下、DataManagerと略して表記します。

DataManagerの利用法

DataManagerは、エンティティのプロパティ*1のうち、同期の必要のあるものを一括で管理するオブジェクトです。エンティティのインスタンス1つにつき1つが用意され、DataWatcherと同様に、初期化の際に監視するプロパティを登録します。

プロパティ生成と登録

プロパティはDataParamater<T>で実装されており、利用するときはDataManagerのcreateKeyメソッドから生成します。生成されたDataParamaterをフィールドとして保持しておき、これに対するアクセスをアクセサで管理することでプロパティとしての機能を実現しています。

生成の例:Entityクラスから

private static final DataParameter<Byte> FLAGS = EntityDataManager.<Byte>createKey(Entity.class, DataSerializers.BYTE);
private static final DataParameter<Integer> AIR = EntityDataManager.<Integer>createKey(Entity.class, DataSerializers.VARINT);
private static final DataParameter<String> CUSTOM_NAME = EntityDataManager.<String>createKey(Entity.class, DataSerializers.STRING);
private static final DataParameter<Boolean> CUSTOM_NAME_VISIBLE = EntityDataManager.<Boolean>createKey(Entity.class, DataSerializers.BOOLEAN);
private static final DataParameter<Boolean> SILENT = EntityDataManager.<Boolean>createKey(Entity.class, DataSerializers.BOOLEAN);

ジェネリクスでデータの型が明らかになっていること、フィールド名で用途を明示できることが大きな利点です。

生成時にcreateKeyメソッドに渡しているDataSirializarsの定数は、格納されるデータの型を表します。

DataSirializerの種類

名前 予想される用途
BLOCK_POS BlockPos ブロック基準の座標
BOOLEAN boolan 各種フラグ
BYTE Byte 8bitのデータやフラグの組み合わせ
FACING EnumFacing ブロックが向いている方向
FLOAT Float 単精度浮動小数
OPTIONAL_BLOCK_POS Optional<BlockPos> OptionalでラップしたBlockPos
OPTIONAL_BLOCK_STATE Optional<IBlockState> OptionalでラップしたBlockState
OPTIONAL_ITEM_STACK Optional<ItemStack> OptionalでラップしたItemStack
OPTIONAL_UNIQUE_ID Optional<UUID> OptionalでラップしたUUID。プレイヤーやエンティティの識別子
ROTATIONS Rotations 現在のところArmorStandの部位の回転方向のみ
STRING String 文字列
TEXT_COMPONENT ITextComponent チャットメッセージ用の装飾指定つき文字列
VARINT Integer 整数

登録には、DataManagerのregister(DataParamater<T>, T)を使用します。
DataWatcherのaddObject(int,Object)に相当しますが、数値ではなく生成しておいたDataParamater自体をキーに使用しますので、可読性が格段に高くなります。また、内部的にはIDに数値を使用していますが、利用者はそれを知っている必要はありません。DataManagerが自動的に採番して重複を避けるようになっています。

登録の例:Entityクラスから

        this.dataWatcher = new EntityDataManager(this);//エンティティ自身を渡してDataManagerを生成
        this.dataWatcher.register(FLAGS, Byte.valueOf((byte)0));//悪名高いflags
        this.dataWatcher.register(AIR, Integer.valueOf(300));
        this.dataWatcher.register(CUSTOM_NAME_VISIBLE, Boolean.valueOf(false));
        this.dataWatcher.register(CUSTOM_NAME, "");
        this.dataWatcher.register(SILENT, Boolean.valueOf(false));

登録されたDataParameterへのアクセスも、DataManagerを通して行います。
アクセスに使用するメソッドはget(DataParameter)とset(DataParameter,T value)でシンプルです。
と言いたいところですが、古いバージョンのソースでプライマリ型を指定されているプロパティについては、キャストやvalueOfで型変換行う必要があります。自作modで新しくプロパティを追加するときには、プライマリ型ではなくラッパークラスを使用するように心がけた方がよさそうです*2
DataParamaterを定数として宣言していますので、実際のソースは以下のようになります。

アクセサの例:Entityクラスから

    public int getAir()
    {
        return ((Integer)this.dataWatcher.get(AIR)).intValue();
    }

    public void setAir(int air)
    {
        this.dataWatcher.set(AIR, Integer.valueOf(air));
    }

DataWatcherの時とは違い、どのデータにアクセスしようとしているかが明確になっています。また、IDEを使用しているのであればデータの型も確かめやすいので、コーディングは格段に楽になるといえるでしょう。先ほども述べましたが、型を宣言しているのに前方互換のためにプライマリ型に戻さなくてはならなかったりするのは、仕様上仕方がありません。

セッターから新しい値が与えられると、エンティティのnotifyDataManagerChange(DataParamater key)が呼び出されます。
エンティティはこのkeyがどのプロパティかを確認して、必要があるならばアニメーションを開始したり、SEを鳴らしたりといった処理を行います。このメソッドの中では親クラスの挙動を変更したい場合を除いて、親クラスの同メソッドを呼び出す必要があります。忘れるとどのような不具合が発生するかわかりませんので、忘れないようにしましょう。

notifyDataManagerChangeの実装の例:EntityLivingクラスから

    public void notifyDataManagerChange(DataParameter<?> key)
    {
        super.notifyDataManagerChange(key);

        if (HAND_STATES.equals(key) && this.worldObj.isRemote)
        {
            if (this.isHandActive() && this.activeItemStack == null)
            {
                this.activeItemStack = this.getHeldItem(this.getActiveHand());

                if (this.activeItemStack != null)
                {
                    this.activeItemStackUseCount = this.activeItemStack.getMaxItemUseDuration();
                }
            }
            else if (!this.isHandActive() && this.activeItemStack != null)
            {
                this.activeItemStack = null;
                this.activeItemStackUseCount = 0;
            }
        }
    }

この例では(おそらく)1.9で追加された両手持ちのアイテムを入れ替える処理を行っています。

DataWatcherから変更点

利用法とその目的はDataWatcherから大きく変わってはいませんが、その仕組みは大きく変化しており、いくつかの制限が撤廃されているようです。

登録できるプロパティが255個(ID0~254)になった

DataManagerのregisterメソッドを見ると、自動採番のIDが255未満で新しいオブジェクトを追加できるようになっています。

登録できる型が増えた

今後も増えるかもしれません。

変更部分のみが送信されるようになった

ゲームサイクルのアップデートの際に、実際に数値の変更があったプロパティのみを送信するように設計されています。DataWatcherでは送信されながら使用されないデータが多く、無駄が多かったという判断でしょうか。格納できるデータの量が増えていることも理由のひとつかもしれません。

*1:アクセサでのみアクセスできるオブジェクトの属性。実体がそのインスタンスのフィールドとは限らない。実装がどのように変化しても、利用者はアクセサのみを使用するため影響を受けにくい。今回のような同期をとる必要のあるフィールドや、単位や型の変換が必要なフィールドへのアクセスを容易にする。

*2:コレクションにプライマリ型は入れられないし、Streamにもできない

DataWatcherに登録されているフィールド

注意事項

このリファレンスは筆者が記述した時点での拙い知識で翻訳、解釈したもののメモです。
誤訳や理解不足の可能性を多分に含みます。ご覧になる際はご注意ください。
ソースは1.8.9 - 11.15.1.1722のものを使用しています。

1.9からDataWatcherに代わってEntityDataManagerが使用されています。
この表でもわかるようにクラスごとにIDが指しているオブジェクトの意味も型も違っているため、その混乱を避ける意味と、キャストが減り、実行速度の改善とメモリの適正な使用が期待できるという理由から変更されたのだと思われます。おそらくこの効果は追加するエンティティが多い大型のMODほど高いです。

DataWatcherに登録されているフィールド

主にベースクラスのものをソースコードから拾っています。

DataWatcher-id 宣言クラス#プロパティ名 用途
0 Entity#flag boolean(byte) 一つのオブジェクトに5つのflagを詰め込んでいる。0:isBurning,1:isSneaking,2:isRiding,3:isSprinting,4:isEating
1 Entity#air Short 呼吸量?
2 Entity#customNameTag String エンティティの固有名
3 Entity#allwaysRenderNameTag boolean(byte) 名前を常時表示するかどうか
4 Entity#silent boolean(byte) 音を出すかどうか
6 EntityLivingBase#helth float 体力値
7 EntityLivingBase#potionMetadata Integer ポーション効果の色
8 EntityLivingBase#portionMetadata boolean(byte) ポーション効果があるかどうか
9 EntityLivingBase#arrowCountInEntity byte エンティティに刺さっている矢の数
10 EntityPlayer byte 不明
12 EntityAgeable#growingAge byte 成長までの年齢(時間)
15 EntityLivig#isAiDisabled boolean(byte) AIを使用するかどうか
16 EntityTameable#isSitting boolean(bit1) お座り状態か
16 EntityTameable#isTamed boolean(bit4) テイムされているかどうか
16 EntityVilager#profession Integer 村人の職業
17 EntytyPlayer#absorptionAmount float 呼吸量
17 EntityTameable#ownerId String 飼い主のID
18 EntityPlayer#score Integer スコア(経験値)

その他エンティティ特有のデータは多数ある模様ですが普通は触らないかと思われます。

DataWatcher

注意事項

このリファレンスは
Datawatcher - Minecraft Forge
を筆者が記述した時点での拙い知識で翻訳、解釈したもののメモです。
誤訳や理解不足の可能性を多分に含みます。ご覧になる際はご注意ください。
3/26追記
1.9からDataWatcherに代わってEntityDataManagerが使用されています。機能的には同じですが、使用できるオブジェクトの総数が増えたり、タイプセーフの考え方を取り入れて改良されているようです。使用されるメソッドも1.9からは変更となります。
1.8.9でmod作り始めているというのに公開してから変更されていることに気づいた…

DataWatcherとは何か

DataWatcherはスレッドセーフな変数の変化を追跡するオブジェクトです。
DataWatcherの利点はデータの更新が起こった際の同期を一つのパケットで行うことができるということです。また、データを必要のあるクライアントにのみ送ることができるので、それを必要としない1万マイル離れた誰かがあなたの体力の変更を受信することはありません。欠点は、最大で32個の限定された型[Byte,Short,Integer,Float,String,ItemStack,ShunkCoorinates]でのみ情報を保存するということです。DateWatcherのChunkCoodinateはエンティティの座標ですので、あなたはそれを必要としない公算が高いです。おそらくあなたが最も利用する典型的な型はint,float,Stringです。

先ほど述べたように、DataWatcherは32個のオブジェクトのみ監視できます。以下が、LvingEntityでの値です。
#は元の記事には印があるもののFoegeのソースでは確認できなかったもの

Entity class 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
Entity x x                                                            
 ┗EntityLivingBase x x         x x x x                                            
 ┣EntityPlayer x x         x x x x             x x x                          
 ┗EntityLiving x x         x x x x # #                                        
   ┣EntitySlime x x         x x x x x x         x                              
   ┣EntityAmbientCreatuer x x         x x x x x x                                        
   ┃┗EntityBat x x         x x x x x x         x                              
   ┣EntityFlying x x         x x x x x x                                        
   ┃┗EntityGhast x x         x x x x x x         x                              
   ┗EntityCreature x x         x x x x x x                                        
     ┣EntityGolem x x         x x x x x x                                        
     ┃┗EntityIronGolem x x         x x x x x x         x                              
     ┣EntityMob x x         x x x x x x                                        
     ┃┣EntityBlaze x x         x x x x x x         x                              
     ┃┣EntityCreeper x x         x x x x x x         x x x                          
     ┃┣EntityEndermen x x         x x x x x x         x x x                          
     ┃┣EntitySkeleton x x         x x x x x x   x                                    
     ┃┣EntitySpider x x         x x x x x x         x                              
     ┗EntityAgeable x x         x x x x x x x                                      
       ┣EntityVillager x x         x x x x x x x       x                              
       ┗EntityAnimal x x         x x x x x x x                                      
         ┣EntitySheep x x         x x x x x x x       x                              
         ┣EntityPig x x         x x x x x x x       x                              
         ┣EntityHorse x x         x x x x x x x       x     x x x x                  
         ┗EntityTameable x x         x x x x x x x       x x                            
           ┣EntityOcelot x x         x x x x x x x       x x x                          
           ┗EntityWolf x x         x x x x x x x       x x x x x                      

では、DataWatcherに新しい値を追加します。それにはaddObject(IL)メソッドを使用します。新しい値はリストに加えられて初めて、DataWatcherが監視を始めます。このとき、DataWatcherには、あなたが保存したい値がどの型であるのかを明示するようにしてください。1と1.0は同じ値として評価されますが、その型は同じではありません。

DataWatcher dw = entity.getDataWatcher();
//dw.addObject(id, object);
dw.addObject(20, 1);//add a new int with id 20, when initializing you can put anything even if it's irrelevant
//(新しくintをid20で追加。初期化の際にたとえそれが無関係な値でも追加することができます。)
dw.addObject(21, 2.5f);//new float at id 21
dw.addObject(22, "hello datawatcher");//string@22
dw.addObject(20, 2);//this will not update the value, this will crash because there's already something at 20, there is another method to update which we will see later
//(この値はアップデートされません。既に20に値があるため、クラッシュします。後ほど、アップデートのためのメソッドを記述します。)
どこで追加するのか

あなたが自作のmobを使用する際には、スポーンしたmobのインスタンスはentityInitメソッドを呼び出して初期化できます。DataWatcherにあなたの監視したいオブジェクトを追加する前に、まずはsuper.entityInit()をコールしましょう。なぜなら親クラスがすでにいくつかのIDを使用しているからです。
もしもあなたがバニラの既存のmobにステータス監視を追加したいときには、EntityConstructing型のイベントを処理できるハンドラを準備する必要があります。EntityConstructingイベントはエンティティと呼ばれるもろもろの参照が現れるたびに呼び出されます。ハンドラの中でinstanceofを使ってエンティティが監視したい型なのかをチェックして、getDatawatcherメソッドでDataWatcherを取得し、単純にaddObjectで監視したい値を追加します。

@ForgeSubscribe
public void handleConstruction(EntityConstructing event){
    if(event.entity instanceof EntityPlayer){
        DataWatcher dw = event.entity.getDataWatcher();
        dw.addObject(20, 0.0f);//karma level
        dw.addObject(21, 0.0f);//amount of mana
        dw.addObject(22, 0);//amount of kill
    }
}

判りやすいシンプルな例ですな
DataWatcherの値はどちらのサイドでも知っているようにしましょう。なぜなら、サーバーが新しい値があるよ、と言っても、クライアントがそれを期待していないのなら、それは完全に無視されてしまうからです。ですから、このハンドラはどちらのサイドでも登録されているようにします。

どのように相互作用するか

次に、DataWatcherの読み書きについてのポイントです。もしも2つのスレッドが同時に書き込みを行おうとした場合、片方はもう片方の書き込みが終わるまで待機することに注意しましょう。

DataWatcherからの読み込み:

DataWatcher dw = entity.getDataWatcher();
//dw.getWatchableObject*type*(int id);
int amountOfKill = dw.getWatchableObjectInt(22);
String title = dw.getWatchableObjectString(23);
ItemStack itemInLeftHand = dw.getWatchableObjectItemStack(24);
//now float was not translated in forge 789, maybe its different in other version
//the name should be "getWatchableObjectFloat(int id)" but its:
//(Forge789現在、floatは翻訳されていません。おそらくほかのバージョンではこのメソッド名は”getWatchableObjectFloat(int id)”となるはずです)
float karmaLevel = dw.func_111145_d(20);

この例では、RenderPlayerEventで負のカルマを持つプレイヤーは暗いオーラを、正のカルマを持つプレイヤーは明るいオーラをまとうようにすることができるでしょう。

DateWatcherに書き込むときには、まず次のことを理解しましょう。DataWatcherはサーバーからクライアントへアップデートを通知する唯一のものであるということ、クライアントがDateWatcherに書き込むことはよほど特殊な理由がない限りは意味がないということです。(例えばreiminimapではクライアント側でのみウェイポイントを描画します。そしてこれはサーバー側では存在しませんし、アップデートする必要はないでしょう。)

DataWatcherへの書き込み:

DataWatcher dw = player.getDataWatcher();
dw.updateObject(20, karmaMap.get(player.username));//writing (updating) is very similar to addObjectMethod. in this case karmaMap would be a hashmap<String, float> that hold the values of everyone's karma
//(addObjectメソッドとよく似た方法で書き込み(アップデート)を行います。この場合、karumaMapはHashMap<String,float>で皆のカルマの値を保持しています)
//訳注:karumaMapからプレイヤー名で値を引いてwatcherの値を上書きしている。先の読み込みの例のFloatの値の話から続いている
どこでDataWatcherを使用してはいけない

理想としては、特定のクライアントに向けて使用されているすべての変数はほかのプレイヤーに伝搬するべきではなく、DataWatcherに入れられるべきではありません。パケットとクライアントプロキシを使えば同じことを達成できるため、あなたはスペースを無駄遣いしていることになります。たとえば、あるプレイヤーが持っているお金の量は他のプレイヤーが参照できてはいけないでしょうから、DataWatcherに登録されるべきではありません。仮にあなたがほかのプレイヤーのお金の量を取得できるようにしたいのであれば、それは頻繁に行われる操作ではありませんから、リクエストを送るパケットを作ることを考えるべきです。
クライアント(プレイヤー)が意識しなくても更新されるべきデータはDataWathcer、インタラクト(右クリックやキー操作)でデータが必要になるときにはパケットでリクエストを送る、と考えれば良いでしょうか

Attribute

注意事項

このリファレンスは
Attribute – Minecraft Wiki
を筆者が記述した時点での拙い知識で翻訳、解釈したもののメモです。
誤訳や理解不足の可能性を多分に含みます。ご覧になる際はご注意ください。

Attribute

Attributesはプレイヤー、Mobのpropertyを増減させるシステムです。
また、Attributeはそれらの効果の強度を調整するmodifierを持ちます。

Attributeの適用

アイテムが適用されたとき、modifierはそのアイテムが保持または装着されていればそれに応じた修正を行います。
AttributeとmodifierはサードパーティのNBT編集ソフトを使用しなくても、コマンドを用いてアイテムやMobに追加できます。

下記のコマンドは最も近いプレイヤーに20の追加ダメージを与えるダイヤモンドソードを与えます。
もしあなたがoperationの値を0から1に変更すれば、攻撃力が(20追加の)代わりに20されます。
[{AttributeName:"generic.attackDamage",Name:"generic.attackDamage",Amount:20,
Operation:0,UUIDLeast:894654,UUIDMost:2872}]}

下記のコマンドは、通常の40ブロックの代わりに100ブロック以内の距離にいるプレイヤーを追跡するゾンビを召還します。
/summon Zombie ~ ~ ~ {Attributes:[{Name:"generic.followRange",Base:100.0}]}

snapshot15w35bでは、特定のattributeをもつスロットを指定できるようになりました。
/give @p diamond_axe 10 {AttributeModifiers[{Slot:"mainhand",AttributeName:"generic.attackDamage",
Name:"generic.attackDamage",Amount:20,Operation:0,UUIDLeast:1,UUIDMost:1}]}

スロットにはmainhand,offhand,head,chest,legs,feetなどが指定できます。

Attributes

個々のatrributeがpropertyをコントロールするには下記の名前が使用されます。attributeは基本値を持ち、いくつかのmodifierを持ちます。attributeは初期値(Mobのスポーン時に使用され、attributeの基本値にも適用されます)、ハードコードつまり通常の手段では変更できないの最小値と最大値を持ちます。modifierは基本値に対して働きますが、最大値と最小値の範囲内で計算された値となります。

最小値と最大値は他に指定がない限りは1.7×10308までとなります。

LivingEntitiesに利用出来るAttribute

これらはプレイヤーも含めたすべてのmobに見られるattributeです。

attribute 説明 基本値 最小値 最大値
generic.macHelth mobの最大体力(ハート半分単位) 20.0 0.0 1.7×10308
generic.followRange mobがプレイヤーや他のmobを追跡する範囲。多くのmobは16,zombieは40. 32.0 0.0 2048.0
generic.knockbackResistance 攻撃や爆発に対してノックバックが発生する確率。1.0のとき100% 0.0 0.0 1.0
generic.movementSpeed 単位不明のmobの最大速度。mobの1秒当たりのブロック距離はこの値の43倍を少し越えるが、さまざまな状況の影響を受ける。 0.7 0.0 1.7×10308
generic.attackDamege 攻撃力(ハート半分単位) 2.0 0.0 1.7×10308
generic.armor 防御力 0.0 0.0 30.0
プレイヤーのattribute
attribute 説明 基本値 最小値 最大値
generic.attackSpeed 攻撃力が最大になるまでのチャージ時間。単位は秒。 4.0 0.0 1024.0
generic.luck loottableの結果に影響する。 0.0 -1024.0 1024
馬のattribute
attribute 説明 基本値 最小値 最大値
horse.jumpStrength 単位不明の馬のジャンプ力 0.7 0.0 2
ゾンビのattribute
attribute 説明 基本値 最小値 最大値
zombie.spawnReinforcements ゾンビが攻撃された際に他のゾンビをスポーンさせる確率 0.0 0.0 1.0
modifier

modifierはattributeの基本値を増減させる働きを持ちます。注意すべきことは、modifierの修正結果はattributeの最小値、最大値の制限が適用されるということです。modifierはattributeのように名前をもちますが、これはmodifierの挙動を表すものではありません。代わりに、modifierの挙動はoperationで決まります。modifierは修正値とUUIDも持っています。

operation

modifierは基本値をどのように処理するかを決めるoperationを持ちます。operationは値の増減、パーセンテージ増減、パーセンテージ倍率の3つが存在します。NBTフォーマットの上ではそれぞれ0,1,2の数字で表されます。

これらの数学的な挙動は以下になります。
0:「対象」に指定の値を足す
1:「対象」に基本値×指定値パーセントを足す
2:「対象」に(1+指定値)パーセントを掛ける(つまり対象の指定値倍を加算する)
ゲームはまず基本値を「対象」に設定します。次にすべてのoperation:0のmodifierを実行してその値を「対象」とします。
次にoparation:1のmodifierをすべて実行し、最後にopration:2のmodifierを実行します。
うかつにopariton2を設定するとすさまじい数字になることがあり得る…

バニラのmodifier

前述のとおり、modifierの名前は任意で、その挙動には何ら影響しません。下記は既知のminecraftのmodifierとその値です。
注意点はいくつかのUUIDは動的に生成され、また別のUUIDはコードに直接記述されています。この表にUUIDが記載されていないものはUUIDがmodifierによって動的に生成されているものです。

modifierの名前 値の説明 既知のmodifier
Random spawn bonus スポーン時に生成されるガウス分布範囲の0.0から0.05の乱数。 generic.followRange(Operation 1:すべてのmob),Knockback Resistance(Operation 0:ゾンビと村人のみ)
Tool modifier ツールごとの値 generic.attackDamage(Operation 0:全ツール;UUID CB3F55D3-645C-4F38-A497-9C13A33DB5CF)
Weapon mofifier 武器ごとの値 generic.attackDamage(Operation 0:全ツール;UUID Tool modifierと同じ)
Sprinting speed boost プレイヤーも含めた全mobで0.3で固定のダッシュ時のスピード generic.moovementSpeed(Operation 2:全LivingEntity,UUID UUID 662A6B8D-DA3E-4C1C-8813-96EA6097278D)
Fleeing speed boost 全mobで2で固定された逃亡時の速度 generic.movementSpeed(Operation 2:全mob,UUIDUUID E199AD21-BA8A-4C53-8D13-6182D5C69D3A)
Attacking speed boost エンダーマン6.2、ゾンビピッグマン0.45で固定された攻撃時の移動速度 generic.movementSpeed(Operation 0:UUID省略)
Baby speed boost 子どもゾンビと村人ゾンビのみに存在する0.5の固定値 generic.movementSpeed(Operation 1: UUID B9766B59-9566-4402-BC1F-2EE2A276D836)
Drinking speed penalty -0.25のウィッチがポーションを飲んでいるときの値 generic.movementSpeed(Operation 0:UUID 5CD17E52-A79A-43D3-A529-90FDE04B181E)
Random Zombie spawn bonus ゾンビがスポーンするときに生成されるランダムの0.0から1.5の値 generic.followRange(Operation 2)
Leader zombie bonus ゾンビがスポーンするときに低確率で生成される値。増援を呼ぶ確立に0.5から0.75の乱数、最大体力に1.0から4.0の乱数 zombie.spawnReinforcements(Operation 0),generic.maxHealth(Operation 2)
Zombie reinforcement caller charge ゾンビが他の仲間を呼ぶたびに適用される-0.05の固定値 zombie.spownReinforcements(Operation 0)
Zombie reinforcement callee charge ゾンビが呼びだされるたびに適用される-0.05の固定値 zombie.spownReinforcements(Operation 0)
potion.mobvSpeed または potion.moveSpeed#(#付きは効果レベル) スピードアップ効果の0.2の固定値。効果のレベルで掛け算される generic.movementSpeed(Operation 2:全LivingEntity、UUID 91AEAA56-376B-4498-935B-2F7F68070635)
potion.moveSlowdown 鈍足効果の-0.15の固定値。効果レベルで掛け算される generic.movementSpeed(Operation 2:全Livingentity UUID UUID 7107DE5E-7CE8-4030-940E-514C1F160890)
potion.damageBoost ダメージ強化効果の1.3の固定値。効果レベルで掛け算される generic.attackDamage(Operation 2:全LivingEntity UUID 648D7064-6A60-4F59-8ABE-C2C23A6DD7A9)
potion.hekthBoost 体力増加効果の4の固定値。効果レベルで掛け算される generic.maxHelth(Operation 0:全LivingEntity UUID 5D6F0BA2-1186-46AC-B896-C61C5CEE99CC)

シーズン期間情報

 TrophyManagerのシーズンの開始、終了に関する情報です。

シーズン 開始日 目標設定締切 終了日 開催中
43 2015/09/07 2015/09/20 2015/11/29
42 2015/06/15 2015/06/28 2015/09/06 -
41 2015/03/21 - 2015/06/14 -

フィールドプレイヤーの能力(スキル)とポジション

※記事内容がいまひとつだったため大幅に改稿しました(2015/07/06)

 TrophyManagerでは、選手の能力は20段階の数値で表される要素と、それ以外の様々な表現法で示されるいくつかの要素で構成されています。
 ユーザーガイドではこれらをひとまとめで「スキル」と呼んでいますが、このブログでは20段階の数値で表現されるものを『スキル』、それ以外を『パラメーター』と呼ぶことにします。そして、これらすべての選手を表現する要素をまとめて、『選手の能力』と呼ぶことにします。

 選手のスキルは、フィールドプレイヤーで14個、ゴールキーパーで11個が設定されており、それぞれで内容が異なります。ここではまずフィールドプレイヤーのスキルに焦点を当て、ポジション別に重視するべき能力を理解していきます。

スキルの構成

 一口に選手のスキルといっても、実際にはいくつかのグループに切り分けることが出来ます。スカウトの報告とユーザーガイドの記述を元に、スキルの構成を把握していきましょう。

フィジカル系スキル

 スカウトがPhyの能力で調査するスキル、Str(強さ)、Sta(スタミナ)、Pac(速さ)の3つです。「スキル」と呼ぶのは若干違和感がありますが、選手の身体的な能力を表します。*1
 選手画面の一覧表でもこの3つは仕切り線があり、明確に他のスキルと区別されていることがわかります。この3つの能力はGKも含めた全ポジションで共通であり、おそらく、どのポジションでもある程度の高さを要求されるものです。
 他のスキルと比べるとポジション別での依存度は低いですが、逆にどんな場面、ポジションでも参照されている可能性がありますので、軽視できるスキルではありません。

戦術系スキル

 スカウトがTacの能力で調査するスキル、Mar(マーク)、Tac(タックル)、Wor(運動量)、Pos(ポジショニング)の4つです。いずれも攻守の「場面」に多く関わることができるかを表す能力ですので、技術系のスキルよりもまずはこれらを重視すべきです。
 特にWorとPosは文字通り「ボールのある場所に顔を出す*2」ために必要となるスキルですので、自分のチームでキーになるポジションの選手にはこのスキルを要求するべきでしょう。能力の割にレート(試合内の評価)が低い選手は、このスキルが足を引っ張っていないかを疑う必要があります。
 攻撃的なポジションの選手ではMarやTacは残る2つよりもいくらか、重要度が低くなります。

技術系スキル

 スカウトがTecの能力で調査するスキル、Pas(パス)、Cro(クロス)、Tec(テクニック)、Fin(決定力)、Lon(ロングシュート)、Set(セットプレー)それと本来はPhyで調査されるHea(ヘディング)の7つです。
 この部分が、ポジション別に重要度の大きく変わるスキルとなります。
 ただし、戦術画面で設定している攻撃スタイルや、フォーメーション(他の選手との位置関係)によって、同じポジションであっても各スキルが必要になる「場面」の数が違ってきます。試合結果から多くの場面を拾い集め、自分のチームの布陣と戦術ではどのスキルが要求されているのかを分析することは、名監督になるために必要な作業でしょう。

ポジション別の重要スキル

 ユーザーガイドの表記をもとに、フィールドプレイヤーに要求される能力を一覧にしてみました。ユーザーガイドで「重要なスキル」とされているものは◎、「その他の重要なスキル」は〇とします。また、Setはポジンションに影響しにくいスキルであることと戦術に関連してくるのでここでは触れないことにします。

  CB SB&WB DMF CMF OMF WG FW
Str
Sta    
Pac
Mar      
Tac      
Wor    
Pos
Pas    
Cro      
Tec  
Hea  
Fin      
Lon      

 サイドバックとウィングバックを同じにしてしまっていたり、CMFは全スキルが重要だったりしてかなり大ざっぱな感じです。
 私の独断になりますが、これをもとにもう少しポジションと重要度を細分して、ポジション別の重要スキルをまとめたいと思います。もっとも重要なスキルを5、ほとんどに気にしなくて良いスキルを1とします。
 ポジションもサイドバックとウィングバックを切り分け、ウィングバックは攻撃にも参加する前提で考えます。また、フォワードも浮き球に対応してポストプレーを担当するTW(タワー)と万能型CF、スピードとテクニック重視のSTに分けて考えます。戦術でどんなフォーメーションとどの攻撃スタイルを組み合わせるかを考える際に役立てばと思います。

重要スキル-ゲーム好きな豚のしっぽ版

  CB SB WB DMF CMF OMF WG ST TW CF
Str 5 4 4 4 4 4 3 3 5 4
Sta 2 4 4 4 5 4 4 3 3 4
Pac 3 5 5 4 4 4 5 5 3 4
Mar 4 5 5 5 4 4 3 2 2 2
Tac 5 4 4 4 4 3 3 2 1 1
Wor 3 4 5 5 5 4 5 5 3 4
Pos 4 4 4 4 4 5 5 5 5 5
Pas 2 3 4 5 5 5 4 5 4 4
Cro 1 4 4 2 3 4 5 4 2 3
Tec 2 3 4 3 4 5 5 4 4 4
Hea 5 4 3 4 3 4 3 4 5 4
Fin 1 2 3 3 3 4 4 5 5 5
Lon 1 2 3 3 4 4 4 5 3 5

表の補足

 ポジショニングと運動量は重視しています。攻守の機会にきちんと参加できることが重要だと考えているからです。
 また、経験的にStrが高い選手はPacが低く、あるいはその逆になりがちのように感じます。このため、各ポジションでもどちらがより重要かを考えています。StaはWorに関連して重要ではないかと考えていますが、ユーザーガイドの説明だと調子の波の低調期がどの程度あるのか、のように読み取れます。これに基づくとこのスキルはどのポジションでも高いに越したことはないように思えます。
 Strが高い選手にはHea、Pacの高い選手にはFinやLonでの得点を期待しています。最前線でない場合はStrとTac、Hea、PacとWor、Marでの防御への貢献を期待します。
 

*1:スカウトはHea(ヘディング)もPhyで調査するようですがここでは除きます。

*2:ユーザーガイド>応用編>選手スキル>フィールドプレイヤー>Pos

スカウトの能力とスカウティング

 選手の成長力や性格的な部分はスカウトに調査させる以外にそれを知る方法がありません。優秀なスカウトは優秀な選手を獲得するために必要なものです。
 ここではスカウトの能力を把握して、選手の獲得に活かす下地を作りましょう。

スカウトの能力

 スカウトは7つの能力を持っています。能力は選手の能力と同じく1~20で表され、高いほどその能力に優れていることを表します。ただし、どの能力についても20のスカウトのコメントであっても必ず正確だとは言い切れないようです。正確を期すには高い能力(万全を期すなら当然20)のスカウトで複数回調査する必要があります。
 また、スカウトの能力は選手以上に偏りがちです。すべての能力に長けたスカウトを雇うことは不可能に近いですから、役割を分担させて1人の選手を複数のスカウトで調査することも必要な場面があります。

Dev(Development)

 選手の「開花の状況」を判断する能力です。まだ開花していない選手であれば開花の時期を、開花中であれば後どのくらい開花が続くのか、開花が終わっていれば「開花した」とコメントしてくれます。
 この能力が高いほど正確に開花の時期を言い当ててくれますが、開花の終了した即戦力の選手を探すのであれば、この能力にこだわる必要はありません。開花が終了した後から能力を成長させるのはレベルの高いトレーニング施設が必要ですし、残された成長も開花中に比べればわずかです。即戦力の補強には別の能力を重視した方が良いでしょう。

開花の時期と開花中のコメント
コメント 意味
開花が早いタイプ 16~17歳に開花し始める選手です。ユースでProを消費して獲得できる若い選手でないと見ることができません。
開花が普通のタイプ 18~21歳に開花し始める選手です。
開花が遅いタイプ 22歳以降に開花を始める選手です。
開花しつつある 開花の1年目です。
開花の真っ只中 開花の2年目です。
開花は終わりつつある 開花の3年目で、誕生日を迎えると開花が終わります。
開花した 既に開花を経験したほぼ完成された選手です。
「成長状況」について

 「成長状況」は開花とは別に与えられている、若い選手の成長*1の段階を表しています。通常は16~18歳の選手に割り当てられるボーナスですので表示される意味合いがあるのか疑問ですが、もしかすると遅咲きの選手の場合このボーナスが20歳前後まで持続する例があるのかもしれません。
 成長状況のコメントは「ほとんどこれから」「なかほど」「ほとんど終わった」「終わった」の4つとなっています。

Sen(Seniors)とYth(Youth)

 それぞれ、20歳以上の選手と19歳以下の選手の「現在の能力」と「ポテンシャル」を測るための能力です。
 ユーザーガイドによると「現在の能力(current ability)」となっていますが、これについては選手の個人画面で見ることが出来ますので、実際にどの部分を指しているのかはっきりしません。
 「ポテンシャル」はその選手が持つ「器」を満たしきった時に到達できるであろうRecを表します。Recと同じ星印で表示される他、1~20の段階評価も表示されます。この数値での評価は11でギリギリRec3に届くようです。特に開花前の選手の将来を知るために重要な能力といえるでしょう。

Phy(Physical),Tac(Tactical),Tec(Technical)

 それぞれ選手の身体能力、戦術能力、技術力のポテンシャルとピーク、その中にスペシャリスト・スキルがあればそれを判断します。
 この3つの能力の難しいところは、それぞれいくつかの能力をまとめて評価するため、選手の一つ一つの能力の具体的な限界値はわからないということと、選手のトレーニングで成長する能力はこの3つの分類をまたいでいる、ということです。
 スカウトがPhyのポテンシャルやピークは低いと判断していて、貴方がもうピークに達していると判断しても、トレーニングでその能力にTIが振り分けられることを防ぐことはかなり難しいでしょう。まだ余裕があるはずのクロスをあげようとしても、速さにTIが振り向けられてしまうことを防ぐのは実質的には不可能です。*2
 この3つの能力に対応する選手のスキルは以下の表のとおりです。*3

スカウトの能力 フィールドプレイヤーの能力 ゴールキーパーの能力
Phy 強さ(str)、スタミナ (Sta)、速さ (Pac)、ヘディング (Hea) 強さ(str)、スタミナ (Sta)、速さ (Pac)、ジャンプ (Jum)
Tac マーク (Mar)、タックル (Tac)、運動量 (Wor)、ポジショニング (Pos) 一対一 (One)、ハイボール処理 (Ari)、コミュニケーション (Com)
Tec 上記以外 上記以外

 これらについてはPotの高い選手では重要な検討材料になりますが、序盤ではあまり気にする必要はないでしょう。Pot3.5の選手はPot3.0の選手より(余程のことがない限りは)優秀です。

Psy(Psychology)

 精神面の能力の判断の正確さです。この能力で判別できる能力は各選手の通常の能力画面では表示されない能力がほとんどです。故に、この能力が高いスカウトは重要になってきます。この能力で判断できる選手の能力は以下になります。

リーダーシップ(Leadership)

 その選手のリーダーシップを表します。5段階評価となります。何故かこの能力はユーザーガイドの選手のスキルでは触れられておらず、戦術のキャプテンに関する項目でだけ触れられています。*4
 チームに数人、キャプテンの条件を満たせる選手がいれば十分なのかもしれません。
 

プロフェッショナリズム(Professionalism)

 その選手のプロ意識を表します。これも5段階です。
 この能力は影響範囲が広く、精神面の能力の中では重要になります。選手の試合でのパフォーマンスの高さや、戦術面の指示に従うかどうか、トレーニングでのTIの大きさ(まじめに練習するか)に影響します。また、リザーブチームを持っている場合、リザーブに降格させるときにその指示に従うかにも影響しています。
 その影響の大きさははっきりしませんが、同じRec、SIの選手であればこれが高い選手のほうが良いのは間違いないでしょう。

積極性(aggressiveness)

 その選手の積極性を表します。これも5段階評価です。
 積極性というとポジティブに聞こえますが、TrophyManagerでは逆で、実際には「怒りっぽさ」を表す能力です。
 この能力が高い選手ほど抑えが効かず、ラフなプレーに走りやすくなります。そのため、この能力が高い選手は1試合に2枚イエローカードを貰って退場するなどの危険性が高くなります。安定して成績を残せなくなるため、明らかにマイナスの能力です。
 ユーザーガイドの説明を見る限り、この能力が高くて良いことはありません。

スカウトの派遣とスカウティング結果

 スカウトは選手の個人画面の下部、「スカウトレポート」のタブから送り出すことができます。調査に派遣したいスカウトの横にある「送信」ボタンを押すと即座に調査結果が報告されます。
 結果は「将来の成長」が少しわかりづらくなっていますので、そこのみ説明しておきます。
f:id:talestail:20150629150535p:plain  項目名がありませんが上から順に

- Phy、フィジカル能力のポテンシャルとピーク
- Tac、戦術系能力のポテンシャルとピーク
- Tec、技術系能力のポテンシャルとピーク
- リーダーシップ
- プロ意識
- 積極性

となっています。
 この例でも、スカウトの能力で評価がばらついているのがわかります。


スカウトの使い分け

 スカウトの能力は当然ながら契約金や給料に影響します。高い能力を持っているスカウトはそれだけ給料も高くなっていきます。無計画に優秀なスカウトを雇用してしまうと、選手を雇う資金が苦しくなるかもしれません。役割分担を考えつつ、必要な能力を持ったスカウトを採用していきましょう。
 Ythの高いスカウトでは、Devも高いことが理想です。19歳以下の選手はまだ開花を迎えていない可能性が高いからです。
 Senが高いスカウトは、2つのタイプが考えられます。20を越えた選手の中でも24歳以上の完成した選手をスカウトする場合は、Psyの方が重要です。積極性とプロ意識は、その選手の完成度を大きく左右します。
 20歳以上でも22,23くらいまでの選手なら、Devの高いスカウトで開花の有無を確認しておくのは重要でしょう。その場合も、本当に優秀な選手を求めているのであれば、Phy、Tac、Tecがそれぞれある程度以上高いスカウトが必要になりますし、Psyの高いスカウトで精神面を観ておくことも必要になります。
 優先されるのはSen、Yth、Dev、Psyです。序盤はこれの調査を安心して任せられるスカウト数名の確保を目指しましょう。そして、移籍リストに載っている選手なら、締め切り当日ではなく数日前から数人づつスカウトを派遣して綿密な調査をしておくことが重要です。中2日あれば、同じスカウトを再び調査に向かわせることもできます。

Proで派遣できる専門チーム

 選手の能力にはスカウトでも調べきれない隠し能力がいくつかあります。負傷傾向(injury proneness)と適応力(adaptability)です。
それぞれ負傷の受けやすさと重症化の傾向、Fp(得意ポジション)以外に配置された時の対応力を表します。
 この2つについてはProを追加で消費して、専門家チームを派遣しないと知ることが出来ません。選手の所属チームから統計を調べることや、戦術や過去の試合を逐一調査することで推測もできなくはありませんが、これを知りたいときは専門家チームに任せるのが無難でしょう。

*1:ユーザーガイド>応用編>選手の成長>選手の一生 の図1の4の範囲

*2:本当にピークに達している能力にTIが割り振られた場合、他の能力にそのTIが振り替えられます。振替先はランダムです。ユーザーガイド>応用編>選手の成長>スキルのピーク

*3:表の各能力の対応はフォーラム>International>General>Self Help To Newbies & Others With Various Stuff....International>#9より

*4:ユーザーガイド>応用編>戦術>キャプテン