土豆兄弟(Brotato) mod--初始属性修改
土豆兄弟(Brotato) mod--初始属性修改
参考:土豆兄弟(Brotato) MOD制作讲解 开局基本属性修改 - 奎歪歪的博客
brotato 内置了mod_loader,最简单的cheat方式便是制作zip mod
- 如果修改文件,那么:
GDRETools/gdsdecomp: Godot reverse engineering tools
在反编译后直接修改调试
- 其它思路可参考:
(针对GDscript脚本加载、方法执行等等;GDScript::load_source_code、GDScriptFunctions::call、……)
游戏中脚本方式值修改-Godot Engine - Yofoo - 博客园
NotNite/GDWeave:Godot的Mod加载器和运行时脚本修补
mod 文件结构
GodotModding/godot-mod-loader:
//ikun-test.zip
mods-unpacked
└───ikun-test
│ manifest.json
│ mod_main.gd
│
└───extensions
└───singletons
player_run_data.gd
manifest.json
{
"name": "test",
"namespace": "ikun",
"version_number": "0.1.0",
"description": "Change init stat",
"website_url": "",
"dependencies": [],
"extra": {
"godot": {
"incompatibilities": [],
"authors": ["ikun"],
"compatible_mod_loader_version": ["6.2.0"],
"compatible_game_version": ["1.1.0.0"],
"config_defaults": {}
}
}
}
mod_main.gd
extends Node
const IKUN_TEST_DIR := "ikun-test"
const IKUN_TEST_LOG := "ikun-test:Main"
var mod_dir_path := ""
var extensions_dir_path := ""
var translations_dir_path := ""
# Before v6.1.0
# func _init(modLoader = ModLoader) -> void:
func _init() -> void:
mod_dir_path = ModLoaderMod.get_unpacked_dir().plus_file(IKUN_TEST_DIR)
# Add extensions
install_script_extensions()
# Add translations
#add_translations()
func install_script_extensions() -> void:
extensions_dir_path = mod_dir_path.plus_file("extensions")
ModLoaderMod.install_script_extension(extensions_dir_path.plus_file("singletons/player_run_data.gd"))
# extensions_dir_path = mod_dir_path.path_join("extensions") # Godot 4
#func add_translations() -> void:
# translations_dir_path = mod_dir_path.plus_file("translations")
# ModLoaderMod.add_translation(translations_dir_path.plus_file(...))
func _ready() -> void:
ModLoaderLog.info("Ready!", IKUN_TEST_LOG)
# var subscribed_items = Platform.get_subscribed_mods()
# for item_dir in subscribed_items:
# ModLoaderLog.info(item_dir,IKUN_TEST_LOG)
# ModLoaderLog.info("get_subscribed_mods success!", IKUN_TEST_LOG)
player_run_data.gd
ikun-test\extensions\singletons\player_run_data.gd
extends "res://singletons//player_run_data.gd"
# Called when the node enters the scene tree for the first time.
func _ready():
pass
static func init_stats(all_null_values: bool = false)->Dictionary:
# gold=12345678
var stats=.init_stats()
stats["stat_max_hp"]=10000
stats["stat_hp_regeneration"]=200
stats["stat_armor"]=1000 # 护甲值
stats["stat_luck"]=1000 #幸运
stats["stat_percent_damage"]=1000 # 伤害
stats["stat_ranged_damage"]=1000 # 远
stats["stat_melee_damage"]=1000 # 近
stats["stat_elemental_damage"]=1000 # 元素
stats["stat_attack_speed"]=1000 #攻速
return stats
static func init_effects()->Dictionary:
var all_effects = .init_effects()
all_effects["dodge_cap"]=95 # 闪避几率上限
return all_effects
对应的目标路径
res://singletons/player_run_data.gd
static func init_stats(all_null_values: bool = false)->Dictionary:
var stats: = {
"stat_max_hp": DEFAULT_MAX_HP if not all_null_values else 0,
"stat_armor": 0,
"stat_crit_chance": 0,
"stat_luck": 0,
"stat_attack_speed": 0,
"stat_elemental_damage": 0,
"stat_hp_regeneration": 0,
"stat_lifesteal": 0,
"stat_melee_damage": 0,
"stat_percent_damage": 0,
"stat_dodge": 0,
"stat_engineering": 0,
"stat_range": 0,
"stat_ranged_damage": 0,
"stat_speed": 0,
"stat_harvesting": 0,
"xp_gain": 0,
"number_of_enemies": 0,
"consumable_heal": 0,
"burning_cooldown_reduction": 0,
"burning_cooldown_increase": 0,
"burning_spread": 0,
"piercing": 0,
"piercing_damage": 0,
"pickup_range": 0,
"chance_double_gold": 0,
"bounce": 0,
"bounce_damage": 0,
"heal_when_pickup_gold": 0,
"item_box_gold": 0,
"knockback": 0,
"hp_cap": Utils.LARGE_NUMBER if not all_null_values else 0,
"speed_cap": Utils.LARGE_NUMBER if not all_null_values else 0,
"lose_hp_per_second": 0,
"map_size": 0,
"dodge_cap": 60,
"crit_chance_cap": Utils.LARGE_NUMBER if not all_null_values else 0,
"gold_drops": 0,
"enemy_health": 0,
"enemy_damage": 0,
"enemy_speed": 0,
"boss_strength": 0,
"explosion_size": 0,
"explosion_damage": 0,
"damage_against_bosses": 0,
"weapon_slot": 6 if not all_null_values else 0,
"items_price": 0,
"reroll_price": 0,
"harvesting_growth": 5 if not all_null_values else 0,
"hit_protection": 0,
"weapons_price": 0,
"structure_attack_speed": 0,
"structure_percent_damage": 0,
"structure_range": 0,
}
for stat in ItemService.stats:
if stat.is_dlc_stat:
stats[stat.stat_name] = 0
return stats
static func init_effects()->Dictionary:
var all_stats = init_stats()
var all_effects = {
"gain_stat_max_hp": 0,
"gain_stat_armor": 0,
"gain_stat_crit_chance": 0,
"gain_stat_luck": 0,
"gain_stat_attack_speed": 0,
"gain_stat_elemental_damage": 0,
"gain_stat_hp_regeneration": 0,
"gain_stat_lifesteal": 0,
"gain_stat_melee_damage": 0,
"gain_stat_percent_damage": 0,
"gain_stat_dodge": 0,
"gain_stat_engineering": 0,
"gain_stat_range": 0,
"gain_stat_ranged_damage": 0,
"gain_stat_speed": 0,
"gain_stat_harvesting": 0,
"gain_stat_curse": 0,
"no_melee_weapons": 0,
"no_ranged_weapons": 0,
"no_duplicate_weapons": 0,
"hp_start_wave": 100,
"hp_start_next_wave": 100,
"pacifist": 0,
"cryptid": 0,
"gain_pct_gold_start_wave": 0,
"torture": 0,
"recycling_gains": 0,
"one_shot_trees": 0,
"max_ranged_weapons": 999,
"max_melee_weapons": 999,
"group_structures": 0,
"can_attack_while_moving": 1,
"trees": 0,
"trees_start_wave": 0,
"min_weapon_tier": 0,
"max_weapon_tier": 99,
"hp_shop": 0,
"free_rerolls": 0,
"instant_gold_attracting": 0,
"double_boss": 0,
"gain_explosion_damage": 0,
"gain_piercing_damage": 0,
"gain_bounce_damage": 0,
"gain_damage_against_bosses": 0,
"neutral_gold_drops": 0,
"enemy_gold_drops": 0,
"wandering_bots": 0,
"can_burn_enemies": 1,
"danger_enemy_health": 0,
"danger_enemy_damage": 0,
"dmg_when_pickup_gold": [],
"dmg_when_death": [],
"dmg_when_heal": [],
"dmg_on_dodge": [],
"heal_on_dodge": [],
"remove_speed": [],
"starting_item": [],
"cursed_starting_item": [],
"starting_weapon": [],
"cursed_starting_weapon": [],
"projectiles_on_death": [],
"burn_chance": BurningData.new(),
"burning_enemy_hp_percent_damage": [],
"weapon_class_bonus": [],
"weapon_bonus": [],
"unique_weapon_effects": [],
"additional_weapon_effects": [],
"tier_iv_weapon_effects": [],
"tier_i_weapon_effects": [],
"gold_on_crit_kill": [],
"heal_on_crit_kill": 0,
"temp_stats_while_not_moving": [],
"temp_stats_while_moving": [],
"temp_stats_on_hit": [],
"stats_end_of_wave": [],
"stat_links": [],
"structures": [],
"explode_on_hit": [],
"explode_when_below_hp": [],
"convert_stats_end_of_wave": [],
"explode_on_death": [],
"alien_eyes": [],
"upgrade_random_weapon": [],
"minimum_weapons_in_shop": 0,
"destroy_weapons": 0,
"extra_enemies_next_wave": [],
"extra_loot_aliens_next_wave": 0,
"extra_loot_aliens": 0,
"stats_next_wave": [],
"consumable_stats_while_max": [],
"temp_consumable_stats_while_max": [],
"explode_on_consumable": [],
"explode_on_consumable_burning": [],
"structures_cooldown_reduction": [],
"convert_stats_half_wave": [],
"stats_on_level_up": [],
"temp_stats_on_dodge": [],
"no_heal": 0,
"tree_turrets": 0,
"stats_below_half_health": [],
"guaranteed_shop_items": [],
"special_enemies_last_wave": 0,
"specific_items_price": [],
"accuracy": 0,
"projectiles": 0,
"upgraded_baits": 0,
"minimum_weapon_cooldowns": [],
"maximum_weapon_cooldowns": [],
"burning_enemy_speed": 0,
"weapon_scaling_stats": [],
"slow_on_hit": [],
"enemy_percent_damage_taken": [],
"gain_stat_for_equipped_item_with_stat": [],
"weapon_slot_upgrades": 0,
"next_level_xp_needed": 0,
"all_weapons_count_for_sets": 0,
"structures_can_crit": 0,
"landmines_on_death_chance": [],
"temp_stats_on_structure_crit": [],
"gain_stat_for_every_step_after_equip": [],
"decaying_stats_on_consumable": [],
"decaying_stats_on_hit": [],
"temp_stats_per_interval": [],
"pierce_on_crit": 0,
"bounce_on_crit": 0,
"consumable_heal_over_time": 0,
"lock_current_weapons": 0,
"knockback_aura": 0,
"level_upgrades_modifications": 0,
"enemy_fruit_drops": 0,
"stats_on_fruit": [],
"duplicate_item": [],
"poisoned_fruit": 0,
"gain_stat_when_attack_killed_enemies": [],
"extra_item_in_crate": [],
"bonus_damage_against_targets_above_hp": [],
"bonus_damage_against_targets_below_hp": [],
"heal_on_kill": 0,
"modify_every_x_projectile": [],
"gold_on_cursed_enemy_kill": 0,
"giant_crit_damage": [],
"loot_alien_speed": 0,
"bonus_non_elemental_damage_against_burning_targets": 0,
"bonus_weapon_class_damage_against_cursed_enemies": [],
"item_steals": 0,
"item_steals_spawns_enemy": [],
"item_steals_spawns_random_elite": 0,
"disable_item_locking": 0,
"explode_on_overkill": [],
"crate_chance": 0,
"loot_alien_chance": 0,
"gain_stat_for_duplicate_items": [],
"max_turret_count": Utils.LARGE_NUMBER,
"convert_bonus_gold": [],
"remove_shop_items": [],
"charm_on_hit": [],
"materials_per_living_enemy": 0,
"negative_knockback": 0,
"weapon_type_bonus": [],
"scale_materials_with_distance": [],
"curse_locked_items": 0,
"increase_tier_on_reroll": [],
"reload_when_pickup_gold": 0,
"increase_material_value": 0,
"gain_stats_on_reroll": [],
"stronger_elites_on_kill": 0,
"stronger_loot_aliens_on_kill": 0,
"hp_regen_bonus": []
}
all_effects.merge(all_stats)
return all_effects
豆包翻译:
### `init_stats`函数中`stats`字典的键翻译
- `"stat_max_hp"`:最大生命值
- `"stat_armor"`:护甲
- `"stat_crit_chance"`:暴击几率
- `"stat_luck"`:幸运值
- `"stat_attack_speed"`:攻击速度
- `"stat_elemental_damage"`:元素伤害
- `"stat_hp_regeneration"`:生命值回复
- `"stat_lifesteal"`:生命偷取
- `"stat_melee_damage"`:近战伤害
- `"stat_percent_damage"`:百分比伤害
- `"stat_dodge"`:闪避
- `"stat_engineering"`:工程学(可能和建造、器械相关属性)
- `"stat_range"`:攻击/作用范围
- `"stat_ranged_damage"`:远程伤害
- `"stat_speed"`:移动速度
- `"stat_harvesting"`:采集(收获资源相关属性)
- `"xp_gain"`:经验获取
- `"number_of_enemies"`:敌人数量
- `"consumable_heal"`:消耗品治疗量
- `"burning_cooldown_reduction"`:燃烧效果冷却缩减
- `"burning_cooldown_increase"`:燃烧效果冷却增加
- `"burning_spread"`:燃烧效果扩散
- `"piercing"`:穿刺(可能是攻击有穿刺效果相关属性)
- `"piercing_damage"`:穿刺伤害
- `"pickup_range"`:拾取范围
- `"chance_double_gold"`:双倍金币几率
- `"bounce"`:弹射(攻击有弹射效果相关属性)
- `"bounce_damage"`:弹射伤害
- `"heal_when_pickup_gold"`:拾取金币时治疗
- `"item_box_gold"`:物品箱金币
- `"knockback"`:击退
- `"hp_cap"`:生命值上限
- `"speed_cap"`:速度上限
- `"lose_hp_per_second"`:每秒损失生命值
- `"map_size"`:地图大小
- `"dodge_cap"`:闪避上限
- `"crit_chance_cap"`:暴击几率上限
- `"gold_drops"`:金币掉落
- `"enemy_health"`:敌人生命值
- `"enemy_damage"`:敌人伤害
- `"enemy_speed"`:敌人速度
- `"boss_strength"`:BOSS强度
- `"explosion_size"`:爆炸范围
- `"explosion_damage"`:爆炸伤害
- `"damage_against_bosses"`:对BOSS造成的伤害
- `"weapon_slot"`:武器槽位
- `"items_price"`:物品价格
- `"reroll_price"`:重roll价格
- `"harvesting_growth"`:采集成长
- `"hit_protection"`:受击保护
- `"weapons_price"`:武器价格
- `"structure_attack_speed"`:建筑攻击速度
- `"structure_percent_damage"`:建筑百分比伤害
- `"structure_range"`:建筑作用范围
### `init_effects`函数中`all_effects`字典的键翻译
- `"gain_stat_max_hp"`:增加最大生命值
- `"gain_stat_armor"`:增加护甲
- `"gain_stat_crit_chance"`:增加暴击几率
- `"gain_stat_luck"`:增加幸运值
- `"gain_stat_attack_speed"`:增加攻击速度
- `"gain_stat_elemental_damage"`:增加元素伤害
- `"gain_stat_hp_regeneration"`:增加生命值回复
- `"gain_stat_lifesteal"`:增加生命偷取
- `"gain_stat_melee_damage"`:增加近战伤害
- `"gain_stat_percent_damage"`:增加百分比伤害
- `"gain_stat_dodge"`:增加闪避
- `"gain_stat_engineering"`:增加工程学属性
- `"gain_stat_range"`:增加攻击/作用范围
- `"gain_stat_ranged_damage"`:增加远程伤害
- `"gain_stat_speed"`:增加移动速度
- `"gain_stat_harvesting"`:增加采集属性
- `"gain_stat_curse"`:增加诅咒属性
- `"no_melee_weapons"`:禁用近战武器
- `"no_ranged_weapons"`:禁用远程武器
- `"no_duplicate_weapons"`:禁止重复武器
- `"hp_start_wave"`:本波次起始生命值
- `"hp_start_next_wave"`:下一波次起始生命值
- `"pacifist"`:和平主义者(可能和禁止攻击相关)
- `"cryptid"`:神秘生物(不太明确游戏内效果,推测和特殊角色/状态有关)
- `"gain_pct_gold_start_wave"`:本波次起始获得的金币百分比
- `"torture"`:折磨(游戏效果不明,可能是给敌人的负面状态 )
- `"recycling_gains"`:回收收益
- `"one_shot_trees"`:一击砍树(可能是砍树相关特效)
- `"max_ranged_weapons"`:最大远程武器数量
- `"max_melee_weapons"`:最大近战武器数量
- `"group_structures"`:建筑分组(推测是和建筑布局、联动相关效果)
- `"can_attack_while_moving"`:移动时可攻击
- `"trees"`:树木(可能和树木相关属性、数量等有关)
- `"trees_start_wave"`:本波次起始的树木相关属性
- `"min_weapon_tier"`:最小武器等级
- `"max_weapon_tier"`:最大武器等级
- `"hp_shop"`:商店生命值相关(也许是能在商店购买生命值)
- `"free_rerolls"`:免费重roll次数
- `"instant_gold_attracting"`:即时吸引金币
- `"double_boss"`:双倍BOSS(可能本关出现两个BOSS )
- `"gain_explosion_damage"`:增加爆炸伤害
- `"gain_piercing_damage"`:增加穿刺伤害
- `"gain_bounce_damage"`:增加弹射伤害
- `"gain_damage_against_bosses"`:增加对BOSS的伤害
- `"neutral_gold_drops"`:中立单位金币掉落
- `"enemy_gold_drops"`:敌人金币掉落
- `"wandering_bots"`:游荡机器人(游戏中的一种单位,和它相关效果)
- `"can_burn_enemies"`:能点燃敌人
- `"danger_enemy_health"`:危险敌人的生命值
- `"danger_enemy_damage"`:危险敌人的伤害
- `"dmg_when_pickup_gold"`:拾取金币时造成伤害
- `"dmg_when_death"`:死亡时造成伤害
- `"dmg_when_heal"`:治疗时造成伤害
- `"dmg_on_dodge"`:闪避时造成伤害
- `"heal_on_dodge"`:闪避时治疗
- `"remove_speed"`:移除速度(可能是减速敌人相关属性)
- `"starting_item"`:起始物品
- `"cursed_starting_item"`:带诅咒的起始物品
- `"starting_weapon"`:起始武器
- `"cursed_starting_weapon"`:带诅咒的起始武器
- `"projectiles_on_death"`:死亡时发射投射物
- `"burn_chance"`:燃烧几率
- `"burning_enemy_hp_percent_damage"`:对敌人造成基于其生命值百分比的燃烧伤害
- `"weapon_class_bonus"`:武器类别加成
- `"weapon_bonus"`:武器加成
- `"unique_weapon_effects"`:独特武器效果
- `"additional_weapon_effects"`:额外武器效果
- `"tier_iv_weapon_effects"`:四级武器效果
- `"tier_i_weapon_effects"`:一级武器效果
- `"gold_on_crit_kill"`:暴击击杀获得金币
- `"heal_on_crit_kill"`:暴击击杀时治疗
- `"temp_stats_while_not_moving"`:静止时的临时属性
- `"temp_stats_while_moving"`:移动时的临时属性
- `"temp_stats_on_hit"`:受击时的临时属性
- `"stats_end_of_wave"`:波次结束时的属性
- `"stat_links"`:属性链接
- `"structures"`:建筑(和建筑相关的一系列效果、属性集合)
- `"explode_on_hit"`:受击时爆炸
- `"explode_when_below_hp"`:生命值低于一定值时爆炸
- `"convert_stats_end_of_wave"`:波次结束时转换属性
- `"explode_on_death"`:死亡时爆炸
- `"alien_eyes"`:外星之眼(游戏内特殊效果、道具相关)
- `"upgrade_random_weapon"`:随机升级武器
- `"minimum_weapons_in_shop"`:商店中最小武器数量
- `"destroy_weapons"`:销毁武器
- `"extra_enemies_next_wave"`:下一波次额外敌人
- `"extra_loot_aliens_next_wave"`:下一波次额外外星掠夺者
- `"extra_loot_aliens"`:外星掠夺者相关额外奖励
- `"stats_next_wave"`:下一波次属性
- `"consumable_stats_while_max"`:满状态时消耗品属性
- `"temp_consumable_stats_while_max"`:满状态时临时消耗品属性
- `"explode_on_consumable"`:使用消耗品时爆炸
- `"explode_on_consumable_burning"`:使用消耗品时燃烧爆炸
- `"structures_cooldown_reduction"`:建筑冷却缩减
- `"convert_stats_half_wave"`:半波次转换属性
- `"stats_on_level_up"`:升级时属性
- `"temp_stats_on_dodge"`:闪避时临时属性
- `"no_heal"`:禁止治疗
- `"tree_turrets"`:树木炮塔(游戏中的特殊建筑)
- `"stats_below_half_health"`:半血以下属性
- `"guaranteed_shop_items"`:商店必出物品
- `"special_enemies_last_wave"`:最后一波特殊敌人
- `"specific_items_price"`:特定物品价格
- `"accuracy"`:精准度
- `"projectiles"`:投射物(相关属性,数量、效果等)
- `"upgraded_baits"`:升级后的诱饵
- `"minimum_weapon_cooldowns"`:最小武器冷却时间
- `"maximum_weapon_cooldowns"`:最大武器冷却时间
- `"burning_enemy_speed"`:燃烧敌人的速度
- `"weapon_scaling_stats"`:武器成长属性
- `"slow_on_hit"`:受击减速
- `"enemy_percent_damage_taken"`:敌人承受的百分比伤害
- `"gain_stat_for_equipped_item_with_stat"`:因装备特定属性物品而获得属性
- `"weapon_slot_upgrades"`:武器槽位升级
- `"next_level_xp_needed"`:下一级所需经验
- `"all_weapons_count_for_sets"`:套装所需武器总数
- `"structures_can_crit"`:建筑能暴击
- `"landmines_on_death_chance"`:死亡时生成地雷几率
- `"temp_stats_on_structure_crit"`:建筑暴击时临时属性
- `"gain_stat_for_every_step_after_equip"`:装备后每步获得属性
- `"decaying_stats_on_consumable"`:消耗品消耗时衰减属性
- `"decaying_stats_on_hit"`:受击时衰减属性
- `"temp_stats_per_interval"`:每个间隔的临时属性
- `"pierce_on_crit"`:暴击时穿刺
- `"bounce_on_crit"`:暴击时弹射
- `"consumable_heal_over_time"`:消耗品持续治疗
- `"lock_current_weapons"`:锁定当前武器
- `"knockback_aura"`:击退光环
- `"level_upgrades_modifications"`:升级修正
- `"enemy_fruit_drops"`:敌人水果掉落
- `"stats_on_fruit"`:水果相关属性
- `"duplicate_item"`:重复物品
- `"poisoned_fruit"`:有毒水果
- `"gain_stat_when_attack_killed_enemies"`:攻击击杀敌人时获得属性
- `"extra_item_in_crate"`:箱子中的额外物品
- `"bonus_damage_against_targets_above_hp"`:对高血量目标的额外伤害
- `"bonus_damage_against_targets_below_hp"`:对低血量目标的额外伤害
- `"heal_on_kill"`:击杀时治疗
- `"modify_every_x_projectile"`:每X个投射物修改(效果不明)
- `"gold_on_cursed_enemy_kill"`:击杀带诅咒敌人获得金币
- `"giant_crit_damage"`:巨型暴击伤害
- `"loot_alien_speed"`:外星掠夺者速度
- `"bonus_non_elemental_damage_against_burning_targets"`:对燃烧目标的额外非元素伤害
- `"bonus_weapon_class_damage_against_cursed_enemies"`:对带诅咒敌人的武器类别额外伤害
- `"item_steals"`:物品窃取
- `"item_steals_spawns_enemy"`:物品窃取时生成敌人
- `"item_steals_spawns_random_elite"`:物品窃取时随机生成精英敌人
- `"disable_item_locking"`:禁用物品锁定
- `"explode_on_overkill"`:过量击杀时爆炸
- `"crate_chance"`:箱子出现几率
- `"loot_alien_chance"`:外星掠夺者出现几率
- `"gain_stat_for_duplicate_items"`:因重复物品获得属性
- `"max_turret_count"`:最大炮塔数量
- `"convert_bonus_gold"`:转换额外金币
- `"remove_shop_items"`:移除商店物品
- `"charm_on_hit"`:受击魅惑
- `"materials_per_living_enemy"`:每个存活敌人的材料
- `"negative_knockback"`:反向击退
- `"weapon_type_bonus"`:武器类型加成
- `"scale_materials_with_distance"`:根据距离缩放材料
- `"curse_locked_items"`:诅咒锁定物品
- `"increase_tier_on_reroll"`:重roll时提升等级
- `"reload_when_pickup_gold"`:拾取金币时重新装填
- `"increase_material_value"`:增加材料价值
- `"gain_stats_on_reroll"`:重roll时获得属性
- `"stronger_elites_on_kill"`:击杀时精英变强
- `"stronger_loot_aliens_on_kill"`:击杀时外星掠夺者变强
- `"hp_regen_bonus"`:生命值回复加成
brotato加载mod流程
res://addons/mod_loader/mod_loader.gd
_init
func _init()->void :
_check_autoload_positions()
if ModLoaderStore.REQUIRE_CMD_LINE and not _ModLoaderCLI.is_running_with_command_line_arg("--enable-mods"):
return
ModLoaderLog._rotate_log_file()
ModLoaderLog.debug_json_print("Autoload order", _ModLoaderGodot.get_autoload_array(), LOG_NAME)
ModLoaderLog.info("game_install_directory: %s" % _ModLoaderPath.get_local_folder_dir(), LOG_NAME)
if not ModLoaderStore.ml_options.enable_mods:
ModLoaderLog.info("Mods are currently disabled", LOG_NAME)
return
var _success_user_profile_load: = ModLoaderUserProfile._load()
_load_mods()
ModLoaderStore.is_initializing = false
_load_mods
func _load_mods()->void :
var zip_data: = _load_mod_zips()
if zip_data.empty():
ModLoaderLog.info("No zipped mods found", LOG_NAME)
else:
ModLoaderLog.success("DONE: Loaded %s mod files into the virtual filesystem" % zip_data.size(), LOG_NAME)
for mod_id in zip_data.keys():
var zip_path: String = zip_data[mod_id]
_init_mod_data(mod_id, zip_path)
_load_mod_zips
根据ml_options配置,默认将通过load_steam_workshop_zips 进行加载mod

