Faction Intro

Provides the system used to define the cutscenes and start-of-game dressing that fires for a given faction, in a given campaign, and under other conditions.

Faction Intro data is defined in the folder of each campaign, under a 'faction_intro' folder. Multiple faction intros can be defined, and will be merged together, allowing for mod compatibility.

The Faction Intro system allows an inherited 'preset' system. For example, if lots of factions share the same intro cutscene, that cutscene could be defined as a preset, with each faction intro inheriting from that preset. If one of those factions also had different potential leaders, requiring different advisor voice lines or a different camera position for each one, then that can be defined with variant tables.

Loaded in Campaign Loaded in Campaign
Loaded in Battle Loaded in Battle
Loaded in Frontend Loaded in Frontend
Back to top

How to Use

To create your own set of faction-intro data for a given campaign, create a faction_intro folder under that campaign's script folder. e.g. script/campaign/main_warhammer/faction_intro/

Scripts placed in this folder must define campaign-intro data, such as initial camera positions and cutscenes. These scripts can have any names, and multiple can be used. The Faction Intro system will load them all and merge them together.

The scripts must take the following structure:

Example:

An example of a faction intro Lua file.
local data = {
    -- Load order defines the order in which each of these tables is loaded, with later loads overwriting the elements of earlier ones.
    -- If this isn't defined, a script will always load last.
    -- If two scripts have an equal load-order, the order becomes alphabetical, based on script name.
    load_order = 0,
    -- A list of functions used to define how a faction's variant might be inferred. A typical example would be determining if we're playing as Karl Franz or Volkmar the Grimm.
    variant_key_getters = {
        -- ...
    },
    -- You can use presets to define bits of intro data which are used by lots of factions.
    intro_presets = {
        theatre_empire = {
            cam_gameplay_start = {
                x = 402,
                y = 497,
                d = 29,
                b = 0,
                h = 67,
            }
        },
    },
}

-- This table provides the actual intro data for each faction.
-- Best practise is to define these after you've defined the initial data table, so that you can reference the contents of the data table (including presets)
data.faction_intros = {
    -- The most simple way to define a faction intro, without using any fancy presets.
    wh2_main_lzd_hexoatl = faction_intro_data:new{
        cam_gameplay_start = {
            x = 402,
            y = 497,
            d = 29,
            b = 0,
            h = 67,
        },
        advice_to_play = {
            "war.camp.prelude.lzd.intro.005",
            "war.camp.prelude.lzd.intro.006",
            "war.camp.prelude.lzd.intro.007",
            "war.camp.prelude.lzd.intro.008",
        },
    },
    -- The Golden Order inherits the Empire Theatre preset's camera position, but defines its own advice lines.
    wh2_dlc13_emp_golden_order = faction_intro_data:new{
        preset = data.intro_presets.theatre_empire,
        advice_to_play = {
            "war.camp.prelude.emp.intro.005",
            "war.camp.prelude.emp.intro.006",
            "war.camp.prelude.emp.intro.007",
            "war.camp.prelude.emp.intro.008",
        },
    },
    wh_main_emp_empire = {
        preset = data.intro_presets.theatre_empire,
        -- You can also override data from the preset.
        cam_gameplay_start = {
            x = 352,
            y = 486,
            d = 17,
            b = 0,
            h = 14,
        },
        -- These are 'variants' for cases where a faction's intro data might differ in certain cases (if it has two possible leaders, for example).
        -- The key provided by the 'variant_key_getters' list decides which of these is used.
        wh_main_emp_karl_franz = faction_intro_data:new{
            advice_to_play = {
                "war.camp.prelude.emp.intro.001",
                "war.camp.prelude.emp.intro.002",
                "war.camp.prelude.emp.intro.003",
                "war.camp.prelude.emp.intro.004",
            },
        },
        wh_dlc04_emp_volkmar = faction_intro_data:new{
            advice_to_play = {
                "dlc04.camp.Volk.intro.001",
                "dlc04.camp.Volk.intro.002",
                "dlc04.camp.Volk.intro.003",
                "dlc04.camp.Volk.intro.004",
            },
        },
    },
    
},
return data
Back to top

Faction Intro Presets

A preset is a template of faction intro data which other tables can inherit from. If all factions in a given culture need to use the same introductory cutscene, for example, it can be defined on a preset. Then each faction's preset entry can be set to the string key of that preset.

Presets are defiend in a faction intro data file and, as with the faction intro definitions themselves, can be re-defined or overriden in multiple files, allowing for mod compatibility.

Back to top

Variants

Variants allow a particular faction to have multiple possible introduction data sets.

The trigger to use either one variant or another is user-defined: it might use the faction's starting-lord, as a way of handling cases where a faction can be lead by different leaders.

Or it might play different voice lines and cutscenes based on the game's difficulty.

Variant triggers must be defined using the faction_intro.variant_key_getters table.

Example - Variant Key Getter Example:

