-- LUA für realistisches Partikelsystem am Auspuff
-- basiert im Grundsatz dynamicExhaustSystem.lua von Face bzw. dessen Shader ausm dem Kirovets K 700A
--
-- by modelleicher
-- www.schwabenmodding.bplaced.net
-- V3 konvertiert zum LS13, Performanceoptimierung und Code aufgeräumt
-- Kommentare in Englisch
-- LUA for realistic exhaust particles. Based on the DynamicExhaustingSystemShader.xml from Face
-- V3 converted to FS13, performance optimized and cleaned the code, also added english comments


realExhaustParticleSystemV3 = {};

function realExhaustParticleSystemV3.prerequisitesPresent(specializations)
    return SpecializationUtil.hasSpecialization(Motorized, specializations);
end;

function realExhaustParticleSystemV3:load(xmlFile)
	self.reps = {}; -- real exhaust particle system table.
	self.reps.minAlpha = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.realExhaustParticleSystem#minAlpha"), 0.1);
	self.reps.maxAlpha = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.realExhaustParticleSystem#maxAlpha"), 1);
	self.reps.parameter = Utils.getNoNil(getXMLString(xmlFile, "vehicle.realExhaustParticleSystem#parameter"), "exhaustingSystem");
	self.reps.realAlpha = self.reps.minAlpha; -- current alpha value
	self.reps.isAcc = false; -- bool is accelerating
	self.reps.accBackup = self.motor.minRpm + 150; -- value needet for acceleration true/false check
	-- new in V3, optional second particleSystem for better looking, but lower performance
	self.reps.hasSecondPS = getXMLBool(xmlFile, "vehicle.realExhaustParticleSystem#hasSecondPS");
	if self.reps.hasSecondPS == true then
		self.reps.secondPS = {};
		Utils.loadParticleSystem(xmlFile, self.reps.secondPS, "vehicle.realExhaustParticleSystem.SecondParticleSystem", self.components, false, nil, self.baseDirectory)
		self.reps.secondPSOn = false;
		self.reps.secondPS_minAlpha = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.realExhaustParticleSystem.SecondParticleSystem#minAlpha"), 0.8);
		self.reps.secondPS_maxAlpha = Utils.getNoNil(getXMLFloat(xmlFile, "vehicle.realExhaustParticleSystem.SecondParticleSystem#maxAlpha"), 1.0);
	end;	
	
	self.reps.flap = getXMLString(xmlFile, "vehicle.realExhaustParticleSystem#flap");
	if self.reps.flap ~= "" and self.reps.flap ~= nil then
		self.reps.flap = Utils.indexToObject(self.components, self.reps.flap);
		self.reps.flapMaxRot = getXMLFloat(xmlFile, "vehicle.realExhaustParticleSystem#flapMaxRot");
	end;
	
	--self.axisF_read = 0;
	self.reps.realAlpha_read = 0;
end;

function realExhaustParticleSystemV3:delete()
	if self.reps.secondPS ~= nil then
		Utils.deleteParticleSystem(self.reps.secondPS);
	end;
end;

function realExhaustParticleSystemV3:readUpdateStream(streamId, timestamp, connection)
--print("function realExhaustParticleSystemV3:readUpdateStream("..tostring(streamId)..", "..tostring(timestamp)..", "..tostring(connection));
	if connection.isServer then
		self.reps.realAlpha_read = streamReadFloat32(streamId);
	end;
end;

function realExhaustParticleSystemV3:writeUpdateStream(streamId, connection, dirtyMask)
	if not connection.isServer then
		streamWriteFloat32(streamId, self.reps.realAlpha);
	end;
end;

function realExhaustParticleSystemV3:mouseEvent(posX, posY, isDown, isUp, button)
end;

function realExhaustParticleSystemV3:keyEvent(unicode, sym, modifier, isDown)
end;

function realExhaustParticleSystemV3:update(dt)
end;


