各種指導者MOD紹介


凝ったことをしている指導者MODをModder視点で紹介していこうと思います。(もちろん自作のは除く)

Workshop Page
作者:Entarogan氏

指導者特性:霊峰踏抱く冥府の鞴(クル・キガル・イルカルラ)
  • 戦争相手の文明の攻撃ユニットのHPを、自国が建造した聖地の数だけターン開始時に削る(最大10)。
    このダメージでユニットを倒すと、信仰力を30ポイント得る。
  • ユニットを倒すとゲームスピード/技術解禁数/プレイヤー数に応じて全都市が生産力ボーナスを得る。
    (正確には、現在生産中のものの残りターン数が直接減る)

文明特性:伝説の勇者
バニラのシュメールと同じです。

ユニークユニット1:戦闘車
バニラのシュメールと同じです。

ユニークユニット2:ガル
  • 近接 :36
  • 遠隔 :25
    • 近接ユニットですが、遠隔攻撃能力はあります。マケドニアの不死隊と同じ。
  • 射程 :1
  • 移動力:0(自国の国境内から移動開始した場合は2)
    • 自国の領土から1タイル先より外へ出てしまうと何も出来なくなります。(国境が広がるなどして再度範囲内になったとしても)
      移動、攻撃の際は注意が必要。
  • 解禁 :神秘主義
ユニーク区域:なし

ユニーク建造物:なし

ユニーク地形改善:ジッグラト
バニラのシュメールと同じです。

指導者特性が非常に特殊で、luaスクリプト制御になっています。

1つ目の特性は「Suzuran.lua」が担当。(・・・鈴蘭?)
function HolysiteCountDamage(playerId)
    local pPlayer = Players[playerId];
    local pPlayerConfig = PlayerConfigurations[playerId];
    
    if pPlayer:IsMajor() and pPlayer:IsAlive() then
        if pPlayerConfig:GetLeaderTypeName() == "LEADER_ENT_ERESHKIGAL" then //エレシュキガルのみ以下実施
            local HolyNum = 0;
            local pCities = pPlayer:GetCities();
            
            //建造した聖地の数をカウントする
            for i, pCity in pCities:Members() do
                local cityDistricts:table = pCity:GetDistricts();
                
                if cityDistricts:HasDistrict(GameInfo.Districts["DISTRICT_HOLY_SITE"].Index) then
                    HolyNum = HolyNum + 1;
                end 
            end
            
            //ダメージが10より増えないように制限
            if HolyNum > 10 then
               HolyNum=10;
            end
            
            if HolyNum > 0 then //聖地が1以上あれば以下実施
                for i = 0, GameDefines.MAX_PLAYERS-1, 1 do
                    if i ~= playerId and pPlayer:GetDiplomacy():IsAtWarWith(i) then //エレシュキガルと戦争中の文明なら以下実施(蛮族は対象外)
                        local Player = Players[i];
                        local PlayerConfig = PlayerConfigurations[i];
                        
                        if Player:IsAlive() and i ~= 63 then
                            local pUnits = Player:GetUnits(); //ユニット数取得
                            
                            for ii, pUnit in pUnits:Members() do
                                if (pUnit ~= nil) then
                                    local typeName:string = GameInfo.Units[pUnit:GetType()].FormationClass; //ユニットのFormationClassを取得
                                    
                                    if (typeName ~= "FORMATION_CLASS_CIVILIAN") then //市民系ユニット以外なら以下実施
                                        local remaining = (100 - pUnit:GetDamage()); //ダメージを与える前の残りHP取得
                                        
                                        if (remaining <= HolyNum) then                     //残りHP <= 聖地数(上限10)、すなわちHP0以下になるときは以下実施
                                            UnitManager.Kill(pUnit, false);                         //ユニットをkill
                                            Players[playerId]:GetReligion():ChangeFaithBalance(30); //信仰力30獲得
                                        else                                               //残りHP > 聖地数(上限10)、すなわち倒せなかった場合
                                            pUnit:ChangeDamage(HolyNum);                            //計算したダメージを与える
                                        end
                                    end
                                end
                            end
                        end
                    end
                end
            end
        end
    end