In this example, we construct a variant key using the quantity of players in the game, which is used to adjust the advisor voicelines.
local data = {
    -- Conditions by which a faction can provide a variant key are defined here. You may want to use the presence of a given effect bundle as a reason to have a particular intro to play, for example.
    -- Criteria are executed in priority of first to last: if an earlier getter is satisfied and provides a non-nil variant key, then later getters will not be consulted.
    variant_key_getters = {
        function(faction_interface)
            local variant_key = nil
            local player_count = #cm:get_human_factions()
            if player_count > 2 then
                variant_key = "players_3_plus"
            else
                variant_key = "players_" .. player_count
            end
            
            return variant_key
        end
    },
    intro_data = {
        main_warhammer = {
            wh2_main_def_naggarond = {
                cam_gameplay_start = {
                    x = 352,
                    y = 486,
                    d = 17,
                    b = 0,
                    h = 14,
                },
                players_1 = faction_intro_data:new{
                    advice_to_play = {
                        "war.camp.prelude.naggarond.singleplayer.001",
                        "war.camp.prelude.naggarond.singleplayer.002",
                    },
                },
                players_2 = faction_intro_data:new{
                    advice_to_play = {
                        "war.camp.prelude.naggarond.twoplayer.001",
                        "war.camp.prelude.naggarond.twoplayer.002",
                    },
                },
                players_3_plus = faction_intro_data:new{
                    advice_to_play = {
                        "war.camp.prelude.naggarond.multiplayer.001",
                        "war.camp.prelude.naggarond.multiplayer.002",
                    },
                },
            }
        }
    }
}
return data
Back to top

Faction Intro Cutscene Configurators

If you want to define complicated custom routines for the intro cutscene, you can specify the cutscene_configurator on the faction intro.

This is a function which takes a cutscene and makes adjustments to it before the cutscene is called.

Example - Cutscene Configurator Example:

Creating a custom flyby routine for Hexoatl.
data.faction_intros = {
    wh2_main_lzd_hexoatl = faction_intro_data:new{
        cam_gameplay_start = {
            x = 402,
            y = 497,
            d = 29,
            b = 0,
            h = 67,
        },
        cutscene_configurator = function(cutscene)
            -- Start at location, fade in, zoom in, play advice line, and restore UI.
            cutscene:set_relative_mode(true)
            cutscene:action_fade_scene(0, 1, 2)
            cutscene:action_override_ui_visibility(0, false, data.map_ui)
            cutscene:action_set_camera_position(0, {11, 614, 20.705231, 0.0, 65.031822})
            cutscene:action_scroll_camera_to_position(1, 8, true, {11, 614, 6.965149, 0.0, 8.008892})
            cutscene:action_show_advice(6, "wh3_flyby_dummy_KF")
            cutscene:action_override_ui_visibility(7, true, data.map_ui)
            cutscene:action_end_cutscene(0)
        end,
    },
},
Back to top

Faction Intro Cutscene Styles

If lots of your cutscenes for each faction are basically the same, but with slight differences, you can create a cutscene style.

A cutscene style is a function which returns a cutscene configurator (which itself returns a cutscene ...). It takes a 'self' parameter (self being the faction intro config table).

For example, maybe we want to use the config's cam_gameplay_start variable as a waypoint for our camera in all of our cutscenes.

Example - Cutscene Style Example:

Creating a zoom-in-and-speak cutscene style that uses positions and advice keys defined on the faction intro config.
data.cutscene_styles = {
    zoom_in_and_speak = function(self)
        local new_configurator = function(cutscene)
            cutscene:set_relative_mode(true)
            cutscene:action_fade_scene(0, 1, 2)
            -- Use variables from the config table to inform our cutscene.
            cutscene:action_set_camera_position(0, { self.cam_cutscene_start.x, self.cam_cutscene_start.y, self.cam_cutscene_start.d, self.cam_cutscene_start.b, self.cam_cutscene_start.h })
            cutscene:action_scroll_camera_to_position(1, 8, true, { self.cam_gameplay_start.x, self.cam_gameplay_start.y, self.cam_gameplay_start.d, self.cam_gameplay_start.b, self.cam_gameplay_start.h })
            cutscene:action_show_advice(6, self.advice_line)
            cutscene:action_end_cutscene(0)
        end

        return new_configurator
    end    
}

data.faction_intros = {
    wh2_main_def_har_ganeth = faction_intro_data:new{
        preset = data.intro_presets.standard,
        cam_cutscene_start = {
            x = 134,
            y = 641,
            d = 20.705231,
            b = 0.0,
            h = 65.031822,
        },
        cam_gameplay_start = {
            x = 134,
            y = 641,
            d = 6.965149,
            b = 0,
            h = 8.008892,
        },
        advice_line = "wh3_flyby_dummy_KF",
        cutscene_style = data.cutscene_styles.zoom_in_and_speak
    }
}

faction_intro:perform_intro(string campaign_folder_name, string faction_key)

Perform the start-of-campaign dressing for the specified faction within the specified campaign, playing advisor lines, cutscenes, etc.
All playable factions ought to have an intro definition table (even a blank one). If it's missing, an error will be thrown.

Parameters:

1

string

The folder from which the campaign's faction intro data should be loaded. This needs to match the folder name from which the campaign's specific scripts are loaded.

2

string

The faction for which we want to perform the intro, from the factions database table.

Returns:

  1. nil

defined in ../../Warhammer/working_data/script/campaign/faction_intro.lua, line 268

Last updated 12/08/2022 11:56:58