2024-04-29 22:14:22 +03:00
dofile_once ( " mods/quant.ew/NoitaPatcher/load.lua " )
local np = require ( " noitapatcher " )
dofile_once ( " data/scripts/lib/utilities.lua " )
np.InstallShootProjectileFiredCallbacks ( )
np.EnableGameSimulatePausing ( false )
np.InstallDamageDetailsPatch ( )
np.SilenceLogs ( " Warning - streaming didn \' t find any chunks it could stream away... \n " )
2024-05-20 01:01:35 +03:00
local ctx = dofile_once ( " mods/quant.ew/files/src/ctx.lua " )
2024-04-29 22:14:22 +03:00
local player_fns = dofile_once ( " mods/quant.ew/files/src/player_fns.lua " )
local net = dofile_once ( " mods/quant.ew/files/src/net.lua " )
2024-05-10 22:17:45 +03:00
local util = dofile_once ( " mods/quant.ew/files/src/util.lua " )
2024-05-20 01:01:35 +03:00
local inventory_helper = dofile_once ( " mods/quant.ew/files/src/inventory_helper.lua " )
2024-05-03 23:38:40 +03:00
local pretty = dofile_once ( " mods/quant.ew/files/lib/pretty_print.lua " )
2024-05-07 23:46:15 +03:00
local perk_fns = dofile_once ( " mods/quant.ew/files/src/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) "
2024-06-01 14:30:04 +03:00
print ( " Noita EW version: " .. version )
2024-05-22 12:48:21 +03:00
2024-05-12 15:31:08 +03:00
ModLuaFileAppend ( " data/scripts/gun/gun.lua " , " mods/quant.ew/files/append/gun.lua " )
ModLuaFileAppend ( " data/scripts/gun/gun_actions.lua " , " mods/quant.ew/files/append/action_fix.lua " )
2024-05-19 21:23:51 +03:00
ModLuaFileAppend ( " data/scripts/items/heart.lua " , " mods/quant.ew/files/append/heart.lua " )
ModLuaFileAppend ( " data/scripts/items/heart_better.lua " , " mods/quant.ew/files/append/heart_better.lua " )
ModLuaFileAppend ( " data/scripts/items/heart_evil.lua " , " mods/quant.ew/files/append/heart_evil.lua " )
ModLuaFileAppend ( " data/scripts/items/heart_fullhp.lua " , " mods/quant.ew/files/append/heart_fullhp.lua " )
ModLuaFileAppend ( " data/scripts/items/heart_fullhp_temple.lua " , " mods/quant.ew/files/append/heart_fullhp_temple.lua " )
2024-06-01 14:30:04 +03:00
ModMagicNumbersFileAdd ( " mods/quant.ew/files/magic.xml " )
2024-06-06 15:25:01 +03:00
local function load_modules ( )
ctx.dofile_and_add_hooks ( " mods/quant.ew/files/src/item_sync.lua " )
ctx.dofile_and_add_hooks ( " mods/quant.ew/files/src/system/enemy_sync.lua " )
2024-06-14 20:40:38 +03:00
-- ctx.dofile_and_add_hooks("mods/quant.ew/files/src/system/effect_sync.lua")
2024-06-10 23:50:13 +03:00
ctx.dofile_and_add_hooks ( " mods/quant.ew/files/src/system/damage/sync.lua " )
2024-06-06 15:25:01 +03:00
ctx.dofile_and_add_hooks ( " mods/quant.ew/files/src/system/nickname.lua " )
ctx.dofile_and_add_hooks ( " mods/quant.ew/files/src/system/debug.lua " )
2024-06-07 21:20:20 +03:00
ctx.dofile_and_add_hooks ( " mods/quant.ew/files/src/system/fungal_shift/sync.lua " )
2024-06-07 22:07:56 +03:00
ctx.dofile_and_add_hooks ( " mods/quant.ew/files/src/system/weather_sync.lua " )
2024-06-14 01:32:58 +03:00
ctx.dofile_and_add_hooks ( " mods/quant.ew/files/src/system/polymorph/sync.lua " )
2024-06-06 15:25:01 +03:00
if ctx.proxy_opt . world_sync_version == " 1 " then
ctx.dofile_and_add_hooks ( " mods/quant.ew/files/src/system/world_sync_v1.lua " )
else
ctx.dofile_and_add_hooks ( " mods/quant.ew/files/src/system/world_sync_v2.lua " )
end
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 = ComponentGetValue2 ( projectileComponent , " mEntityThatShot " )
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
rng = shooter_player_data.projectile_seed_chain [ entity_that_shot ] + 25
end
else
if ( entity_that_shot == 0 and multicast_index ~= - 1 and unknown3 == 0 ) then
2024-05-12 18:26:54 +03:00
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
GamePrint ( " No values in projectile_rng_init " )
rng = 0
end
else
rng = shooter_player_data.projectile_seed_chain [ entity_that_shot ] + 25
end
end
shooter_player_data.projectile_seed_chain [ projectile_id ] = rng
-- GamePrint("on fired "..projectile_id.." "..entity_that_shot.." "..shooter_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 )
2024-05-25 13:55:38 +03:00
local players = EntityGetWithTag ( " ew_current_player " ) or { }
2024-05-02 20:24:27 +03:00
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
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-05-02 20:24:27 +03:00
--GamePrint( "OnWorldInitialized() " .. tostring(GameGetFrameNum()) )
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-05-19 21:23:51 +03:00
if GlobalsGetValue ( " ew_player_count " , " " ) == " " then
GlobalsSetValue ( " ew_player_count " , " 1 " )
end
2024-05-15 16:50:59 +03:00
for _ , client in pairs ( EntityGetWithTag ( " ew_client " ) ) do
GamePrint ( " Removing previous client: " .. client )
EntityKill ( client )
end
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
GamePrint ( " My peer_id: " .. ctx.my_id )
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
2024-05-19 21:23:51 +03:00
ctx.my_player = my_player
2024-05-07 23:46:15 +03:00
np.SetPauseState ( 4 )
np.SetPauseState ( 0 )
2024-06-14 01:32:58 +03:00
-- EntityAddTag(player_entity, "polymorphable_NOT") -- TODO
2024-05-14 15:38:20 +03:00
2024-05-10 23:43:32 +03:00
if ctx.is_host then
EntityAddTag ( player_entity , " ew_host " )
else
2024-05-26 00:49:53 +03:00
-- EntityAddComponent2(player_entity, "LuaComponent", {script_damage_about_to_be_received = "mods/quant.ew/files/cbs/immortal.lua"})
2024-05-10 22:17:45 +03:00
end
2024-05-25 13:55:38 +03:00
EntityAddTag ( player_entity , " ew_current_player " )
2024-05-12 15:31:08 +03:00
EntityAddComponent2 ( player_entity , " LuaComponent " , { script_wand_fired = " mods/quant.ew/files/cbs/count_times_wand_fired.lua " } )
2024-05-18 19:13:34 +03:00
net.send_welcome ( )
2024-05-18 21:22:37 +03:00
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
2024-05-22 12:48:21 +03:00
GamePrint ( " Noita Entangled Worlds version " .. version )
2024-05-25 13:55:38 +03:00
OnPausedChanged ( false , false )
2024-05-29 23:55:34 +03:00
print ( " Game state entity: " .. GameGetWorldStateEntity ( ) )
2024-04-29 22:14:22 +03:00
end
2024-05-12 15:31:08 +03:00
local function on_world_pre_update_inner ( )
2024-06-14 01:32:58 +03:00
if ctx.my_player == 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
2024-06-16 14:31:52 +03:00
-- if not ctx.is_host then
-- local hp, _ = util.get_ent_health(ctx.my_player.entity)
-- if hp == 0 then
-- EntityInflictDamage(ctx.my_player.entity, 10000000, "DAMAGE_CURSE", "Out of shared health", "NONE", 0, 0, GameGetWorldStateEntity())
-- GameTriggerGameOver()
-- if not ctx.run_ended then
-- GamePrint("Notifying of run end")
-- net.proxy_notify_game_over()
-- ctx.run_ended = true
-- end
-- end
-- end
2024-05-13 13:07:28 +03:00
2024-05-24 23:27:06 +03:00
if GameGetFrameNum ( ) % 120 == 0 then
player_fns.respawn_if_necessary ( )
player_fns.spread_max_health ( )
end
2024-05-24 17:27:16 +03:00
2024-05-11 18:06:48 +03:00
-- Player sync
2024-05-08 20:33:41 +03:00
if GameGetFrameNum ( ) % 1 == 0 then
2024-06-14 01:32:58 +03:00
local input_data = player_fns.serialize_inputs ( ctx.my_player )
local pos_data = player_fns.serialize_position ( ctx.my_player )
local current_slot = player_fns.get_current_slot ( ctx.my_player )
2024-05-14 15:06:32 +03:00
if input_data ~= nil and pos_data ~= nil then
net.send_player_update ( input_data , pos_data , current_slot )
end
2024-04-29 22:14:22 +03:00
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
local inventory_state = player_fns.serialize_items ( ctx.my_player )
2024-05-15 17:39:40 +03:00
if inventory_state ~= nil then
-- GamePrint("Sending updated inventory")
net.send_player_inventory ( inventory_state )
2024-05-15 16:50:59 +03:00
end
end
2024-05-25 22:24:15 +03:00
-- 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
2024-05-19 21:23:51 +03:00
local heart_pickup = GlobalsGetValue ( " ew_heart_pickup " , " " )
if heart_pickup ~= " " then
net.send_heart_pickup ( heart_pickup )
GlobalsSetValue ( " ew_heart_pickup " , " " )
end
2024-05-20 01:01:35 +03:00
if ctx.is_host then
ctx.hook . on_world_update_host ( )
else
ctx.hook . on_world_update_client ( )
end
2024-05-24 23:27:06 +03:00
ctx.hook . on_world_update ( )
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 ( )
2024-06-14 01:32:58 +03:00
if ctx.my_player == nil then return end
2024-05-25 22:20:43 +03:00
-- local px, py = EntityGetTransform(my_player.entity)
-- GameSetCameraPos(px, py)
2024-06-14 17:03:34 +03:00
ctx.hook . on_world_update_post ( )
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 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
net.send_fire ( fire_data )
end
end
2024-06-14 17:03:34 +03:00
if ctx.is_host and not EntityGetIsAlive ( ctx.my_player . entity ) then
GamePrint ( " My player is not alive " .. ctx.my_player . entity )
if not ctx.run_ended then
GamePrint ( " Notifying of run end " )
net.proxy_notify_game_over ( )
ctx.run_ended = true
end
end
2024-05-12 15:31:08 +03:00
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 ( )
2024-04-30 23:49:51 +03:00
net.init ( )
2024-06-06 15:25:01 +03:00
load_modules ( )
2024-04-29 22:14:22 +03:00
end
2024-06-14 17:03:34 +03:00
function OnModInit ( ) end
function OnModPostInit ( ) end
2024-04-29 22:14:22 +03:00
print ( " entangled_worlds init ok " )