Hello, I'm trying to make working pit stops on my map. I want to use LUA triggers to repair vehicle when trigger is entered. First I tried this: Code: local function trigger_repair(data) print("Trigger activated. Event: " .. tostring(data.event)) -- Debugging line if data.event == 'enter' then print("Player entered the trigger.") -- Debugging line be:reloadVehicle(-1) -- Reloads the player's vehicle print("Vehicle reloaded!") -- Debugging line end end return trigger_repair It works (like clicking Ctrl+R), but the problem is it does it to every vehicle on map. Then I tried to get vehicle ID and to reload only the one that entered the trigger Code: local function trigger_repair(data) print("Trigger activated. Event: " .. tostring(data.event)) -- Debugging line if data.event == 'enter' then print("Player entered the trigger.") -- Debugging line local vid = be:getPlayerVehicleID(0) -- Get player's vehicle ID if vid then local vehicle = scenetree.findObjectById(vid) -- Get vehicle object from ID if vehicle then print("Vehicle found. ID: " .. tostring(vid)) -- Debugging line be:reloadVehicle(vid) -- Reload only the player's vehicle print("Vehicle reloaded!") -- Debugging line else print("Vehicle object not found!") -- Debugging line end else print("No valid player vehicle ID found!") -- Debugging line end end end return trigger_repair And the problem with this code it that it does nothing. It works without an error and the debugging lines in console display as if everything has worked out, but it has no effect on players vehicle. Code: 7669.236|I|GELua.print|Trigger activated. Event: enter 7669.236|I|GELua.print|Player entered the trigger. 7669.236|I|GELua.print|Vehicle found. ID: 33986 7669.236|I|GELua.print|Vehicle reloaded! Any ideas?
I just did a bit of testing. The following code seems to work: Spoiler: Code Code: local function resetVehicle(data) if data.event == "enter" then local vehid = data.subjectID if vehid == be:getPlayerVehicleID(0) then be:reloadVehicle(0) -- reloads player vehicle end end end return resetVehicle The only issue is that the vehicle gets stuck in a reset loop. You would need a variable that changes value when the player enters the trigger and prevents the reset until the player exits the trigger. Spoiler: Code Code: isPlayerInTrigger = false local function resetVehicle(data) if data.event == "enter" then if not isPlayerInTrigger then isPlayerInTrigger = true local vehid = data.subjectID if vehid == be:getPlayerVehicleID(0) then be:reloadVehicle(0) end end end if data.event == "exit" then isPlayerInTrigger = false end end return resetVehicle However, that doesn't seem to work with just one lua trigger. I think the reason is that reloading the vehicle counts as exiting the trigger. If you use two triggers (one for reset/pitstop, the other for registering the exit) that call functions from mainLevel.lua, it does work. The mainLevel.lua is needed to save the state of wether the player was inside the pit stop or not, as this info cannot be passed between triggers afaik. So, the code for your reset trigger could look like this: Spoiler: Code Code: local function test(data) mainLevel.resetVehicle(data) end return test When exiting the pit stop, a trigger with the following code is entered: Spoiler: Code Code: local function test(data) mainLevel.exitPit() end return test And the code inside the mainLevel.lua that is called could look like this: Spoiler: Code Code: local M = {} local isPlayerInPit = false local function resetVehicle(data) if data.event == "enter" then if not isPlayerInPit then isPlayerInPit = true local vehid = data.subjectID if vehid == be:getPlayerVehicleID(0) then be:reloadVehicle(0) -- reloads player vehicle (0 => vehicle the player is currently using) end end end end local function exitPit() isPlayerInPit = false end M.resetVehicle = resetVehicle M.exitPit = exitPit return M I just experimented myself, so there might be better solutions. I hope it's helpful anyway
Thanks a lot! I've tweaked things a bit, I've used 2 lua triggers as you can see in this screenshot For vehicle reload - Yellow - "pit1" After player enters it, vehicle reloads and trigger "pit1" hides to prevent looping when player restarts vehicle. Code: local isPlayerInPit = false local function trigger_reset(data) if data.event == "enter" then if not isPlayerInPit then -- Ensures the vehicle only resets once per entry isPlayerInPit = true local vehid = data.subjectID if vehid == be:getPlayerVehicleID(0) then be:reloadVehicle(0) -- Reloads the player's vehicle only local pit1 = scenetree.findObject("pit1") if pit1 then pit1:setHidden(true) end end end end end return trigger_reset The purple one - "exit_pit" for unhiding "pit1" so player can reload vehicle again Code: local function exit_pit(data) if data.event == "enter" then local obj = scenetree.findObject("pit1") if obj then obj:setHidden(false) end end end return exit_pit (red triggers are for decoration) Here is vid demonstration:
That's a cool idea to make a pit stop repair! Have you figured out all your logic for how to deal with the trigger? I've coded a few in my stuff. There are "enter", "exit" and "tick" possible values in data.event. Something fun to consider would be to use a check on vehicle velocity combined with delay timer/update so you only perform the vehicle reload once the vehicle comes to a stop, and then only after a certain amount of time has elapsed, to similar a repair time. If you knew how much damage was on the vehicle then you could vary the delay time before reload. I don't want to just throw out a bunch of code snippets at you, so just ask if you have a specific task about this.
Thanks a lot for the "be:reloadVehicle(0)" line! That's exactly what I was looking for . Some additional thoughts: If you'd like to start the action only if the vehicle comes to stop, you have to use a ticking trigger, cause obviously a vehicle cannot enter a trigger with zero speed. So for this cases I have two triggers, with the same position and size. One of them is ticking. Since a ticking tirigger can't send enter/exit events, there has to be the second one to recognize the exit event. So the logic is to check by the ticking trigger if the player vehicle has zero speed (and thus must be in the trigger) and a dedicated flag variable signals "place clear". The action whatever needed (refill or repair) is then processed and the flag variable is set to "place occupied". If the player drives on this is recognized by the second trigger and the flag variable is set to "place clear" again, what means the place is ready for a new action. There is a random delay between the moment the player stopped (of course in the trigger) and the action is started depending on the (absolute) ticking time. If you give the ticking trigger a relatively long time (e.g. 2sec), the delay will be from 0 to 2sec by chance and this feels quite realistic, imo. The advantage to realize the "place (is) clear" logic by an exit event instead of testing if the speed of the player rises again is that it is proof to recognize any irregular disappearing of the vehicle, for example by a map or [F7] jump or by removing the car. How to check the speed: Code: vehObj = be:getObjectByID(data.subjectID) -- Convert trigger subject into vehicle object airspeed = vehObj:getVelocity():length() -- in m/s Hope I wrote something useful --- Post updated --- BTW: Does anyone know how to test if the player vehicle is the unicycle (avatar)?
Thank you, that's very useful! I didn't know about ticking triggers before You can test for the unicycle using the following code: Code: if core_vehicle_manager.getPlayerVehicleData().mainPartName == "unicycle" then -- some code end -- alternative, works for non-player vehicles as well, if you have their id -- local vehicle = getPlayerVehicle(0) if core_vehicle_manager.getVehicleData(vehicle:getId()).mainPartName == "unicycle" then -- some code end You can also use this to test for specific vehicles, eg. "us_semi", "etk800" or "simplified_traffic". Edit: I did some testing myself and my ticking triggers can send enter/exit events I use the following order of if-statements: if data.event == "enter" ... elseif data.event == "exit" ... elseif data.event == "tick" It might not work if you have the "tick"-query first, as I think the tick-event is always sent. It also works if I put the tick-query first.