end
GameEvents.PlayerTurnStarted.Add(HolysiteCountDamage); //ターン開始時に↑を呼び出す

2つ目の特性は「Production.lua」が担当。
function Ere_Cities_Get_Population_By_Death(dplayerID:number, dunitID:number, aplayerID:number, aunitID:number)
    local Rate = 10;
    local xPlayerConfig = PlayerConfigurations[dplayerID];
    local CivilizationTypeName:string = xPlayerConfig:GetCivilizationTypeName();
    local PlayerCount = PlayerManager.GetAliveMajorsCount(); //プレイヤーカウント取得(滅んでいない文明のみ)
    print("First ter loaded\n");
        for i = 0, GameDefines.MAX_PLAYERS-1, 1 do
            local pPlayer = Players[i];
            local pPlayerConfig = PlayerConfigurations[i];
            if pPlayerConfig:GetLeaderTypeName() == "LEADER_ENT_ERESHKIGAL" then //エレシュキガルのみ以下を実施
                local pPlayerTechs = pPlayer:GetTechs() //テクノロジー一覧の取得
                
                //解禁してる分だけカウント
                local iNumTechs = 0
                for row in GameInfo.Technologies() do
                    if pPlayerTechs:HasTech(row.Index) then 
                        iNumTechs = iNumTechs + 1
                    end
                end
                print("Total player techs: "..iNumTechs);
                
                //ここでポイント計算している。(技術解禁数 * 10) * ゲームスピード / (100 * プレイヤー数)
                Award = (iNumTechs * Rate) * GameInfo.GameSpeeds[GameConfiguration.GetGameSpeedType()].CostMultiplier / (100 * PlayerCount);
                
                //ポイントを所有都市数で割り、その数だけ生産キューの残りターン数を減らす
                local pCities = pPlayer:GetCities();
                local pCity;
                for ii, pCity in pCities:Members() do
                    local pCityBuildQueue = pCity:GetBuildQueue();
                    pCityBuildQueue:AddProgress(Award / pCities:GetCount());
                end
            end
        end
end

Events.UnitKilledInCombat.Add(Ere_Cities_Get_Population_By_Death);  //戦闘でユニットを倒したときに↑を呼び出す

Workshop Page
作者:Vicevirtuoso氏

指導者特性:王の財宝(ゲート・オブ・バビロン)
  • 他文明のユニークユニットを生産できるが、経験値取得にペナルティがつく。
    (指導者に紐づいているものは対象外となり生産できない)
  • [RaF] 他文明のユニークユニットを生産すると時代スコア+1。

文明特性:伝説の勇者
バニラのシュメールと同じです。

ユニークユニット:戦闘車
バニラのシュメールと同じです。

ユニーク区域:なし

ユニーク建造物:なし

ユニーク地形改善:ジッグラト
バニラのシュメールと同じです。

指導者特性のゲート・オブ・バビロンが特殊です。
なんと、バニラの文明のみならずMODで追加された文明のユニークユニットまで勝手に追加されるという素敵なことになっております。
以下、参考画像です。鷲の戦士、戦闘車、ピタティ弓兵、オキチタウが存在してる上に、
あぶみで解禁されるユニットにアルトリアMODのユニークユニット:RoundTableががが・・・(初見時はバグったのかと思いました)


