noita_entangled_worlds/quant.ew/init.lua

417 lines
15 KiB
Lua
Raw Normal View History

2024-04-29 22:14:22 +03:00
dofile_once("mods/quant.ew/NoitaPatcher/load.lua")
2024-08-09 13:13:08 +03:00
np = require("noitapatcher")
2024-04-29 22:14:22 +03:00
package.cpath = package.cpath .. ";./mods/quant.ew/?.dll"
package.path = package.path .. ";./mods/quant.ew/?.lua"
print(package.cpath)
2024-04-29 22:14:22 +03:00
dofile_once( "data/scripts/lib/utilities.lua" )
dofile_once("mods/quant.ew/files/system/player/player_cosmetics.lua")
2024-04-29 22:14:22 +03:00
np.InstallShootProjectileFiredCallbacks()
np.EnableGameSimulatePausing(false)
np.InstallDamageDetailsPatch()
np.SilenceLogs("Warning - streaming didn\'t find any chunks it could stream away...\n")
2024-09-23 19:48:56 +03:00
ewext = require("ewext")
2024-08-09 13:13:08 +03:00
-- Make some stuff global, as it's way too annoying to import each time.
ctx = dofile_once("mods/quant.ew/files/core/ctx.lua")
player_fns = dofile_once("mods/quant.ew/files/core/player_fns.lua")
net = dofile_once("mods/quant.ew/files/core/net.lua")
util = dofile_once("mods/quant.ew/files/core/util.lua")
inventory_helper = dofile_once("mods/quant.ew/files/core/inventory_helper.lua")
2024-08-13 14:18:45 +03:00
constants = dofile_once("mods/quant.ew/files/core/constants.lua")
2024-05-20 01:01:35 +03:00
2024-08-07 17:11:55 +03:00
local perk_fns = dofile_once("mods/quant.ew/files/core/perk_fns.lua")
2024-05-20 01:01:35 +03:00
2024-05-23 21:02:39 +03:00
local version = dofile_once("mods/quant.ew/files/version.lua") or "unknown (dev build)"
print("Noita EW version: "..version)
2024-06-20 15:53:01 +03:00
dofile_once("data/scripts/lib/coroutines.lua")
2024-08-07 17:21:25 +03:00
ModLuaFileAppend("data/scripts/gun/gun.lua", "mods/quant.ew/files/resource/append/gun.lua")
ModLuaFileAppend("data/scripts/gun/gun_actions.lua", "mods/quant.ew/files/resource/append/action_fix.lua")
2024-05-12 15:31:08 +03:00
ModMagicNumbersFileAdd("mods/quant.ew/files/magic.xml")
np.CrossCallAdd("ew_per_peer_seed", function()
return tonumber(string.sub(ctx.my_id, 9), 16)
end)
2024-06-06 15:25:01 +03:00
local function load_modules()
2024-09-23 19:48:56 +03:00
ctx.load_system("ewext_init")
2024-08-07 17:11:55 +03:00
ctx.dofile_and_add_hooks("mods/quant.ew/files/system/item_sync.lua")
2024-08-13 02:54:44 -04:00
2024-08-07 17:11:55 +03:00
ctx.dofile_and_add_hooks("mods/quant.ew/files/system/player_sync.lua")
ctx.dofile_and_add_hooks("mods/quant.ew/files/system/enemy_sync.lua")
2024-08-07 15:05:38 +03:00
if ctx.proxy_opt.game_mode == "shared_health" then
ctx.load_system("damage")
ctx.load_system("heart_pickups")
2024-08-07 15:05:38 +03:00
ctx.load_system("patch_meat_biome")
ctx.load_system("kivi_patch")
end
if ctx.proxy_opt.game_mode == "local_health" then
ctx.load_system("local_health")
2024-08-09 11:31:16 +03:00
ctx.load_system("notplayer_ai")
2024-08-27 19:54:54 +03:00
ctx.load_system("spectator_helps")
ctx.load_system("end_fight")
2024-08-07 15:05:38 +03:00
end
2024-08-07 17:11:55 +03:00
ctx.dofile_and_add_hooks("mods/quant.ew/files/system/nickname.lua")
2024-06-21 15:45:55 +03:00
2024-07-18 13:15:21 +03:00
if ctx.proxy_opt.debug then
2024-08-07 17:11:55 +03:00
ctx.dofile_and_add_hooks("mods/quant.ew/files/system/debug.lua")
2024-06-21 15:45:55 +03:00
end
2024-08-13 02:54:44 -04:00
ctx.load_system("fungal_shift")
2024-08-07 17:11:55 +03:00
ctx.dofile_and_add_hooks("mods/quant.ew/files/system/weather_sync.lua")
ctx.load_system("polymorph")
2024-06-06 15:25:01 +03:00
2024-08-25 14:45:47 +03:00
ctx.load_system("world_sync")
ctx.load_system("spawn_hooks")
2024-08-07 17:11:55 +03:00
ctx.dofile_and_add_hooks("mods/quant.ew/files/system/proxy_info.lua")
ctx.load_system("perk_patches")
2024-07-02 01:32:51 +03:00
2024-07-18 13:15:21 +03:00
if ctx.proxy_opt.player_tether then
ctx.load_system("player_tether")
2024-07-02 01:32:51 +03:00
end
2024-07-14 12:19:26 +03:00
ctx.load_system("kolmi")
ctx.load_system("ending")
ctx.load_system("spell_patches")
2024-07-18 16:27:28 +03:00
ctx.load_system("enemy_scaling")
2024-08-06 14:28:37 +03:00
ctx.load_system("patch_dragon_boss")
2024-08-05 16:38:55 +03:00
ctx.load_system("player_arrows")
2024-08-19 08:45:35 -04:00
ctx.load_system("player_ping")
ctx.load_system("extra_genomes")
2024-08-19 22:36:26 +03:00
ctx.load_system("game_effect_sync")
2024-08-21 14:25:12 +03:00
ctx.load_system("orb_sync")
2024-08-21 21:15:22 +03:00
ctx.load_system("flag_sync")
2024-08-22 15:41:13 +03:00
ctx.load_system("essence_sync")
ctx.load_system("spectate")
2024-09-03 09:03:59 -04:00
ctx.load_system("effect_data_sync")
ctx.load_system("gen_sync")
2024-09-22 09:56:48 -04:00
ctx.load_system("karl")
ctx.load_system("remove_wand_sound")
if ctx.proxy_opt.randomize_perks then
ctx.load_system("randomize_perks")
end
2024-10-02 20:42:56 +03:00
ctx.load_system("streaming_sync")
2024-10-03 20:30:06 -04:00
ctx.load_system("random_start")
2024-06-06 15:25:01 +03:00
end
local function is_suitable_target(entity)
return EntityGetIsAlive(entity) and not EntityHasTag(entity,"ew_notplayer")
end
2024-05-12 16:23:28 +03:00
function OnProjectileFired(shooter_id, projectile_id, initial_rng, position_x, position_y, target_x, target_y, send_message,
2024-05-02 20:24:27 +03:00
unknown1, multicast_index, unknown3)
2024-06-14 23:55:25 +03:00
ctx.hook.on_projectile_fired(shooter_id, projectile_id, initial_rng, position_x, position_y, target_x, target_y, send_message, unknown1, multicast_index, unknown3)
2024-05-12 15:31:08 +03:00
if not EntityHasTag(shooter_id, "player_unit") and not EntityHasTag(shooter_id, "ew_client") then
return -- Not fired by player, we don't care about it (for now?)
end
2024-06-14 20:40:38 +03:00
EntityAddTag(projectile_id, "ew_no_enemy_sync")
2024-05-12 15:31:08 +03:00
local projectileComponent = EntityGetFirstComponentIncludingDisabled(projectile_id, "ProjectileComponent")
local entity_that_shot
if projectileComponent == nil then
entity_that_shot = GameGetWorldStateEntity()
else
entity_that_shot = ComponentGetValue2(projectileComponent, "mEntityThatShot")
end
2024-05-12 15:31:08 +03:00
2024-05-12 16:23:28 +03:00
local shooter_player_data = player_fns.get_player_data_by_local_entity_id(shooter_id)
local rng = 0
-- Was shot locally
2024-06-14 01:32:58 +03:00
if shooter_id == ctx.my_player.entity then
2024-05-12 16:23:28 +03:00
-- If it was an initial shot by host
if (entity_that_shot == 0 and multicast_index ~= -1 and unknown3 == 0) then
rng = initial_rng
table.insert(shooter_player_data.projectile_rng_init, rng)
else
2024-08-21 17:46:01 -04:00
rng = (shooter_player_data.projectile_seed_chain[entity_that_shot] or 0) + 25
2024-05-12 16:23:28 +03:00
end
else
if (entity_that_shot == 0 and multicast_index ~= -1 and unknown3 == 0) then
if #shooter_player_data.projectile_rng_init > 0 then
2024-05-12 16:23:28 +03:00
rng = table.remove(shooter_player_data.projectile_rng_init, 1)
else
-- Shouldn't happen
rng = 0
end
else
2024-06-29 18:33:19 +03:00
rng = (shooter_player_data.projectile_seed_chain[entity_that_shot] or 0) + 25
2024-05-12 16:23:28 +03:00
end
end
shooter_player_data.projectile_seed_chain[projectile_id] = rng
2024-05-12 15:31:08 +03:00
np.SetProjectileSpreadRNG(rng)
2024-05-02 20:24:27 +03:00
end
function OnProjectileFiredPost(shooter_id, projectile_id, rng, position_x, position_y, target_x, target_y, send_message,
unknown1, multicast_index, unknown3)
end
function OnPausedChanged(paused, is_wand_pickup)
ctx.is_wand_pickup = is_wand_pickup
local players = EntityGetWithTag("player_unit") or {}
if (players[1]) then
np.RegisterPlayerEntityId(players[1])
--local inventory_gui = EntityGetFirstComponentIncludingDisabled(players[1], "InventoryGuiComponent")
local controls_component = EntityGetFirstComponentIncludingDisabled(players[1], "ControlsComponent")
if (paused) then
--EntitySetComponentIsEnabled(players[1], inventory_gui, false)
np.EnableInventoryGuiUpdate(false)
np.EnablePlayerItemPickUpper(false)
ComponentSetValue2(controls_component, "enabled", false)
else
--EntitySetComponentIsEnabled(players[1], inventory_gui, true)
np.EnableInventoryGuiUpdate(true)
np.EnablePlayerItemPickUpper(true)
ComponentSetValue2(controls_component, "enabled", true)
end
end
2024-05-02 20:24:27 +03:00
end
2024-04-29 22:14:22 +03:00
function OnWorldInitialized() -- This is called once the game world is initialized. Doesn't ensure any world chunks actually exist. Use OnPlayerSpawned to ensure the chunks around player have been loaded or created.
2024-08-06 14:28:37 +03:00
if ctx.is_host then
GameAddFlagRun("ew_flag_this_is_host")
else
GameRemoveFlagRun("ew_flag_this_is_host")
end
ctx.hook.on_world_initialized()
2024-04-29 22:14:22 +03:00
end
2024-05-12 15:31:08 +03:00
2024-04-29 22:14:22 +03:00
function OnPlayerSpawned( player_entity ) -- This runs when player entity has been created
2024-06-14 17:03:34 +03:00
print("Initial player entity: "..player_entity)
2024-08-13 02:54:44 -04:00
if GlobalsGetValue("ew_player_count", "") == "" then
GlobalsSetValue("ew_player_count", "1")
end
2024-05-15 16:50:59 +03:00
local x, y = EntityGetTransform(player_entity)
ctx.initial_player_pos = {x=x, y=y}
2024-06-14 01:32:58 +03:00
local my_player = player_fns.make_playerdata_for(player_entity, ctx.my_id)
2024-05-02 20:24:27 +03:00
ctx.players[ctx.my_id] = my_player
2024-05-12 16:23:28 +03:00
ctx.player_data_by_local_entity[player_entity] = my_player
2024-05-02 20:24:27 +03:00
ctx.ready = true
ctx.my_player = my_player
2024-05-07 23:46:15 +03:00
2024-07-16 12:48:40 +03:00
EntityAddTag(player_entity, "ew_peer")
2024-08-09 15:43:56 +03:00
if not GameHasFlagRun("ew_flag_notplayer_active") then
EntityAddComponent2(player_entity, "LuaComponent", {script_wand_fired = "mods/quant.ew/files/resource/cbs/count_times_wand_fired.lua"})
end
2024-05-12 15:31:08 +03:00
net.send_welcome()
local item_pick = EntityGetFirstComponentIncludingDisabled(player_entity, "ItemPickUpperComponent")
ComponentSetValue2(item_pick, "is_immune_to_kicks", true)
2024-05-26 00:49:53 +03:00
ctx.hook.on_local_player_spawn(my_player)
2024-05-27 19:53:29 +03:00
ctx.hook.on_should_send_updates()
2024-05-26 00:49:53 +03:00
GamePrint("Noita Entangled Worlds version "..version)
OnPausedChanged(false, false)
2024-08-13 02:54:44 -04:00
2024-05-29 23:55:34 +03:00
print("Game state entity: "..GameGetWorldStateEntity())
2024-08-13 02:54:44 -04:00
if not GameHasFlagRun("ew_flag_notplayer_active") then
player_cosmetics(player_entity)
player_color(player_entity)
else
EntityInflictDamage(player_entity, 1000000, "DAMAGE_CURSE", "dont rejoin", "NONE", 0, 0, GameGetWorldStateEntity())
GameAddFlagRun("ew_kill_player")
end
if ctx.host_id == ctx.my_id then
np.MagicNumbersSetValue("STREAMING_CHUNK_TARGET", ctx.proxy_opt.chunk_target)
end
2024-08-25 17:53:29 -04:00
local controls_component = EntityGetFirstComponentIncludingDisabled(player_entity, "ControlsComponent")
ComponentSetValue2(controls_component, "enabled", true)
2024-04-29 22:14:22 +03:00
end
2024-10-04 20:17:12 -04:00
local function change_homing(x, y)
for _, proj in pairs(EntityGetInRadiusWithTag(x, y, 512, "player_projectile")) do
local homing = EntityGetFirstComponentIncludingDisabled(proj, "HomingComponent")
if homing ~= nil then
local projcom = EntityGetFirstComponentIncludingDisabled(proj, "ProjectileComponent")
if projcom ~= nil then
local whoshot = ComponentGetValue2(projcom, "mWhoShot")
if EntityHasTag(whoshot, "ew_notplayer") then
ComponentSetValue2(homing, "target_tag", "ew_peer")
end
end
end
end
end
2024-05-12 15:31:08 +03:00
local function on_world_pre_update_inner()
if ctx.my_player == nil or ctx.my_player.entity == nil then return end
2024-05-10 22:17:45 +03:00
2024-05-12 15:31:08 +03:00
GlobalsSetValue("ew_player_rng", tostring(GameGetFrameNum()))
2024-05-13 15:18:52 +03:00
2024-05-02 20:24:27 +03:00
net.update()
2024-05-11 18:06:48 +03:00
2024-06-14 01:32:58 +03:00
local inventory_gui_comp = EntityGetFirstComponentIncludingDisabled(ctx.my_player.entity, "InventoryGuiComponent")
2024-06-14 20:40:38 +03:00
if inventory_gui_comp and inventory_gui_comp ~= 0 then
local inventory_open = ComponentGetValue2(inventory_gui_comp, "mActive")
if ctx.is_inventory_open and not inventory_open then
ctx.events.inventory_maybe_just_changed = true
end
ctx.is_inventory_open = inventory_open
2024-05-15 16:50:59 +03:00
end
if GameGetFrameNum() % 120 == 0 and not ctx.run_ended then
player_fns.respawn_if_necessary()
end
2024-06-14 01:32:58 +03:00
if ctx.events.new_player_just_connected or ctx.events.inventory_maybe_just_changed or (GameGetFrameNum() % 5 == 0 and inventory_helper.has_inventory_changed(ctx.my_player)) then
async(function()
-- Wait 1 frame because apperently it takes some time for an item to get properly "registered" in an inventory?
wait(1)
local inventory_state = player_fns.serialize_items(ctx.my_player)
if inventory_state ~= nil then
net.send_player_inventory(inventory_state)
end
end)
2024-05-15 16:50:59 +03:00
end
-- Perk sync
if GameGetFrameNum() % 120 == 0 and not ctx.run_ended then
2024-05-07 23:46:15 +03:00
local perk_data = perk_fns.get_my_perks()
2024-05-10 22:17:45 +03:00
if perk_data ~= nil then
net.send_player_perks(perk_data)
end
2024-05-03 23:38:40 +03:00
end
if not ctx.run_ended then
if ctx.is_host then
ctx.hook.on_world_update_host()
else
ctx.hook.on_world_update_client()
end
ctx.hook.on_world_update()
2024-05-20 01:01:35 +03:00
end
2024-06-20 15:53:01 +03:00
2024-10-04 20:17:12 -04:00
if GameGetFrameNum() % 4 == 0 then
local x, y = EntityGetTransform(ctx.my_player.entity)
2024-10-05 06:12:44 -04:00
if x ~= nil then
change_homing(x, y)
end
2024-10-04 20:17:12 -04:00
elseif GameGetFrameNum() % 4 == 1 then
local x, y = EntityGetTransform(ctx.my_player.entity)
local cx, cy = GameGetCameraPos()
2024-10-05 06:12:44 -04:00
if x ~= nil and cx ~= nil then
if math.abs(x - cx) > 256 or math.abs(y - cy) > 256 then
change_homing(cx, cy)
end
end
end
2024-06-20 15:53:01 +03:00
wake_up_waiting_threads(1)
2024-04-29 22:14:22 +03:00
end
2024-05-12 15:31:08 +03:00
function OnWorldPreUpdate() -- This is called every time the game is about to start updating the world
util.tpcall(on_world_pre_update_inner)
end
local function on_world_post_update_inner()
if ctx.my_player == nil or ctx.my_player.entity == nil then return end
2024-05-25 22:20:43 +03:00
if not ctx.run_ended then
ctx.hook.on_world_update_post()
end
2024-05-25 22:20:43 +03:00
2024-05-12 15:31:08 +03:00
local times_wand_fired = tonumber(GlobalsGetValue("ew_wand_fired", "0"))
GlobalsSetValue("ew_wand_fired", "0")
if times_wand_fired > 0 then
local inventory_component = EntityGetFirstComponentIncludingDisabled(ctx.my_player.entity, "Inventory2Component")
if inventory_component == nil then
return
end
local last_switch = ComponentGetValue2(inventory_component, "mLastItemSwitchFrame")
local switched_now = last_switch == GameGetFrameNum()
2024-08-13 02:54:44 -04:00
2024-05-12 15:31:08 +03:00
local special_seed = tonumber(GlobalsGetValue("ew_player_rng", "0"))
2024-06-14 01:32:58 +03:00
local fire_data = player_fns.make_fire_data(special_seed, ctx.my_player)
2024-05-12 15:31:08 +03:00
if fire_data ~= nil then
if switched_now then
fire_data.switched_now = true
end
2024-05-12 15:31:08 +03:00
net.send_fire(fire_data)
end
end
end
function OnWorldPostUpdate() -- This is called every time the game has finished updating the world
util.tpcall(on_world_post_update_inner)
2024-05-15 16:50:59 +03:00
ctx.events = {}
2024-05-12 15:31:08 +03:00
end
2024-04-29 22:14:22 +03:00
function register_localizations(translation_file, clear_count)
clear_count = clear_count or 0
local loc_content = ModTextFileGetContent("data/translations/common.csv") -- Gets the original translations of the game
local append_content = ModTextFileGetContent(translation_file) -- Gets my own translations file
-- Split the append_content into lines
local lines = {}
for line in append_content:gmatch("[^\n]+") do
table.insert(lines, line)
end
-- Remove the first clear_count lines
for i = 1, clear_count do
table.remove(lines, 1)
end
-- Reconstruct append_content after removing clear_count lines
local new_append_content = table.concat(lines, "\n")
-- if loc_content does not end with a new line, add one
if not loc_content:match("\n$") then
loc_content = loc_content .. "\n"
end
-- Concatenate loc_content and new_append_content without extra newline character
local new_content = loc_content .. new_append_content .. "\n"
-- Set the new content to the file
ModTextFileSetContent("data/translations/common.csv", new_content)
end
function OnModPreInit()
register_localizations("mods/quant.ew/translations.csv", 1)
2024-05-02 20:24:27 +03:00
ctx.init()
net.init()
2024-08-06 14:28:37 +03:00
2024-06-06 15:25:01 +03:00
load_modules()
2024-08-13 02:54:44 -04:00
2024-08-07 16:37:54 +03:00
print("Entangled worlds init ok")
2024-04-29 22:14:22 +03:00
end
2024-06-14 17:03:34 +03:00
function OnModInit() end
2024-09-11 12:38:20 +03:00
function OnModPostInit()
ctx.hook.on_late_init()
end
2024-04-29 22:14:22 +03:00
2024-08-07 16:37:54 +03:00
function OnPlayerDied(player_entity)
ctx.hook.on_player_died(player_entity)
print("player died")
end