z_mirror/Krastorio2
git clone https://git.raiguard.me/z_mirror/Krastorio2
041f29c4
santichu95/patch-1
1local charging_rate =3000000 -- 3 MW 2local cooldown =10 3local loss_multiplier =1.8 4local range =20 5local required_energy =10000000 -- 10 MW 6 7local absorber_buffer_capacity =prototypes . equipment [ "energy-absorber-equipment" ]. energy_source . buffer_capacity 8 9-- TOWER 10-- The entity that is interacted with 11 12--- @param e EntityBuiltEvent 13local function on_entity_built ( e ) 14local entity =e . entity or e . destination 15if not entity or not entity . valid then 16return 17end 18local entity_name =entity . name 19 20-- Internal entities should not be cloned 21if 22e . name == defines . events . on_entity_cloned 23and ( entity_name == "kr-tesla-coil-turret" or entity_name == "kr-tesla-coil-collision" ) 24then 25entity . destroy () 26return 27end 28 29if entity_name ~= "kr-tesla-coil" then 30return 31end 32 33local surface =entity . surface 34local unit_number =entity . unit_number --[[@as uint]] 35 36local turret =surface . create_entity ( { 37name ="kr-tesla-coil-turret" , 38position =entity . position , 39force =game . forces [ "kr-internal-turrets" ], 40create_build_effect_smoke =false , 41raise_built =true , 42} ) 43if not turret or not turret . valid then 44game . ( 45"Building tesla failed due to AAI Programmable Vehicles; This tesla coil will not function. To fix this, change the 'Deadzone construction denial range' map setting to zero." 46) 47entity . active =false 48return 49end 50turret . destructible =false 51 52local collision_entity =surface . create_entity ( { 53name ="kr-tesla-coil-collision" , 54position =entity . position , 55force =entity . force , 56create_build_effect_smoke =false , 57raise_built =true , 58} ) 59collision_entity . destructible =false 60 61--- @class TowerData 62local data ={ 63entities ={ 64collision =collision_entity , 65tower =entity , 66turret =turret , 67} , 68tower_unit_number =unit_number , 69turret_unit_number =turret . unit_number , 70} 71 72storage . tesla_coil . turrets [ data . turret_unit_number ] =data 73storage . tesla_coil . towers [ unit_number ] =data 74end 75 76--- @param entity LuaEntity 77local function destroy_if_valid ( entity ) 78if entity . valid then 79entity . destroy () 80end 81end 82 83--- @param e EntityDestroyedEvent 84local function on_entity_destroyed ( e ) 85local entity =e . entity 86if not entity or not entity . valid or entity . name ~= "kr-tesla-coil" then 87return 88end 89 90local unit_number =entity . unit_number 91assert ( unit_number ) 92local tower_data =storage . tesla_coil . towers [ unit_number ] 93if not tower_data then 94return 95end 96 97destroy_if_valid ( tower_data . entities . collision ) 98destroy_if_valid ( tower_data . entities . turret ) 99 100storage . tesla_coil . turrets [ tower_data . turret_unit_number ] =nil 101storage . tesla_coil . towers [ unit_number ] =nil 102end 103 104-- TARGET 105-- An entity that will receive energy from a tesla coil 106 107--- @param target LuaEntity 108--- @return GridData? 109local function get_grid_data ( target ) 110--- @type LuaEquipmentGrid 111local grid 112if target . type == "character" then 113local armor_inventory =target . get_inventory ( defines . inventory . character_armor ) 114if armor_inventory and armor_inventory . valid then 115local armor =armor_inventory [ 1 ] 116if armor and armor . valid_for_read then 117grid =armor . grid 118end 119end 120else 121grid =target . grid 122end 123 124if grid then 125--- @class GridData 126local data ={ 127absorber =grid . find ( "energy-absorber-equipment" ), 128grid =grid , 129} 130 131return data 132end 133end 134 135--- Updates the absorber object in a target's equipment grid 136--- @param grid LuaEquipmentGrid 137local function update_target_grid ( grid ) 138for _ , target_data in pairs ( storage . tesla_coil . targets ) do 139local grid_data =target_data . grid_data 140if grid_data . grid . valid and grid_data . grid == grid then 141grid_data . absorber =grid . find ( "energy-absorber-equipment" ) 142end 143end 144end 145 146--- @param target LuaEntity 147--- @param tower_data TowerData 148local function add_target ( target , tower_data ) 149local target_unit_number =target . unit_number --[[@as uint]] 150local tower =tower_data . entities . tower 151if not tower . valid or tower . energy < required_energy then 152return 153end 154-- Check the target's equipment grid for an energy absorber 155local grid_data =get_grid_data ( target ) 156if grid_data and grid_data . absorber and grid_data . absorber . valid then 157--- @class TargetData 158local target_data ={ 159connections ={ 160--- @type table<number, ConnectionData> 161by_beam ={} , 162--- @type table<number, ConnectionData> 163by_tower ={} , 164} , 165entity =target , 166--- @type number? 167full_tick =nil , 168grid_data =grid_data , 169unit_number =target_unit_number , 170} 171storage . tesla_coil . targets [ target_unit_number ] =target_data 172 173return target_data 174end 175end 176 177--- @param target_unit_number number 178local function remove_target ( target_unit_number ) 179storage . tesla_coil . targets [ target_unit_number ] =nil 180end 181 182-- CONNECTION 183-- A connection between a tower and a target, comprising of a beam 184-- There can be unlimited connections per target 185 186--- @param target_data TargetData 187--- @param tower_data TowerData 188--- @return boolean 189local function add_connection ( target_data , tower_data ) 190-- Check if the absorber has space 191local absorber =target_data . grid_data . absorber 192if not absorber or not absorber . valid then 193remove_target ( target_data . unit_number ) 194return false 195end 196 197local tower =tower_data . entities . tower 198if not tower . valid then 199remove_target ( target_data . unit_number ) 200return false 201end 202 203if absorber . energy >= absorber_buffer_capacity then 204return false 205end 206 207-- Create beam entity 208local beam =tower_data . entities . tower . surface . create_entity ( { 209name ="kr-tesla-coil-electric-beam" , 210source =tower_data . entities . tower , 211source_offset ={ 0 , - 2.2 } , 212position =tower_data . entities . tower . position , 213target =target_data . entity , 214duration =0 , 215max_length =range , 216force =tower_data . entities . tower . force , 217raise_built =true , 218} ) 219if not beam then 220return false 221end 222local beam_number =script . register_on_object_destroyed ( beam ) 223 224--- @class BeamData 225storage . tesla_coil . beams [ beam_number ] ={ 226beam =beam , 227beam_number =beam_number , 228target_data =target_data , 229tower_data =tower_data , 230} 231 232--- @class ConnectionData 233local connection_data ={ 234beam =beam , 235beam_number =beam_number , 236tower_data =tower_data , 237} 238target_data . connections . by_beam [ beam_number ] =connection_data 239target_data . connections . by_tower [ tower_data . tower_unit_number ] =connection_data 240 241return true 242end 243 244--- @param target_data TargetData 245--- @param tower_data TowerData 246local function remove_connection ( target_data , tower_data ) 247local connection_data =target_data . connections . by_tower [ tower_data . tower_unit_number ] 248 249-- Destroy beam if it still exists 250if connection_data . beam . valid then 251connection_data . beam . destroy () 252end 253 254local beam_number =connection_data . beam_number 255storage . tesla_coil . beams [ beam_number ] =nil 256 257target_data . connections . by_beam [ beam_number ] =nil 258target_data . connections . by_tower [ tower_data . tower_unit_number ] =nil 259 260if table_size ( target_data . connections . by_beam ) == 0 then 261remove_target ( target_data . unit_number ) 262end 263end 264 265--- @param target_data TargetData 266--- @param tower_data TowerData 267local function update_connection ( target_data , tower_data ) 268local absorber =target_data . grid_data . absorber 269 270-- Check if the tower is powered 271if not absorber or not absorber . valid or tower_data . entities . tower . energy < required_energy then 272remove_connection ( target_data , tower_data ) 273return 274end 275 276local energy =absorber . energy 277if energy < absorber_buffer_capacity then 278-- Calculate how much to add 279local to_add =charging_rate / 60 * cooldown 280local result =energy + to_add 281local tower =tower_data . entities . tower 282 283if result >= absorber_buffer_capacity then 284absorber . energy =absorber_buffer_capacity 285target_data . full_tick =game . tick 286else 287absorber . energy =result 288target_data . full_tick =nil 289end 290 291tower . energy =tower . energy - ( to_add * loss_multiplier ) 292elseif target_data . full_tick and target_data . full_tick + cooldown <= game . tick then 293remove_connection ( target_data , tower_data ) 294end 295end 296 297--- @param target LuaEntity 298--- @param turret LuaEntity 299local function process_turret_fire ( target , turret ) 300local tower_data =storage . tesla_coil . turrets [ turret . unit_number ] 301if not tower_data then 302return 303end 304 305local target_data =storage . tesla_coil . targets [ target . unit_number ] 306if not target_data then 307target_data =add_target ( target , tower_data ) 308end 309 310if target_data then 311-- Just in case (#182) 312if not target_data . entity . valid then 313target_data . entity =target 314end 315local connection =target_data . connections . by_tower [ tower_data . tower_unit_number ] 316if connection or add_connection ( target_data , tower_data ) then 317update_connection ( target_data , tower_data ) 318end 319end 320end 321 322-- EVENTS 323 324--- @param e EventData.on_object_destroyed 325local function on_object_destroyed ( e ) 326local beam_data =storage . tesla_coil . beams [ e . registration_number ] 327if beam_data then 328remove_connection ( beam_data . target_data , beam_data . tower_data ) 329end 330end 331 332--- @param e EventData.on_equipment_inserted 333local function on_equipment_inserted ( e ) 334if not e . equipment . valid or e . equipment . name ~= "energy-absorber-equipment" then 335return 336end 337update_target_grid ( e . grid ) 338end 339 340--- @param e EventData.on_equipment_removed 341local function on_equipment_removed ( e ) 342if e . equipment == "energy-absorber-equipment" then 343update_target_grid ( e . grid ) 344end 345end 346 347--- @param e EventData.on_script_trigger_effect 348local function on_script_trigger_effect ( e ) 349if e . effect_id == "kr-tesla-coil-trigger" then 350process_turret_fire ( e . target_entity , e . source_entity ) 351end 352end 353 354local tesla_coil ={} 355 356function tesla_coil . on_init () 357storage . tesla_coil ={ 358--- @type table<number, BeamData> 359beams ={} , 360--- @type table<number, TowerData> 361turrets ={} , 362--- @type table<number, TowerData> 363towers ={} , 364--- @type table<number, TargetData> 365targets ={} , 366} 367end 368 369tesla_coil . events ={ 370[ defines . events . on_built_entity ] =on_entity_built , 371[ defines . events . on_entity_cloned ] =on_entity_built , 372[ defines . events . on_entity_died ] =on_entity_destroyed , 373[ defines . events . on_equipment_inserted ] =on_equipment_inserted , 374[ defines . events . on_equipment_removed ] =on_equipment_removed , 375[ defines . events . on_object_destroyed ] =on_object_destroyed , 376[ defines . events . on_player_mined_entity ] =on_entity_destroyed , 377[ defines . events . on_robot_built_entity ] =on_entity_built , 378[ defines . events . on_robot_mined_entity ] =on_entity_destroyed , 379[ defines . events . on_script_trigger_effect ] =on_script_trigger_effect , 380[ defines . events . script_raised_built ] =on_entity_built , 381[ defines . events . script_raised_destroy ] =on_entity_destroyed , 382[ defines . events . script_raised_revive ] =on_entity_built , 383[ defines . events . on_space_platform_built_entity ] =on_entity_built , 384[ defines . events . on_space_platform_mined_entity ] =on_entity_destroyed , 385} 386 387return tesla_coil 388 389--[[ 390-- Quick testing code 391event.register(remote.call("EditorExtensions", "debug_world_ready_event"), function() 392local surface = game.surfaces.nauvis 393 394local coils = { 395{ x = -9.5, y = -9.5 }, 396{ x = 10.5, y = -9.5 }, 397{ x = -9.5, y = 10.5 }, 398{ x = 10.5, y = 10.5 }, 399} 400for _, position in pairs(coils) do 401surface.create_entity({ 402name = "kr-tesla-coil", 403direction = defines.direction.north, 404position = position, 405force = game.forces.player, 406raise_built = true, 407create_build_effect_smoke = false, 408}) 409end 410surface.create_entity({ 411name = "ee-infinity-accumulator-primary-output", 412position = { x = -1, y = -9 }, 413force = game.forces.player, 414raise_built = true, 415create_build_effect_smoke = false, 416}) 417surface.create_entity({ 418name = "ee-super-substation", 419position = { x = 1, y = -9 }, 420force = game.forces.player, 421raise_built = true, 422create_build_effect_smoke = false, 423}) 424 425local character = game.get_player(1).character 426local armor_inventory = character.get_inventory(defines.inventory.character_armor) 427if armor_inventory and armor_inventory.valid then 428local armor = armor_inventory[1] 429if armor and armor.valid_for_read then 430armor.grid.put({ name = "energy-absorber-equipment", position = { 5, 5 } }) 431end 432end 433end) 434]]