function rom_reload() {
	exec($Con::File);
}
$lualogic_rom_maxheight = (2/5)*256;

package lualogic_rom_update {
	function fxDtsBrick::onPlant(%brick) {
		parent::onPlant(%brick);
		lualogic_rom_updatebrick(%brick);
	}
	function fxDtsBrick::onLoadPlant(%brick) {
		parent::onLoadPlant(%brick);
		lualogic_rom_updatebrick(%brick);
	}
	function fxDTSBrick::onDeath(%brick) {
		parent::onDeath(%brick);
		%brick.lualogic_rom_delete = 1;
		lualogic_rom_updatebrick(%brick);
	}
	function fxDTSBrick::onRemove(%brick) {
		parent::onRemove(%brick);
		%brick.lualogic_rom_delete = 1;
		lualogic_rom_updatebrick(%brick, 1);
	}
	function fxDtsBrick::setRaycasting(%brick, %val) {
		parent::setRaycasting(%brick, %val);
		lualogic_rom_updatebrick(%brick);
	}
};
schedule(0, 0, activatePackage, lualogic_rom_update);

function lualogic_rom_updatebrick(%brick) {
	cancel(%brick.lualogic_rom_updatebrick_schedule);
	%brick.lualogic_rom_updatebrick_schedule = schedule(100, 0, lualogic_rom_updatebrick_final, %brick, %brick.getWorldBox());
}
function lualogic_rom_updatebrick_final(%brick, %box) {
	if(isObject(%brick)) {
		if(%brick.lualogic_rom_delete) {
			if(%brick.lualogic_rom_deletedone) return;
			%brick.lualogic_rom_deletedone = 1;
		}
	}
	
	// update any roms below
	%boxl = getWords(%box, 0, 2); %boxlz = getWord(%boxl, 2);
	%boxh = getWords(%box, 3, 5);
	%boxs = vectorSub(%boxh, %boxl);
	%boxc = vectorAdd(%boxl, vectorScale(%boxs, 0.5));
	%boxc = getWords(%boxc, 0, 1) SPC (%boxlz - $lualogic_rom_maxheight/2);
	%boxs = getWords(%boxs, 0, 1) SPC $lualogic_rom_maxheight;
	%boxs = vectorSub(%boxs, 0.5 SPC 0.5 SPC 0.1);
	initContainerBoxSearch(%boxc, %boxs, $TypeMasks::FxBrickAlwaysObjectType);
	while(%tbrick = containerSearchNext()) {
		%tdata = %tbrick.getDatablock();
		if(%tdata.isLogicRom) {
			%rommaxz = getWord(%tbrick.getPosition(), 2) + (%tdata.brickSizeZ/10) + ((%tdata.logicRomZ$="" ? 1 : %tdata.logicRomZ)/5) - 0.1;
			if(%boxlz <= %rommaxz) {
				lualogic_rom_updatedata(%tbrick);
			}
		}
	}
	
	// if rom, update
	if(isObject(%brick)) {
		if(%brick.lualogic_rom_delete) return;
		if(%brick.getDatablock().isLogicRom) {
			lualogic_rom_updatedata(%brick);
		}
	}
}

function lualogic_rom_updatedata(%brick) {
	cancel(%brick.lualogic_rom_updatedata_schedule);
	%brick.lualogic_rom_updatedata_schedule = schedule(1000, 0, lualogic_rom_updatedata_final, %brick);
}

function lualogic_rom_min(%a, %b) { return %a<%b ? %a : %b; }
function lualogic_rom_max(%a, %b) { return %a>%b ? %a : %b; }

