--- добавлено позже в 06 авг 2015, 22:44 ---
Стандартные сценарии West Highland Line (South) доступны для скачивания. Забираем, проверяем, наслаждаемся стандартным режимом

CrossCross писал(а):Света
наша тема выходит за рамки той, в которой ведём диалог. Так что этот вопрос можно обсудить в теме с патчами для ПС. Знания языка C и C++ здесь желательны, так как они наиболее похожи на Lua.
1) да, локальные переменные можно создавать.
2) на счёт этого не понял. Как бы просто пишется скрипт, задаются функции и условия, потом проверяется всё на локомотиве.
3) что за программное прерывание?
4) вообще нужен хороший скриптёр!
Код: Выделить всё
function Update(time)
if (counter==101)then
counter = 1
else
counter = counter + 1
end
end
Код: Выделить всё
function OnControlValueChange (name, index, value)
if Call("*:ControlExists", name, index) then
Call("*:SetControlValue", name, index, value)
end
if (name == "CabLight") then
if(value == 1) then
...
if (counter < porog) then //если значение счетчика меньше заданного порога, то при
//включении света в кабине произойдет поломка. Если значение
//порога будет 12, то вероятность "поломки" будет 1:12
Call("команда, по которой инициируется "поломка")
end
...
Call("Light_Cab:Activate", 1)
else
Call("Light_Cab:Activate", 0)
end
elseif(name == "PriborLight") then
if(value == 1) then
Call("Pribor_Light:Activate", 1)
else
Call("Pribor_Light:Activate", 0)
end
end
end
понятно, значит код скрипта компилятор подключает к основному коду и считывание происходит циклично.Cross писал(а): есть дополнительные пользовательские функции, которые пишутся уже в скрипте
Ничего, я думаю, что суть мне понятнаCross писал(а): при срабатывании той самой DSD и срыве стоп крана (при заданных условиях) мы уже имеем возможность двигать ручку тяги, ибо она не блокируется никогда, но параметр Regulator бы не реагировал, то есть двигай ручку как угодно, а тяги не будет. Затем, при определённых условиях мы возвращаем связь виртуальной функции и базы и всё снова работает. Фух, сложно объяснил? Увлёкся малость.
Я вижу, что в lua понятия "прерывание" нет, но это и неудивительно. Если Вам знакомо понятие "флаги" в программировании и интересно, то я смогу объяснить, что это. Для скриптования, судя по всему, это не нужно.Cross писал(а): программное прерывание - это вызов по событиям или триггеру, заданному программой (например, совпадение нескольких условий). Здесь мне не всё ясно до конца.
Тогда мой метод очень просто может реализовать непредсказуемость. Например, при прохождении триггера сверяется значение счетчика, и если оно ниже порога, начинается обратный отсчет этого значения. По истечении этого отсчета происходит поломка, характер которой, опять-таки может определяться значением счетчика. Фактически, одной переменной, можно сделать случайными место, время, характер поломки, и саму поломку. А, ну может понадобиться ещё одна защитная переменная-диспетчер. А значение счетчика по-любому будет случайным, ведь при инкрементировании 20-30 раз в секунду он тысячи раз успеет переполниться до прохождения триггераCross писал(а): ... эти триггеры размещаются в сценариях в заданных местах и таким образом можно организовать любую гадость машинисту, но такой способ я не хочу практиковать никак, ибо он слишком линейный, а хочется непредсказуемости.
Мне очень хочется внести какой-нибудь вклад в сим. Если мне удастся хоть как-то помочь, это будет замечательноCross писал(а): Света
Если вы готовы мне помочь в скриптовке локомотивов и таким образом в разработке патчей, то я буду только рад и очень рекомендую изучить каждый патч в плане скриптов и поглядеть как и что там устроено. Ваши примеры близки к правде и должны работать в игре
Код: Выделить всё
function Initialise ()
FaultTime = math.random (60, 36000)
FaultOccured = 0 -- позволяет проследить, чтобы неисправность не случилась дважды
end
function Update (time)
if FaultOccured == 0 then
if time == FaultTime then
Call (-- неисправность)
FaultOccured = 1
end
end
end
написанием скриптов и можете помочь) Речь не идёт о полном написании с нуля, здесь важны только сложные моменты, когда таковые появятся, а они обязательно будут. Вот сейчас остался нерешённым вопрос о блокировке управления у Class 47, когда пищит DSD. Пока что можно сбросить тормоз в ноль одним касанием кнопки и работать с тягой. Как мне пояснил pROssO, при срабатывании DSD по прошествии нескольких секунд, если не нажать на педаль, то блокируется управление тягой (ручку можно дёргать, а эффекта на базовую функцию от неё ноль), затем срабатывает экстренный тормоз (также ручку тормоза можно дёргать, но сама базовая функция не будет реагировать). Далее условие на разблокировку управления. Мы должны нажать педаль DSD, чтобы деактивировать пищалку и перевести виртуальный тормоз в положение "экстренный", а затем в положение "отпустить", тогда управление снова активируется. Я ломал голову, но не пришёл к результату.Главный вопрос - чем конкретно я могу помочь?
Код: Выделить всё
function Initialise ()
PreviousFaultTime = 0
FaultTimer = math.random (60, 36000)
end
function Update (time)
if time == PreviousFaultTime + FaultTimer then
Call (-- неисправность)
PreviousFaultTime = time
FaultTimer = math.random (60, 36000)
end
end
Код: Выделить всё
--------------------------------------------------------------------------------------
-- Engine Script for Class 47
--
-- (c) Railsimulator.com 2011
--
-- Provides script for variable exhaust smoke.
-- Animates cooling vents based on RPM.
--
--------------------------------------------------------------------------------------
-- maximum tractive effort for determining smoke density. Acceleration rate for AI.
MAXTE = 0.5
ACCELRATE = 0.25
gSmokeColourR = 1.0
gSmokeColourG = 1.0
gSmokeColourB = 1.0
gEmitRate = 0.05
-------------------------------------------------------------------------------------
function Initialise ()
-- Get emitter values.
gSmokeColourR, gSmokeColourG, gSmokeColourB = Call( "Exhaust:GetEmitterColour" )
-- Stores for checking when values have changed.
gDriven = 0
-- Stores for vent positions.
gFrontVent = 0
gBackVent = 0
isPlayerLoco = false
isExpert = false
DSDDELAY = 60
gDSDStartCount = 0
gDSDStopCount = 0
isDSDTriggered = false
isSafetyIsolated = false
isReverserDSDReset = true
gReverserDSDTimer = 0
gRunningTime = 0
gReverserState = 0
gRegulator = 0
gBrakeState = 0
aws_warn_time = 0
prev_aws = 0
prev_awsreset = 0
gAWSReady = true
gAWSTesting = false
Call( "BeginUpdate" )
end
-------------------------------------------------------------------------------------
function OnControlValueChange ( name, index, value )
if Call( "*:ControlExists", name, index ) then
Call( "*:SetControlValue", name, index, value );
end
-- Virtual Function and DSD if Player is loco and Expert mode
if isPlayerLoco and isExpert then
-- DSD Disable/Enable
if name == "SafetyIsolation" then
if value == 1 then
isSafetyIsolated = true
alert("Class 47", "DSD Disabled", 1)
end
if value == 0 then
isSafetyIsolated = false
alert("Class 47", "DSD Enabled", 1)
end
gDSDStartCount = 0
end
-- Visual Alarms Enabled/Disabled
--if name == "VisualAlarms" then
--
-- if value == 1 then
-- alert("Visual Alarms", "Enabled", 1)
-- end
-- if value == 0 then
-- alert("Visual Alarms", "Disabled", 1)
-- end
--end
if name == "VirtualReverser" then
if value == 0 then
gReverserState = -1
elseif value == 1 then
gReverserState = 0
elseif value == 2 then
gReverserState = 1
end
Call( "*:SetControlValue", "Reverser", 0, gReverserState )
if (value == 2 or value < 0.5) and isReverserDSDReset and gRunningTime > gReverserDSDTimer then
if isSafetyIsolated == false then
Call( "*:SetControlValue", "DSD", 0, 1 )
elseif isSafetyIsolated == true then
Call( "*:SetControlValue", "DSD", 0, 0 )
end
isReverserDSDReset = false
elseif value == 1 and isReverserDSDReset == false then
Call( "*:SetControlValue", "DSD", 0, 0 )
isReverserDSDReset = true
gReverserDSDTimer = gRunningTime
end
end
if name == "VirtualThrottle" then
gRegulator = Call( "*:GetControlValue", "VirtualThrottle", 0)
Call( "*:SetControlValue", "Regulator", 0, gRegulator )
end
if name == "VirtualBrake" then
gBrakeState = Call( "*:GetControlValue", "VirtualBrake", 0)
Call( "*:SetControlValue", "TrainBrakeControl", 0, gBrakeState )
end
if name == "DSDPedal" then
Call( "*:SetControlValue", "DSD", 0, 0 )
gDSDStartCount = 0
end
--If the alarm is enabled DSD, while the countdown timer is stopped
if name == "AWSReset" or name == "Horn" or name == "Bell" or name == "VirtualThrottle" or name == "VirtualReverser" then
if Call( "*:GetControlValue", "DSD", 0) == 1 then
if gDSDStartCount > DSDDELAY then
gDSDStopCount = 0
end
elseif Call( "*:GetControlValue", "DSD", 0) == 0 then
gDSDStartCount = 0
end
end
end
-- Engine Control
if name == "EngineStart" then
if value > 0.5 then
Call( "*:SetControlValue", "Startup", 0, 1 )
end
end
if name == "EngineStop" then
if value > 0.5 then
Call( "*:SetControlValue", "Startup", 0, -1 )
end
end
end
-------------------------------------------------------------------------------------
function Update ( time )
gRunningTime = gRunningTime + time
if Call( "GetIsPlayer" ) == 1 then
isPlayerLoco = true
else
isPlayerLoco = false
end
if Call( "IsExpertMode" ) == 1 then
isExpert = true
else
isExpert = false
end
if isPlayerLoco and isExpert then
DriverSafetyDevice (time)
end
-- Cab Lights/ Cab Lights for AI.
if Call("*:GetControlValue", "CabLight", 0) == 1 then
Call( "CabLight_Front_01:Activate", 1)
Call( "CabLight_Front_02:Activate", 1)
Call( "CabLight_Front_03:Activate", 1)
Call( "CabLight_Rear_01:Activate", 1)
Call( "CabLight_Rear_02:Activate", 1)
Call( "CabLight_Rear_03:Activate", 1)
else
Call( "CabLight_Front_01:Activate", 0)
Call( "CabLight_Front_02:Activate", 0)
Call( "CabLight_Front_03:Activate", 0)
Call( "CabLight_Rear_01:Activate", 0)
Call( "CabLight_Rear_02:Activate", 0)
Call( "CabLight_Rear_03:Activate", 0)
end
if isPlayerLoco == false then
Call( "CabLight_Front_01:Activate", 0)
Call( "CabLight_Front_02:Activate", 0)
Call( "CabLight_Front_03:Activate", 0)
Call( "CabLight_Rear_01:Activate", 0)
Call( "CabLight_Rear_02:Activate", 0)
Call( "CabLight_Rear_03:Activate", 0)
end
-- AWS Extended.
if isExpert then
local warncount = Call("GetControlValue", "AWSWarnCount", 0)
local my_awsreset = Call("GetControlValue", "MyAWSReset", 0)
local aws = Call("GetControlValue", "AWS", 0)
local aws_warn = 0
-- delay AWS horn.
if warncount == 1 then
aws_warn_time = aws_warn_time + time
if aws_warn_time > 1 then
aws_warn = 1
else
aws_warn = 0
end
else
prev_aws = aws
aws_warn_time = 0
aws_warn = 0
end
Call("SetControlValue", "MyAWSWarnCount", 0, aws_warn)
-- cancel AWS only on release of the button.
if my_awsreset == 0 and prev_awsreset ~= 0 and aws_warn == 1 then
Call("SetControlValue", "AWSReset", 0, 1)
else
Call("SetControlValue", "AWSReset", 0, 0)
end
prev_awsreset = my_awsreset
-- AWS Self Test.
if Call( "*:GetControlValue", "Reverser", 0) ~= 0 and gAWSReady == true then
gAWSTesting = true
Call("*:SetControlValue", "AWSWarnCount", 0, 1)
Call("*:SetControlValue", "AWS", 0, 0)
gAWSReady = false
end
if Call( "*:GetControlValue", "AWSReset", 0) > 0.9 and gAWSReady == false and gAWSTesting == true then
Call("*:SetControlValue", "AWSWarnCount", 0, 0)
Call("*:SetControlValue", "AWSClearCount", 0, 1)
Call("*:SetControlValue", "AWS", 0, 1)
gAWSTesting = false
end
end
-- Check for player train.
if Call( "GetIsPlayer" ) == 1 then
-- Check if player is driving this engine.
if ( Call( "GetIsEngineWithKey" ) == 1 ) then
if gDriven == 0 then
gDriven = 1
Call( "*:SetControlValue", "Active", 0, 1 )
end
else
if gDriven == 1 then
gDriven = 0
Call( "*:SetControlValue", "Active", 0, 0 )
end
end
-- Get tractive effort values for this vehicle.
TractiveEffort = Call ( "GetTractiveEffort" )
TractiveEffort = math.abs ( TractiveEffort )
else -- This is an AI train.
-- Tractive effort doesn't work for AI, so use acceleration.
Accel = Call( "GetAcceleration" )
Speed = Call( "GetSpeed" )
-- Unfortunately acceleration is signed based on direction loco is facing (sic).
if Speed < 0 then
Accel = Accel * -1
end
if Accel > ACCELRATE then
TractiveEffort = MAXTE
elseif ( math.abs(Speed) > 1 ) and ( Accel > -0.1 ) then
TractiveEffort = MAXTE/2
else
TractiveEffort = MAXTE/11
end
end
-- Get rpm value for this vehicle.
rpm = Call( "*:GetControlValue", "RPM", 0 )
-- Adjust exhaust smoke based on tractive effort.
if TractiveEffort < MAXTE/10 then
gSmokeColourR = 0.8
gSmokeColourG = 0.8
gSmokeColourB = 0.8
Call ( "Exhaust:SetEmitterColour", gSmokeColourR, gSmokeColourG, gSmokeColourB )
Call ( "Exhaust:SetEmitterRate", gEmitRate )
end
if ( TractiveEffort <= MAXTE/2 ) and ( TractiveEffort >= MAXTE/10 ) then
gSmokeColourR = 0.25
gSmokeColourG = 0.25
gSmokeColourB = 0.25
Call ( "Exhaust:SetEmitterColour", gSmokeColourR, gSmokeColourG, gSmokeColourB )
Call ( "Exhaust:SetEmitterRate", 0.01 )
end
if TractiveEffort > MAXTE/2 then
gSmokeColourR = 0.0
gSmokeColourG = 0.0
gSmokeColourB = 0.0
Call ( "Exhaust:SetEmitterColour", gSmokeColourR, gSmokeColourG, gSmokeColourB )
Call ( "Exhaust:SetEmitterRate", 0.005 )
end
-- Vent animations.
if rpm < 220 then
if gFrontVent == 1 then
if ( Call( "*:AddTime", "FrontVents", -time ) ~= 0 ) then
gFrontVent = 0
end
end
if gBackVent == 1 then
if ( Call( "*:AddTime", "BackVents", -time ) ~= 0 ) then
gBackVent = 0
end
end
elseif ( rpm >= 220 ) and ( rpm <= 600 ) then
if gFrontVent == 0 then
if ( Call( "*:AddTime", "FrontVents", time ) ~= 0 ) then
gFrontVent = 1
end
end
if gBackVent == 1 then
if ( Call( "*:AddTime", "BackVents", -time ) ~= 0 ) then
gBackVent = 0
end
end
else -- RPM must be greater than 600
if gFrontVent == 0 then
if ( Call( "*:AddTime", "FrontVents", time ) ~= 0 ) then
gFrontVent = 1
end
end
if gBackVent == 0 then
if ( Call( "*:AddTime", "BackVents", time ) ~= 0 ) then
gBackVent = 1
end
end
end
end
function alert(title, str, time)
SysCall("ScenarioManager:ShowAlertMessageExt", title, str, time, 1)
end
function DriverSafetyDevice (time)
-- If the reverser is in neutral then disable DSD
if Call( "*:GetControlValue", "Reverser", 0) == 0 then
isDSDTriggered = false
return
end
-- If DSD warning has been active for 5 seconds with no response then cut power and trigger emergency brake
if gDSDStartCount > DSDDELAY + 5 and not isDSDTriggered and not isSafetyIsolated then
isDSDTriggered = true
Call( "*:SetControlValue", "EmergencyBrake", 0, 1 )
Call( "*:SetControlValue", "Regulator", 0, 0 )
Call( "*:SetControlValue", "Reverser", 0, 0 )
-- If DSD timer has expired then sound DSD alarm
elseif gDSDStartCount > DSDDELAY and not isSafetyIsolated then
Call( "*:SetControlValue", "DSD", 0, 1 )
end
-- DSD alarm off when DSD isolated
if isSafetyIsolated == true and Call( "*:GetControlValue", "DSD", 0) == 1 then
Call( "*:SetControlValue", "DSD", 0, 0 )
end
-- Increment DSD timer
gDSDStartCount = gDSDStartCount + time
end