res://addons/mod_loader/options/options.tres
[gd_resource type="Resource" load_steps=6 format=2]
[ext_resource path="res://addons/mod_loader/options/profiles/steam.tres" type="Resource" id=1]
[ext_resource path="res://addons/mod_loader/resources/options_current.gd" type="Script" id=2]
[ext_resource path="res://addons/mod_loader/options/profiles/editor.tres" type="Resource" id=3]
[ext_resource path="res://addons/mod_loader/options/profiles/epic.tres" type="Resource" id=4]
[ext_resource path="res://addons/mod_loader/options/profiles/default.tres" type="Resource" id=5]
[resource]
script = ExtResource( 2 )
current_options = ExtResource( 5 )
feature_override_options = {
"editor": ExtResource( 3 ),
"epic": ExtResource( 4 ),
"steam": ExtResource( 1 )
}
res://addons/mod_loader/options/profiles/current.tres
[gd_resource type="Resource" load_steps=2 format=2]
[ext_resource path="res://addons/mod_loader/resources/options_profile.gd" type="Script" id=1]
[resource]
script = ExtResource( 1 )
enable_mods = true
locked_mods = [ ]
log_level = 3
disabled_mods = [ ]
allow_modloader_autoloads_anywhere = true
steam_workshop_enabled = true
override_path_to_mods = ""
override_path_to_configs = ""
override_path_to_workshop = ""
ignore_deprecated_errors = false
ignored_mod_names_in_log = [ ]
func _load_mod_zips()->Dictionary:
var zip_data: = {}
if not ModLoaderStore.ml_options.steam_workshop_enabled:
var mods_folder_path: = _ModLoaderPath.get_path_to_mods()
var loaded_zip_data: = _ModLoaderFile.load_zips_in_folder(mods_folder_path)
zip_data.merge(loaded_zip_data)
else:
var loaded_workshop_zip_data: = _ModLoaderSteam.load_steam_workshop_zips()
zip_data.merge(loaded_workshop_zip_data)
return zip_data
load_steam_workshop_zips
res://addons/mod_loader/internal/third_party/steam.gd
static func load_steam_workshop_zips()->Dictionary:
var zip_data: = {}
var workshop_folder_path: = _get_path_to_workshop()
ModLoaderLog.info("Checking workshop items, with path: \"%s\"" % workshop_folder_path, LOG_NAME)
var workshop_dir: = Directory.new()
var workshop_dir_open_error: = workshop_dir.open(workshop_folder_path)
if not workshop_dir_open_error == OK:
ModLoaderLog.error("Can't open workshop folder %s (Error: %s)" % [workshop_folder_path, workshop_dir_open_error], LOG_NAME)
return {}
var workshop_dir_listdir_error: = workshop_dir.list_dir_begin(true)
if not workshop_dir_listdir_error == OK:
ModLoaderLog.error("Can't read workshop folder %s (Error: %s)" % [workshop_folder_path, workshop_dir_listdir_error], LOG_NAME)
return {}
var subscribed_items: = Platform.get_subscribed_mods()
while true:
var item_dir: = workshop_dir.get_next()
var item_path: = workshop_dir.get_current_dir() + "/" + item_dir
ModLoaderLog.info("Checking workshop item path: \"%s\"" % item_path, LOG_NAME)
if item_dir == "":
break
if not workshop_dir.current_is_dir():
continue
if int(item_dir) in subscribed_items:
zip_data.merge(_ModLoaderFile.load_zips_in_folder(ProjectSettings.globalize_path(item_path)))
workshop_dir.list_dir_end()
return zip_data
Platform.get_subscribed_mods
res://singletons/platforms/steam.gd
获得当前游戏中,当前用户所订阅的所有物品的清单。
func get_subscribed_mods()->Array:
return steam.getSubscribedItems()
如何加载自定义mod
因此在不修改游戏的情况下,需要通过‘创意工坊’订阅mod后,才能加载;
订阅后便可以在 Steam安装目录steamapps\workshop\content\1942280\ (对应brotato)下
会出现一个名字全为数字的文件夹,因此可以在订阅一个mod后将自己的mod zip进行替换
log 会出现在%AppData%\Brotato\logs 目录下
效果
修改后游戏变得索然无味~



浙公网安备 33010602011771号