中身を見ると、このMODは大部分がSQL直叩きで作られています。
「Gilgamesh_Defines.sql」がこのMODの本体部分です。その中の以下で実現しています。
--Trigger for new UUs added after this file loads
CREATE TRIGGER VVGilgameshOnNewUU
AFTER INSERT ON Units //Unitsテーブルにデータが追加された後
WHEN NEW.TraitType LIKE ('TRAIT_CIVILIZATION_UNIT%') AND NOT EXISTS (SELECT * FROM LeaderTraits WHERE LeaderType = 'LEADER_VV_GILGAMESH' AND TraitType = NEW.TraitType) //TraitTypeがTRAIT_CIVILIZATION_UNITで始まり、まだギルガメシュに対して未割当のもの
BEGIN
    //条件に一致したものをLeaderTraitsテーブルに追加
    INSERT INTO LeaderTraits (LeaderType, TraitType)
    VALUES ('LEADER_VV_GILGAMESH', NEW.TraitType); //LeaderTraitsがギルガメシュ固定=ギルガメシュに強制割り当て

    //こっちはAIの好み。他文明のユニークユニットを好んで作るように設定しています。(財宝の出し惜しみはしない模様。さすがである)
    INSERT INTO AiFavoredItems (ListType, Item, Value)
    VALUES ('VV_Gilgamesh_UnitBuilds', NEW.UnitType, 1);
END;
「お前のものは俺のもの」をコードで実際にやっている、といえばいいでしょうかw
UnitsテーブルにTRAIT_CIVILIZATION_UNIT~で始まるものが追加されたら、そのユニットをギルガメシュの指導者特性に紐づけてしまう。
つまりバニラの書き方を真似て作ったMODのユニークユニットは対象に入るという寸法ですね。
また、マスターデータを直参照していますので、プレイしたゲーム内でオリジナルの文明が登場しなくても構いません。
MOD入れて有効にしてる数だけ作れるユニットが増える可能性があるという恐るべき性能。

RaFの場合は他文明のユニークユニットを作ると時代スコアが+1されますが、それは部分は以下で実現しているようです。
//指導者特性の文章の更新
UPDATE Traits
SET Description = 'LOC_TRAIT_LEADER_VV_GATE_OF_BABYLON_RAF_DESCRIPTION'
WHERE TraitType = 'TRAIT_LEADER_VV_GATE_OF_BABYLON' AND EXISTS (SELECT * FROM Types WHERE Type = 'MODIFIER_PLAYER_ADJUST_PLAYER_ERA_SCORE_PER_PRIDE_MOMENT');

//TraitとModifierの紐づけ
INSERT INTO TraitModifiers (TraitType, ModifierId)
    SELECT  'TRAIT_LEADER_VV_GATE_OF_BABYLON', 'TRAIT_LEADER_VV_GATE_OF_BABYLON_RAF_MOMENT_REDUCTION'
    FROM Types WHERE Type = 'MODIFIER_PLAYER_ADJUST_PLAYER_ERA_SCORE_PER_PRIDE_MOMENT';

//Modifierの追加
INSERT INTO Modifiers (ModifierId, ModifierType, SubjectRequirementSetId)
    SELECT 'TRAIT_LEADER_VV_GATE_OF_BABYLON_RAF_MOMENT_REDUCTION', 'MODIFIER_PLAYER_ADJUST_PLAYER_ERA_SCORE_PER_PRIDE_MOMENT', null
    FROM Types WHERE Type = 'MODIFIER_PLAYER_ADJUST_PLAYER_ERA_SCORE_PER_PRIDE_MOMENT';

//加算ポイントを1に設定
INSERT INTO ModifierArguments (ModifierId,  Name,  Value, Extra, Type)
    SELECT 'TRAIT_LEADER_VV_GATE_OF_BABYLON_RAF_MOMENT_REDUCTION', 'Amount', -1, null, 'ARGTYPE_IDENTITY'
    FROM Types WHERE Type = 'MODIFIER_PLAYER_ADJUST_PLAYER_ERA_SCORE_PER_PRIDE_MOMENT';
INSERT INTO ModifierArguments (ModifierId, Name, Value, Extra, Type)
    SELECT 'TRAIT_LEADER_VV_GATE_OF_BABYLON_RAF_MOMENT_REDUCTION', 'MinScore', 1, null, 'ARGTYPE_IDENTITY'
    FROM Types WHERE Type = 'MODIFIER_PLAYER_ADJUST_PLAYER_ERA_SCORE_PER_PRIDE_MOMENT';
副問い合わせのWHERE条件に指定しているModifierはRaFの場合のみ追加されるので、バニラでは条件不一致となるため追加は行われない。(エラーになるの防ぐため)