Code Monkey home page Code Monkey logo

vermintide-mod-framework's Introduction

Vermintide Mod Framework

Build Status

Welcome to the Vermintide Mod Framework (VMF) Repository!

The Vermintide Mod Framework is an open-source, community-run framework of modules that provides enhanced modding capabilities and support. The framework is designed to be both independent and lightweight; making no changes to gameplay on its own.

Mods created for the project may utilize:

  • Mod options
  • Shared function hooks
  • Chat commands
  • Keybinds
  • Mutator support (for now available only in Vermintide 1)
  • Network calls
  • QHD+ UI re-scaling
  • Rewritten, lightweight mod functions
  • An on-event call system

The Vermintide Mod Framework originally started in Warhammer End Times: Vermintide as an unofficial modding platform. In the time since, VMF has been rewritten and redesigned with contributions from many unique members of the community; culminating in this unified project made for the arrival of official mod support.

For more information, check out the framework's wiki pages.

Building the Framework

Prerequisites:

Building Steps:

  1. Navigate to your VMB directory. Let's assume it's unpacked into a folder named vermintide-mod-builder.
  2. Create a folder inside vermintide-mod-builder (we'll call it vermintide-mod-framework) and clone in the VMF repository's contents.
  3. Open a console/Command Prompt/PowerShell window inside your vermintide-mod-builder directory and use the following VMB command: vmb build vmf -f vermintide-mod-framework -g [1|2], where the number after -g indicates the target Vermintide game.

You can find more VMB mod-building information in the Vermintide Mod Builder documentation.

Steam Workshop Links

Beta builds:

Stable builds:

vermintide-mod-framework's People

Contributors

aussiemon avatar dreomite avatar e1camino avatar firesiku avatar fracticality avatar manuelblanc avatar prismism0 avatar sclu1034 avatar unshame avatar vermintide-analytics avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

vermintide-mod-framework's Issues

Re-publish VMF on Steam and remove iamlupo as maintainer

I am a fan of Vermintide and like a lot of players use VMF and mods depending on it

Currently Iamlupo is the publisher of VMF on Steam Workshops and a maintainer of this group. Through recent actions it has become obvious he does not have the best interests of the community at heart, even leading to a stickied post and dedicated subreddit: https://ft.reddit.com/r/Vermintide/comments/ap4miv/introducing_rvermintides_book_of_grudges/

Considering he enjoys grieving the community, he could remove VMF from Steam Workshop or publish harmful code which would result in breaking mods.

I request and urge you to consider removing his influence and publishing VMF through another Steam account.

Edit: I was under the wrong assumption he was the publisher of VMW, but fortunately I was wrong.

Function mod:dtf does not always respect table depth

This snippet

-- Outputs complete table of backend items to your Vermintide game folder
-- File is located at '<game folder>/launcher/dump/owned_items.json' by default
mod.export_backend_items_to_file = function(self, export_name)
	local backend = Managers.backend
	local backend_item_interface = backend:get_interface("items")
	local backend_items = backend_item_interface:get_all_backend_items()
	
	mod:dtf(backend_items, export_name or "owned_items", 10)
end

should explore tables to depth 10, but does not.

Example output

    "1234567890123456": {
      "backend_id": "1234567890123456 (string)",
      "power_level": "300 (number)",
      "ItemInstanceId": "1234567890123456 (string)",
      "ItemId": "wh_fencing_sword (string)",
      "PurchaseDate": "2018-06-05T03:35:59.392Z (string)",
      "CustomData": {
        "skin": "wh_fencing_sword_skin_01_runed_01 (string)",
        "properties": "{\"power_vs_chaos\":1,\"crit_chance\":1} (string)",
        "power_level": "300 (string)",
        "rarity": "unique (string)",
        "traits": "[\"melee_attack_speed_on_crit\"] (string)"
      },
      "properties": {
        "power_vs_chaos": "1 (number)",
        "crit_chance": "1 (number)"
      },
      "rarity": "unique (string)",
      "skin": "wh_fencing_sword_skin_01_runed_01 (string)",
      "data": "(table)(000000000489DDC0)",
      "traits": {
        "1": "melee_attack_speed_on_crit (string)"
      },
      "UnitPrice": "0 (number)",
      "CatalogVersion": "1 (string)",
      "key": "wh_fencing_sword (string)",
      "RemainingUses": "1 (number)"
    },

only has depth 2 before the 'data' table is exported as "(table)(000000000489DDC0)".

The following entry

"2345678901234567": {
      "backend_id": "2345678901234567 (string)",
      "ItemInstanceId": "2345678901234567 (string)",
      "PurchaseDate": "2018-06-04T03:26:22.574Z (string)",
      "CustomData": {
        "skin": "wh_1h_axe_skin_04 (string)"
      },
      "ItemId": "wh_1h_axe_skin (string)",
      "rarity": "plentiful (string)",
      "CatalogVersion": "1 (string)",
      "UnitPrice": "0 (number)",
      "data (0000000004877FC8)": {
        "matching_item_type": "wh_1h_axe (string)",
        "item_type": "weapon_skin (string)",
        "can_wield": {
          "2": "wh_bountyhunter (string)",
          "1": "wh_zealot (string)",
          "3": "wh_captain (string)"
        },
        "information_text": "information_weapon_skin (string)",
        "slot_type": "weapon_skin (string)",
        "key": "wh_1h_axe_skin (string)",
        "name": "wh_1h_axe_skin (string)",
        "display_name": "No_display_name_for_item_\"wh_1h_axe_skin\" (string)",
        "rarity": "plentiful (string)",
        "localized_name": "<No_display_name_for_item_\"wh_1h_axe_skin\"> (string)"
      },
      "skin": "wh_1h_axe_skin_04 (string)",
      "key": "wh_1h_axe_skin (string)",
      "RemainingUses": "1 (number)"
    },

has the correct depth, however.

Keep Interactable + "You have new mods installed" popup

Add keep interactable that brings up the mod menu.
Add a popup, like the ones for new chests/items/quests, when a new mod is found (no options set).

You have new mods installed

Check out Mod Options (<hot_key>) to see new options.

Highlight/bring new mods to top until the menu is closed/they are hovered over.

Forbid binding LMB for closing Mod Options

You can accidentally bind LMB for closing action which renders Mod Options unusable. Currently, the only way to fix this is to manually change this in the config file.

Let modders change chat commands gui definitions

Currently, all the properties related to how chat commands are drawn are defined as locals. There's no way to easily change them outside of VMF.

All style properties should be made public, so modders can easily adjust them.

Incorrect UI Scaling

Chat command suggestions are bigger than the chat box.

4k resolution with UI scaling set to 70

20190228233452_1

`Game object not found` crash

I keep having these random irreproducible crashes with following stack traces:
<>scripts/managers/network/game_network_manager.lua:563: Game object not found 1<</Lua Error>>
<>
[1] [C]: in function destroy_game_object
[2] scripts/managers/network/game_network_manager.lua:563: in function destroy_game_object
[3] scripts/managers/player/player_sync_data.lua:51: in function destroy
[4] scripts/managers/player/bulldozer_player.lua:419: in function destroy
[5] scripts/managers/player/player_manager.lua:307: in function func
[6] scripts/mods/vmf/modules/core/network.lua:353: in function hook_chain
[7] scripts/mods/vmf/modules/core/hooks.lua:180: in function remove_player
[8] scripts/managers/player/player_manager.lua:263: in function remove_all_players_from_peer
[9] scripts/managers/network/game_network_manager.lua:672: in function remove_peer
[10] scripts/network/peer_states.lua:453: in function on_enter
[11] scripts/network/peer_state_machine.lua:30: in function change_state
[12] scripts/network/network_server.lua:496: in function update
[13] scripts/game_state/state_ingame.lua:771: in function pre_update
[14] scripts/game_state/game_state_machine.lua:28: in function pre_update
[15] scripts/boot.lua:727: in function game_update
[16] scripts/boot.lua:526:in function <scripts/boot.lua:524>
<</Lua Stack>>

As lines [6] and [7] indicate, it might be related to VMF. Any ideas from mod maintainers? Do you require more log data?

Rehooking, preventing hooking after initialization

Add rehooking hooks of the same type to the same object. Order should be saved.
For this, expand hook_data

local hook_data = {
    active,
    hook,
    handler,
    hook_type,
    obj
}

Experimental:
Only allow mod:hook (and mod:origin?) while the mod is initializing.
For this, add some hidden variable to the mod that is set to true at the very end of new_mod call.
This should lock down the order of hooks 100%.

Move chat command execution to mod.update

vmf.run_command(_COMMANDS_LIST[_COMMAND_INDEX].name, unpack(args))

Chat commands are executed during ChatGui._update_input, which is run during GUI update. During GUI update some game functionality is disabled (e.g. raycasting).
Execution should be delayed and done in mod.update function instead.
Maybe also add some kind of mod:queue_function(func, callback) api.

Crash when viewing mod options in the 2.0.13_mod_branch beta

<<Script Error>>scripts/ui/ui_fonts.lua:69: attempt to index a nil value<</Script Error>>
<<Lua Stack>>  [1] @scripts/ui/ui_fonts.lua:69: in function UIGetFontHeight
  [2] @scripts/mods/vmf/modules/ui/options/vmf_options_view.lua:3105: in function callback_fit_tooltip_to_the_screen
  [3] @scripts/mods/vmf/modules/ui/options/vmf_options_view.lua:941: in function offset_function
  [4] @scripts/ui/ui_passes.lua:4016: in function draw
  [5] @scripts/ui/ui_renderer.lua:570: in function draw_element
  [6] @scripts/ui/ui_renderer.lua:402: in function hook_chain
  [7] @scripts/mods/vmf/modules/core/hooks.lua:180: in function draw_widget
  [8] @scripts/mods/vmf/modules/ui/options/vmf_options_view.lua:4196: in function update_settings_list
  [9] @scripts/mods/vmf/modules/ui/options/vmf_options_view.lua:4162: in function draw_widgets
  [10] @scripts/mods/vmf/modules/ui/options/vmf_options_view.lua:4136: in function update
  [11] @scripts/ui/views/ingame_ui.lua:559: in function hook_chain
  [12] @scripts/mods/vmf/modules/core/hooks.lua:180: in function update
  [13] @scripts/game_state/state_ingame_running.lua:906: in function update_ui
  [14] @scripts/game_state/state_ingame.lua:606:in function <scripts/game_state/state_ingame.lua:604>
  [15] =[C]: in function update_animations_with_callback
  [16] @foundation/scripts/util/script_world.lua:358: in function update
  [17] @foundation/scripts/managers/world/world_manager.lua:102: in function update
  [18] @scripts/boot.lua:788: in function game_update
  [19] @scripts/boot.lua:544:in function <scripts/boot.lua:542>
<</Lua Stack>>

Stack trace graciously provided by @danreeves. Thanks!

Add upvalue setting/getting to hook

API:
mod:get_upvalue(object "func_name", "local_name")
mod:set_upvalue(object, "func_name", {"local_name1", "local_name2"...})

Rough implementation outline:

  i = 1
  while true do
    local n, v = debug.getupvalue(func, i)
    if not n then break end
    if n == name then return v end
    i = i + 1
  end
    local dumped = string.dump(orig_function)
    local cloned = loadstring(dumped)
    local i = 1
    while true do
        local name = debug.getupvalue(orig_function, i)
        if not name then
            break
        end
        debug.upvaluejoin(cloned, i, orig_function, i)
        i = i + 1
    end
    return cloned

https://www.lua.org/pil/23.1.2.html

Proposed restrictions:

  1. One set of one or more upvalues can be changed per mod per function
  2. Disallow multiple mods to set the same upvalue
  3. Maybe disallow multiple mods to set different upvalues in the same function. Can be difficult to implement undoing upvalue changes without this restriction.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.