function lualogic_rom_updatedata_final(%brick) {
	if(!isObject(%brick) || %brick.lualogic_rom_delete) return;
	
	// compute rom stud box
	%data = %brick.getDatablock();
	%rx = (%brick.angleId%2==0) ? %data.logicRomX : %data.logicRomY;
	%ry = (%brick.angleId%2==0) ? %data.logicRomY : %data.logicRomX;
	%rz = (%data.logicRomZ$="") ? 1 : %data.logicRomZ;
	%rpos = vectorAdd(%brick.getPosition(), 0 SPC 0 SPC (%rz/10 + 1/10));
	%rxc = getWord(%rpos, 0)* 4;
	%ryc = getWord(%rpos, 1)* 4;
	%rzc = getWord(%rpos, 2)*10;
	%rxl = %rxc - (%rx-1);
	%ryl = %ryc - (%ry-1);
	%rzl = %rzc - (%rz-1);
	%rxh = %rxc + (%rx-1);
	%ryh = %ryc + (%ry-1);
	%rzh = %rzc + (%rz-1);
	
	// generate box by brick's rom volume
	%boxs = vectorScale((%rx/4 - 1/4) SPC (%ry/4 - 1/4) SPC (%rz/10 - 1/10), 2);
	
	// for each brick in the scan box, add all of its volume to data array
	initContainerBoxSearch(%rpos, %boxs, $TypeMasks::FxBrickObjectType);
	while(isObject(%tbrick = containerSearchNext())) {
		if(%tbrick.isRaycasting()) {
			// compute target stud box
			%tdata = %tbrick.getDatablock();
			%tx = (%tbrick.angleId%2==0) ? %tdata.brickSizeX : %tdata.brickSizeY;
			%ty = (%tbrick.angleId%2==0) ? %tdata.brickSizeY : %tdata.brickSizeX;
			%tz = %tdata.brickSizeZ;
			%tpos = %tbrick.getPosition();
			%txl = getWord(%tpos, 0)* 4 - (%tx-1);
			%tyl = getWord(%tpos, 1)* 4 - (%ty-1);
			%tzl = getWord(%tpos, 2)*10 - (%tz-1);
			%txh = getWord(%tpos, 0)* 4 + (%tx-1);
			%tyh = getWord(%tpos, 1)* 4 + (%ty-1);
			%tzh = getWord(%tpos, 2)*10 + (%tz-1);
			
			// add each stud within volume overlap to array
			for(%x=lualogic_rom_max(%rxl, %txl); %x<=lualogic_rom_min(%rxh, %txh); %x+=2) { %xc = %x - %rxc;
			for(%y=lualogic_rom_max(%ryl, %tyl); %y<=lualogic_rom_min(%ryh, %tyh); %y+=2) { %yc = %y - %ryc;
				switch(%brick.angleId%4) {
					case 0: %xcr =  %xc; %ycr =  %yc;
					case 1: %xcr = -%yc; %ycr =  %xc;
					case 2: %xcr = -%xc; %ycr = -%yc;
					case 3: %xcr =  %yc; %ycr = -%xc;
				}
			for(%z=lualogic_rom_max(%rzl, %tzl); %z<=lualogic_rom_min(%rzh, %tzh); %z+=2) { %zc = %z - %rzc;
				%data_array[%xcr+0, %ycr+0, %zc+0] = 1;
			} } }
		}
	}
	
	// stringify array
	%data_str = "";
	%rxd = %data.logicRomX - 1;
	%ryd = %data.logicRomY - 1;
	%rzd = (%data.logicRomZ$="" ? 1 : %data.logicRomZ) - 1;
	for(%z=-%rzd; %z<= %rzd; %z+=2) { %plane_str = "";
	for(%y= %ryd; %y>=-%ryd; %y-=2) { %line_str  = "";
	for(%x=-%rxd; %x<= %rxd; %x+=2) {
		if(%data_array[%x+0, %y+0, %z+0]) {
			%line_str = %line_str @ "1";
		} else {
			%line_str = %line_str @ "0";
		}
	} %plane_str = %plane_str @ %line_str;
	} %data_str  = %data_str  @ %plane_str;
	}
	
	// send output
	//talk("rom" SPC %brick SPC %data_str);
	lualogic_sendinput(%brick, 1, %data_str);
}