土豆兄弟(Brotato) mod--初始属性修改

土豆兄弟(Brotato) mod--初始属性修改

参考:土豆兄弟(Brotato) MOD制作讲解 开局基本属性修改 - 奎歪歪的博客

brotato 内置了mod_loader,最简单的cheat方式便是制作zip mod

  • 如果修改文件,那么:

GDRETools/gdsdecomp: Godot reverse engineering tools

GodotSteam/GodotSteam: An ecosystem of tools for Godot Engine and Valve's Steam. For the Windows, Linux, and Mac platforms.

在反编译后直接修改调试

  • 其它思路可参考:

(针对GDscript脚本加载、方法执行等等;GDScript::load_source_code、GDScriptFunctions::call、……)

游戏中脚本方式值修改-Godot Engine - Yofoo - 博客园

godot 引擎逆向初探 | in1t's blog

Brotato (蒸汽) - Fearless 作弊引擎

NotNite/GDWeave:Godot的Mod加载器和运行时脚本修补

mod 文件结构

GodotModding/godot-mod-loader:

Mod Structure - GMLWiki

//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

Stats - Brotato Wiki

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

Mod Loader Options - GMLWiki

image-20250111210650701

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

ISteamUGC 接口 (Steamworks 文献库)

获得当前游戏中,当前用户所订阅的所有物品的清单。

func get_subscribed_mods()->Array:
	return steam.getSubscribedItems()

如何加载自定义mod

因此在不修改游戏的情况下,需要通过‘创意工坊’订阅mod后,才能加载;

订阅后便可以在 Steam安装目录steamapps\workshop\content\1942280\ (对应brotato)下

会出现一个名字全为数字的文件夹,因此可以在订阅一个mod后将自己的mod zip进行替换

log 会出现在%AppData%\Brotato\logs 目录下

效果

修改后游戏变得索然无味~

image-20250111213336248

image-20250111213533896

posted @ 2025-01-11 21:57  DirWangK  阅读(2256)  评论(0)    收藏  举报