-- -- Passenger -- Specialization for Passenger -- -- @author JoXXer -- @date 26/11/11 -- Passenger = {}; function Passenger.prerequisitesPresent(specializations) return SpecializationUtil.hasSpecialization(Steerable, specializations); end; function Passenger:load(xmlFile) -- Set passenger function self.setPassenger = SpecializationUtil.callSpecializationsFunction("setPassenger"); -- Nickname rendernode self.passengerNicknameRenderNode = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.passengerNicknameRenderNode#index")); self.passengerNicknameRenderNodeOffset = {0,0,0}; -- The passenger. He is the passenger, he rides and he rides. self.passengerPlayer = nil; -- The passengers name self.passengerName = ""; -- Passenger cameras. Yes, there can be more then two, but that requires modifications in the script. self.passengerCameras = {}; local passengerCameraName = string.format("vehicle.passengerCamera"); local passengerCamera = VehicleCamera:new(self); if passengerCamera:loadFromXML(xmlFile, passengerCameraName) then table.insert(self.passengerCameras, passengerCamera); end; -- Variable for inrangecheck self.inRangeOfVehicle = false; -- Variable to check if user is chatting, to prevent exit on InputBinding.ENTER-event self.isChatting = false; end; function Passenger:delete() for _, passengerCamera in ipairs(self.passengerCameras) do passengerCamera:delete(); end; end; function Passenger:readStream(streamId, connection) local passengerPlayerId = streamReadInt32(streamId); self.passengerName = streamReadString(streamId); if passengerPlayerId ~= -1 then self.passengerPlayer = networkGetObject(passengerPlayerId); end; end; function Passenger:writeStream(streamId, connection) if self.passengerPlayer ~= nil then streamWriteInt32(streamId, networkGetObjectId(self.passengerPlayer)); else streamWriteInt32(streamId, -1); end; streamWriteString(streamId, self.passengerName); end; function Passenger:readUpdateStream(streamId, timestamp, connection) end; function Passenger:writeUpdateStream(streamId, connection, dirtyMask) end; function Passenger:mouseEvent(posX, posY, isDown, isUp, button) end; function Passenger:keyEvent(unicode, sym, modifier, isDown) end; function Passenger:update(dt) if self.passengerPlayer ~= nil then self.passengerCameras[1]:update(dt); if self.passengerName == g_settingsNickname then if InputBinding.hasEvent(InputBinding.CHAT) and not self.isChatting then self.isChatting = true; end; if InputBinding.hasEvent(InputBinding.SEND_CHAT_MESSAGE) and self.isChatting then self.isChatting = false; end; if InputBinding.hasEvent(InputBinding.ENTER) and not self.isChatting then self.passengerCameras[1]:onDeactivate(); setCamera(self.passengerPlayer.cameraId); self:setPassenger("Exited", nil); end; local pcx, pcy, pcz = getRotation(self.passengerPlayer.cameraId); local prx, pry, prz = getRotation(self.passengerPlayer.graphicsRootNode); setRotation(self.passengerCameras[1].cameraNode, pcx, pry, 0); g_currentMission:addHelpButtonText(string.format(g_i18n:getText("EXIT_PASSENGERSEAT"), self.typeDesc), InputBinding.ENTER); end; if self.passengerPlayer ~= nil then if g_currentMission:getIsServer() then if g_currentMission.connectionsToPlayer[self.passengerPlayer.creatorConnection] == nil then self:setPassenger("Disconnected", nil); end; end; end; end; if self.passengerPlayer ~= nil then -- if player joins a vehicle, set passenger-spot not taken! if not self.passengerPlayer.isControlled and not self.passengerPlayer.isEntered then self:setPassenger("ExitedToOtherVehicle", nil); end; end; -- Manage key events for inrange -- if self.inRangeOfVehicle and self.passengerPlayer == nil and self.isControlled and g_settingsNickname ~= self.controllerName then g_currentMission:addHelpButtonText(string.format(g_i18n:getText("ENTER_PASSENGERSEAT"), self.typeDesc), InputBinding.ENTER); if InputBinding.hasEvent(InputBinding.ENTER) then self:setPassenger(g_settingsNickname, g_currentMission.player); self.passengerCameras[1]:onActivate(); end; end; end; function Passenger:updateTick(dt) if g_currentMission.player ~= nil then -- Getting the distance between the player and the implement local nearestDistance = 4.0; --max distance allowed local px, py, pz = getWorldTranslation(self.rootNode); local vx, vy, vz = getWorldTranslation(g_currentMission.player.rootNode); local distance = Utils.vector3Length(px-vx, py-vy, pz-vz); if distance < nearestDistance then self.inRangeOfVehicle = true; else self.inRangeOfVehicle = false; end; end; end; function Passenger:draw() -- Renders the passenger name for everyone except the passenger if g_settingsNickname ~= nil then if self.passengerName ~= g_settingsNickname and self.isControlled and self.passengerPlayer ~= nil and g_gui.currentGui == nil then local x,y,z = getWorldTranslation(self.passengerNicknameRenderNode); local x1,y1,z1 = getWorldTranslation(getCamera()) local distSq = Utils.vector3LengthSq(x-x1,y-y1,z-z1); if distSq <= 100*100 then x = x + self.passengerNicknameRenderNodeOffset[1]; y = y + self.passengerNicknameRenderNodeOffset[2]; z = z + self.passengerNicknameRenderNodeOffset[3]; local sx,sy,sz = project(x,y,z); if sz <= 1 then setTextAlignment(RenderText.ALIGN_CENTER); setTextBold(false); setTextColor(0.0, 0.0, 0.0, 0.75); renderText(sx, sy-0.0015, 0.02, self.passengerName); setTextColor(0.5, 1.0, 0.5, 1.0); renderText(sx, sy, 0.02, self.passengerName); setTextAlignment(RenderText.ALIGN_LEFT); end; end; end; end; end; function Passenger:onLeave() end; function Passenger:onEnter() end; function Passenger:setPassenger(passengerName, passengerPlayer, noEventSend) SetPassengerEvent.sendEvent(self, passengerName, passengerPlayer, noEventSend); if passengerPlayer ~= nil then setTranslation(passengerPlayer.rootNode, 0, 0, 0); self.passengerName = passengerName; elseif passengerName == "Exited" then local exitX, exitY, exitZ = getWorldTranslation(self.exitPoint); setTranslation(self.passengerPlayer.rootNode, exitX, exitY+2, exitZ); self.passengerName = ""; else self.passengerName = ""; end; self.passengerPlayer = passengerPlayer; end; -- Passenger on enter event-class SetPassengerEvent = {}; SetPassengerEvent_mt = Class(SetPassengerEvent, Event); InitEventClass(SetPassengerEvent, "SetPassengerEvent"); function SetPassengerEvent:emptyNew() local self = Event:new(SetPassengerEvent_mt); self.className="SetPassengerEvent"; return self; end; function SetPassengerEvent:new(vehicle, passengerName, passengerPlayer) local self = SetPassengerEvent:emptyNew() self.vehicle = vehicle; self.passengerName = passengerName; self.passengerPlayer = passengerPlayer; return self; end; function SetPassengerEvent:readStream(streamId, connection) local id = streamReadInt32(streamId); local passengerPlayerId = streamReadInt32(streamId); self.passengerName = streamReadString(streamId); self.vehicle = networkGetObject(id); self.passengerPlayer = networkGetObject(passengerPlayerId); self:run(connection); end; function SetPassengerEvent:writeStream(streamId, connection) streamWriteInt32(streamId, networkGetObjectId(self.vehicle)); streamWriteInt32(streamId, networkGetObjectId(self.passengerPlayer)); streamWriteString(streamId, self.passengerName); end; function SetPassengerEvent:run(connection) self.vehicle:setPassenger(self.passengerName, self.passengerPlayer, true); if not connection:getIsServer() then g_server:broadcastEvent(SetPassengerEvent:new(self.vehicle, self.passengerName, self.passengerPlayer), nil, connection, self.vehicle); end; end; function SetPassengerEvent.sendEvent(vehicle, passengerName, passengerPlayer, noEventSend) if noEventSend == nil or noEventSend == false then if g_server ~= nil then g_server:broadcastEvent(SetPassengerEvent:new(vehicle, passengerName, passengerPlayer), nil, nil, vehicle); else g_client:getServerConnection():sendEvent(SetPassengerEvent:new(vehicle, passengerName, passengerPlayer)); end; end; end;