function realExhaustParticleSystemV3:updateTick(dt)

	if self.isMotorStarted and self:getIsActive() and self.isServer then

		
		local lastRPM = self.motor.lastMotorRpm;
		--if lastRPM == 0 and self.motor.lastMotorRpm_read ~= 0 then
		--	lastRPM = self.motor.lastMotorRpm_read;
		--end;		
		
		-- check if tractor is accelerating
		if self.reps.accBackup < lastRPM then
			self.reps.isAcc = true;
		elseif self.reps.accBackup > lastRPM then
			self.reps.isAcc = false;
		end;
		self.reps.accBackup = lastRPM;

		-- acc 0 , 1 means if key for acceleration is pressed, or 0 to 1 float for pedal axis
		--local acc = self.axisForward; 	-- value is sync'ed by default (vehicle.lua)
		--if acc == 0 and self.axisF_read ~= 0 then
		local acc = self.axisForward; --axisF_read;
		--end;
		--acc = -InputBinding.getAnalogInputAxis(InputBinding.AXIS_MOVE_FORWARD_VEHICLE);
		--if InputBinding.isAxisZero(acc) then
		--	acc = -InputBinding.getDigitalInputAxis(InputBinding.AXIS_MOVE_FORWARD_VEHICLE);
		--end;		
		-- speedLevels 1,2,3,4:
		local increaseAlpha = nil;
		
		local spdLvl = self.motor.speedLevel;
		--if spdLvl == 0 and self.motor.speedLevel_read ~= 0 then
		--	spdLvl = self.motor.speedLevel_read;
		--end;
		
		if spdLvl == 1 then
			if lastRPM < (self.motor.maxRpm[1] - 100) then
				increaseAlpha = true;
			else
				increaseAlpha = false;
			end;
		elseif spdLvl == 2 then
			if lastRPM < (self.motor.maxRpm[2] - 200) then
				increaseAlpha = true;
			else
				increaseAlpha = false;
			end;
		elseif spdLvl == 3 then
			if lastRPM < (self.motor.maxRpm[3] - 250) then
				increaseAlpha = true;
			else
				increaseAlpha = false;
			end;
		elseif spdLvl == 4 then
			if lastRPM < (self.motor.maxRpm[4] - 150) then		
				increaseAlpha = true;
			else
				increaseAlpha = false;
			end;
		end;
		
		--print("-> "..tostring(self.axisForward).."   "..tostring(self.motor.speedLevel).."   "..tostring(self.motor.lastMotorRpm).."   "..tostring(self.reps.realAlpha) );

		-- if no speedlevel active
		if spdLvl == 0 then
			if self.reps.isAcc == true then -- only more alpha if accelerating
				self.reps.realAlpha = math.min(self.reps.maxAlpha, self.reps.realAlpha + 0.005);
				self.reps.secondPSOn = true;
			elseif self.reps.isAcc == false then
				self.reps.realAlpha = math.max(self.reps.minAlpha, self.reps.realAlpha - 0.005);	
				self.reps.secondPSOn = false;
			end;
			-- if acc == 1 means full power but not full speed, also more alpha
			if acc == 1 then
				if lastRPM < (self.motor.maxRpm[3] - 250) then 
					increaseAlpha = true;
				else
					self.reps.secontPSOn = false;
				end;
			end;
		end;
		
		-- calculate current alpha value
		if increaseAlpha == true then
			self.reps.realAlpha = math.min(self.reps.maxAlpha, self.reps.realAlpha + 0.005);
			--self.reps.secondPSOn = true;		
		elseif increaseAlpha == false then
			self.reps.realAlpha = math.max(self.reps.minAlpha, self.reps.realAlpha - 0.005);	
			--self.reps.secondPSOn = false;			
		end;
	end;
	
	
	
	if self.isMotorStarted and self:getIsActive() and self.isClient then
	
		-- do flap animation, if flap is there
		if self.reps.flap ~= "" and self.reps.flap ~= nil then
			setRotation(self.reps.flap, Utils.degToRad(math.min(self.reps.flapMaxRot*0.2, self.reps.flapMaxRot*(self.motor.lastMotorRpm / 2000))));
		end;	
		
		local alpha = self.reps.realAlpha_read;
		if alpha == 0 and self.reps.realAlpha ~= 0 then
			alpha = self.reps.realAlpha;
		end;
	
		-- if secondPS is active
		if self.reps.hasSecondPS then
			--if self.reps.secondPSOn then
			--if alpha > (self.reps.maxAlpha * 0.6) then
			if (alpha > self.reps.secondPS_minAlpha) and (alpha < self.reps.secondPS_maxAlpha) then
				Utils.setEmittingState(self.reps.secondPS, true);
			else
				Utils.setEmittingState(self.reps.secondPS, false)
			end;
		end;
		-- set new alpha value to the shader
		setShaderParameter(self.exhaustParticleSystems[1].shape, self.reps.parameter, 0, 0, 0, alpha, false);		
	else
		if self.reps.flap ~= "" and self.reps.flap ~= nil then
			setRotation(self.reps.flap, 0, 0, 0);
		end;
	end;
end;

function realExhaustParticleSystemV3:onLeave()
	if self.reps.hasSecondPS then
		Utils.setEmittingState(self.reps.secondPS, false);
	end;
end;

function realExhaustParticleSystemV3:draw()
end;
