BalloonWheels im Multiplayer sichtbar machen :/

  • Hi,


    ich habe seit längerem das BalloonWheel Script raus welches auf Basis der LUA Video Tuts entstand.
    Leider habe ich damit ein Problem.


    Im Multiplayer kann ich als Host die Balloon Reifen einschalten und sehen aber als Client nicht.


    Ich habe mir zu dem Thema mal einige andere Scripts angeguckt (Einblendung, toggleAnimatedParts u.s.w).
    Wenn ich das richtig verstehe muss man ein Event einbauen ähnlich wie das hier:


    [lua]Setblends1Event = {};
    Setblends1Event_mt = Class(Setblends1Event, Event);
    InitEventClass(Setblends1Event, "Setblends1Event");
    function Setblends1Event:emptyNew()
    local self = Event:new(Setblends1Event_mt);
    self.className="Setblends1Event";
    return self;
    end;
    function Setblends1Event:new(object, active)
    local self = Setblends1Event:emptyNew()
    self.active = active;
    self.object = object;
    return self;
    end;
    function Setblends1Event:readStream(streamId, connection)
    local id = streamReadInt32(streamId);
    self.active = streamReadBool(streamId);
    self.object = networkGetObject(id);
    self:run(connection);
    end;
    function Setblends1Event:writeStream(streamId, connection)
    streamWriteInt32(streamId, networkGetObjectId(self.object));
    streamWriteBool(streamId, self.active);
    end;
    function Setblends1Event:run(connection)
    self.object:setblends1Visibility(self.active, true);
    if not connection:getIsServer() then
    g_server:broadcastEvent(Setblends1Event:new(self.object, self.active), nil, connection, self.object);
    end;
    end;[/lua]


    Leider habe ich keine Ahnung wie das bei mir aussehen müsste. ;(
    Hier mal das aktuelle Script:


    [lua]balloonWheels = {};


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


    function balloonWheels:load(xmlFile)
    self.wheelToBalloonRearLeft = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.balloonWheels.wheelToBalloonRearLeft#index"));
    self.wheelToBalloonRearRight = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.balloonWheels.wheelToBalloonRearRight#index"));
    self.wheelToBalloonFrontLeft = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.balloonWheels.wheelToBalloonFrontLeft#index"));
    self.wheelToBalloonFrontRight = Utils.indexToObject(self.components, getXMLString(xmlFile, "vehicle.balloonWheels.wheelToBalloonFrontRight#index"));

    self.bwRLX, self.bwRLY, self.bwRLZ = getScale(self.wheelToBalloonRearLeft);
    self.bwRRX, self.bwRRY, self.bwRRZ = getScale(self.wheelToBalloonRearRight);
    self.bwFLX, self.bwFLY, self.bwFLZ = getScale(self.wheelToBalloonFrontLeft);
    self.bwFRX, self.bwFRY, self.bwFRZ = getScale(self.wheelToBalloonFrontRight);

    self.bwTRLX, self.bwTRLY, self.bwTRLZ = getTranslation(self.wheelToBalloonRearLeft);
    self.bwTRRX, self.bwTRRY, self.bwTRRZ = getTranslation(self.wheelToBalloonRearRight);
    self.bwTFLX, self.bwTFLY, self.bwTFLZ = getTranslation(self.wheelToBalloonFrontLeft);
    self.bwTFRX, self.bwTFRY, self.bwTFRZ = getTranslation(self.wheelToBalloonFrontRight);

    self.balloonWheelsWidth = getXMLFloat(xmlFile, "vehicle.balloonWheels#wheelWidth");
    self.balloonWheelsAxleDiv = getXMLFloat(xmlFile, "vehicle.balloonWheels#axleDiv");
    self.isSelectable = true
    self.balloonWheelsState = false;
    end;


    function balloonWheels:delete()
    end;


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


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


    function balloonWheels:update(dt)
    if self:getIsActiveForInput() then
    if InputBinding.hasEvent(InputBinding.BALLOONWHEELS) then
    self.balloonWheelsState = not self.balloonWheelsState;
    end;

    if self.balloonWheelsState == true then
    setScale(self.wheelToBalloonRearLeft, (self.bwRLX / 100) + self.balloonWheelsWidth, self.bwRLY ,self.bwRLZ);
    setScale(self.wheelToBalloonRearRight, (self.bwRRX / 100) + self.balloonWheelsWidth, self.bwRRY ,self.bwRRZ);
    setScale(self.wheelToBalloonFrontLeft, (self.bwFLX / 100) + self.balloonWheelsWidth, self.bwFLY ,self.bwFLZ);
    setScale(self.wheelToBalloonFrontRight, (self.bwFRX / 100) + self.balloonWheelsWidth, self.bwFRY ,self.bwFRZ);

    setTranslation(self.wheelToBalloonRearLeft, self.bwTRLX + self.balloonWheelsAxleDiv, self.bwTRLY, self.bwTRLZ);
    setTranslation(self.wheelToBalloonRearRight, self.bwTRRX - self.balloonWheelsAxleDiv, self.bwTRRY, self.bwTRRZ);
    setTranslation(self.wheelToBalloonFrontLeft, self.bwTFLX + self.balloonWheelsAxleDiv, self.bwTFLY, self.bwTFLZ);
    setTranslation(self.wheelToBalloonFrontRight, self.bwTFRX - self.balloonWheelsAxleDiv, self.bwTFRY, self.bwTFRZ);

    elseif self.balloonWheelsState == false then
    setScale(self.wheelToBalloonRearLeft, self.bwRLX, self.bwRLY ,self.bwRLZ);
    setScale(self.wheelToBalloonRearRight, self.bwRRX, self.bwRRY ,self.bwRRZ);
    setScale(self.wheelToBalloonFrontLeft, self.bwFLX, self.bwFLY ,self.bwFLZ);
    setScale(self.wheelToBalloonFrontRight, self.bwFRX, self.bwFRY ,self.bwFRZ);

    setTranslation(self.wheelToBalloonRearLeft, self.bwTRLX, self.bwTRLY, self.bwTRLZ);
    setTranslation(self.wheelToBalloonRearRight, self.bwTRRX, self.bwTRRY, self.bwTRRZ);
    setTranslation(self.wheelToBalloonFrontLeft, self.bwTFLX, self.bwTFLY, self.bwTFLZ);
    setTranslation(self.wheelToBalloonFrontRight, self.bwTFRX, self.bwTFRY, self.bwTFRZ);

    end;
    end;
    end;


    function balloonWheels:draw()
    if self.balloonWheelsState then
    g_currentMission:addHelpButtonText(g_i18n:getText("BALLOONOFF"), InputBinding.BALLOONWHEELS);
    else
    g_currentMission:addHelpButtonText(g_i18n:getText("BALLOONON"), InputBinding.BALLOONWHEELS);
    end;
    end;


    function balloonWheels:loadFromAttributesAndNodes(xmlFile, key, resetVehicles)
    local balloonWheelsState = getXMLBool(xmlFile, key.."#balloonWheelsState");
    if balloonWheelsState ~= nil then
    self.balloonWheelsState = balloonWheelsState;
    end;
    return BaseMission.VEHICLE_LOAD_OK;
    end;


    function balloonWheels:getSaveAttributesAndNodes(nodeIdent)
    local attributes = ""
    if self.balloonWheelsState ~= nil then
    attributes = ' balloonWheelsState="'.. tostring(self.balloonWheelsState) ..'"';
    end;
    return attributes, nil;
    end;


    function balloonWheels:onLeave()
    end;
    [/lua]


    Ich hoffe ihr könnt mir da weiter helfen.


    Lg
    Webby

  • Hi,
    Also alos erstes musst du mal eine Funkticon anlegen, damit das ganze funktioniert, hier dazu mal etwas von modelleicher: http://planet-ls.de/board/inde…&postID=204622#post204622


    Wie du die Function nennst, ist vollkommen egal, ich nehme jetzt einfach mal balloonState. Als erstes musst du diese neue function auch registrieren, das machst du im load() Teil.
    [lua]self.balloonState = SpecializationUtil.callSpecializationsFunction("balloonState");[/lua]


    Diese function kannst du dann in deinem Skript aufrufen mit self:balloonState().


    Deinen Update() Teil muss man dann auch umschreiben, was auch eh sinnvoll ist, da du bei jedem updateDurchlauf deine Reifen scalierst und versetzt, was aber nur ein einziges mal notwendig ist. Hier hatte man das ganze auch in den Teil packen können wo du den Tastendruck und das ändern deiner Variablen durchführst. Dann würden deine Reifen nur einmal scaliert und versetzt und nicht bei jedem Durchlauf.
    Der Tastendruck ist soweit korrekt, nach dem umschalten der Variablen rufen wir die fuction auf wo wir die Räder scalieren und versetzen:
    [lua]function balloonWheels:update(dt)
    if self:getIsActiveForInput() then
    if InputBinding.hasEvent(InputBinding.BALLOONWHEELS) then
    self.balloonWheelsState = not self.balloonWheelsState;
    self:ballonState(self.balloonWheelsState);
    end;
    end;
    end;
    [/lua]
    mehr braucht es in deinem Skript im Update Teil auch gar nicht. Du siehst, wenn man die Taste drückt, wird der Status der Räder(true/false) geändert. Entweder false oder true, diesen boolean hat ja deine Variable self.balloonWheelsState, somit übergeben wir den boolean auch an die fuction, diese muss ja wissen ob der Status true oder false ist.
    Wenn du erst die fuction aufrufst und danach die Statusvariable änderst, dann wärst du immer in der falschen Reihenfolge. Ich rufe also mit
    self:ballonState(self.balloonWheelsState); die function auf, der wert wird in den klammern mit übergeben. Unsere fuction sieht dann im leeren Zustand erstmal so aus:
    [lua]function balloonWheels:ballonState(state, noEventSend)
    end;[/lua]
    state ist die Variable die wir in der function nutzen, diese ist entweder true oder false, je nachdem wie der self.ballonWheelsState ist. noEventSend brauchen wir um das Event zu senden.
    In der function scalieren und versetzen wir nun die Räder:


    [lua]function balloonWheels:ballonState(state, noEventSend)
    if not noEventSend then
    BalloonWheelsEvent.sendEvent(self, state, noEventSend) --// das Eventscript aufrufen um alle Mitspieler zu informieren //
    end;


    if state then
    setScale(self.wheelToBalloonRearLeft, (self.bwRLX / 100) + self.balloonWheelsWidth, self.bwRLY ,self.bwRLZ);
    setScale(self.wheelToBalloonRearRight, (self.bwRRX / 100) + self.balloonWheelsWidth, self.bwRRY ,self.bwRRZ);
    setScale(self.wheelToBalloonFrontLeft, (self.bwFLX / 100) + self.balloonWheelsWidth, self.bwFLY ,self.bwFLZ);
    setScale(self.wheelToBalloonFrontRight, (self.bwFRX / 100) + self.balloonWheelsWidth, self.bwFRY ,self.bwFRZ);

    setTranslation(self.wheelToBalloonRearLeft, self.bwTRLX + self.balloonWheelsAxleDiv, self.bwTRLY, self.bwTRLZ);
    setTranslation(self.wheelToBalloonRearRight, self.bwTRRX - self.balloonWheelsAxleDiv, self.bwTRRY, self.bwTRRZ);
    setTranslation(self.wheelToBalloonFrontLeft, self.bwTFLX + self.balloonWheelsAxleDiv, self.bwTFLY, self.bwTFLZ);
    setTranslation(self.wheelToBalloonFrontRight, self.bwTFRX - self.balloonWheelsAxleDiv, self.bwTFRY, self.bwTFRZ);

    elseif not state then
    setScale(self.wheelToBalloonRearLeft, self.bwRLX, self.bwRLY ,self.bwRLZ);
    setScale(self.wheelToBalloonRearRight, self.bwRRX, self.bwRRY ,self.bwRRZ);
    setScale(self.wheelToBalloonFrontLeft, self.bwFLX, self.bwFLY ,self.bwFLZ);
    setScale(self.wheelToBalloonFrontRight, self.bwFRX, self.bwFRY ,self.bwFRZ);

    setTranslation(self.wheelToBalloonRearLeft, self.bwTRLX, self.bwTRLY, self.bwTRLZ);
    setTranslation(self.wheelToBalloonRearRight, self.bwTRRX, self.bwTRRY, self.bwTRRZ);
    setTranslation(self.wheelToBalloonFrontLeft, self.bwTFLX, self.bwTFLY, self.bwTFLZ);
    setTranslation(self.wheelToBalloonFrontRight, self.bwTFRX, self.bwTFRY, self.bwTFRZ);
    end;
    end;[/lua]


    Als erstes prüfen wir ob ein Event gesendet werden muss/soll. Da wir nur den state übergeben ist noEventSend also false. Wenn du kein Event senden willst, müsstest du hier also beim aufrufen der function nicht nur den State übergeben, sondern zudem noch ein true dahinter, also so: self:ballonState(self.balloonWheelsState, true), denn würde in den function die abfrage wegen noEventSend also nicht durchlaufen. Aber wir wollen ja ein Event senden.


    Da wir ein true/false für den Status übergeben haben, prüft das Skript nun ob ein true oder false. Dann werden dementsprechend die Räder scaliert und versetzt.


    Das Eventskript sieht dann so aus:


    [lua]BalloonWheelsEvent = {};
    BalloonWheelsEvent_mt = Class(BalloonWheelsEvent, Event);


    InitEventClass(BalloonWheelsEvent, "BalloonWheelsEvent");
    --// diese Funktion wird von new() aufgerufen und erstellt ein leeres Event-Objekt //--
    function BalloonWheelsEvent:emptyNew()
    local self = Event:new(BalloonWheelsEvent_mt);
    self.className = "BalloonWheelsEvent";
    return self;
    end;


    --// die Funktion :new() wird von sendEvent() aufgerufen und liefert das befüllte Objekt zurück //--
    function BalloonWheelsEvent:new(object, state)
    local self = BalloonWheelsEvent:emptyNew(); --// das leere Objekt wird erstellt //--
    self.object = object; --// object ist in dem Falle dein Fahrzeug //--
    self.balloonWheelsState = state;
    return self;
    end;


    --// writeStream sendet die neuen Informationen raus und wurde von broadcastEvent ausgelöst //--
    function BalloonWheelsEvent:writeStream(streamId, connection)
    --// zuerst die ID vom Fahrzeug übergeben damit "der andere" weiss um welches Fahrzeug es geht //--
    streamWriteInt32(streamId, networkGetObjectId(self.object));
    --// dann die Daten übergeben.
    streamWriteBool(streamId, self.balloonWheelsState);
    end;


    --// readStream liest die neuen Infos wieder ein. //--
    function BalloonWheelsEvent:readStream(streamId, connection)
    --// auch hier erstmal die ID einlesen //--
    self.object = networkGetObject(streamReadInt32(streamId));
    --// dann die Daten. Wichtig ist, das hier die selbe Reihenfolge wie bei writeStream eingehalten wird!! //--
    self.balloonWheelsState = streamReadBool(streamId);
    --// im Anschluss muss natürlich mit den Daten nochwas angefangen werden //--
    self:run(connection);
    end;


    --// die funktion run() wird von readStream aufgerufen wenn neue Daten vorliegen //--
    function BalloonWheelsEvent:run(connection)
    --// als erstes werden die erhaltenen Daten an dein eigentliches Script übergeben //--
    --// dazu wird wieder die funktion ballonState ausgeführt so wie beim Tastendruck - nur eben beim Mitspieler //--
    self.object:ballonState(self.balloonWheelsState, true);


    --// wenn du die Daten nicht vom Server bekommen hast , dann wurde die funktion lokal aufgerufen //--
    --// in dem Falle wird das Statusupdate nochmal an den Server geschickt damit der es verteilt //--
    if not connection:getIsServer() then
    g_server:broadcastEvent(BalloonWheelsEvent:new(self.object, self.balloonWheelsState), nil, connection, self.object);
    end;
    end;


    --// die Funktion :sendEvent() rufst du von deiner Spezi auf. Sie wird die Funktion :new() auslösen --//
    function BalloonWheelsEvent.sendEvent(object, state, noEventSend)
    if noEventSend == nil or noEventSend == false then
    if g_server ~= nil then --// wenn du der Server bist, //--
    g_server:broadcastEvent(BalloonWheelsEvent:new(object, state), nil, nil, object); --// schickst du das ergebnis von :new() an alle //--
    else --// wenn du client bist, //--
    g_client:getServerConnection():sendEvent(BalloonWheelsEvent:new(object, state)); --// schickst du das ergebnis von :new() an den server //--
    end;
    end;
    end;
    [/lua]
    die Erklärungen in grün stammen von Sven777b.


    Das Eventskript kannst du nun entweder unter dein Skript drunterkopieren, oder du speicherst es als extra lua ab und lädst sie dann in der moddesc über extraSourceFiles!


    Das ganze funktioniert dann zumindest in einer laufenden MP runde. Wenn nun aber ein neuer Spieler die Runde betritt, dann hat er immer den Status der Reifen, wie er sie durch das Skript/Savegame lädt. Sprich es kann dann sein das der neue Spieler immer den falschen Status sieht. Das kriegt man weg wenn man in deinem Skript noch ein readStream und writeStream einbaut, das wird immer beim joinen eines neuen Spielers aufgerufen.


    [lua]function balloonWheels:readStream(streamId, connection)
    self.balloonWheelsState = streamReadBool(streamId);
    self:ballonState(self.balloonWheelsState, true);
    end;


    function balloonWheels:writeStream(streamId, connection)
    streamWriteBool(streamId, self.balloonWheelsState);
    end;
    [/lua]
    im readStream liest der neue Spieler den Status, dann ruft er die function auf und übergibt der function auch den Status um den aktuellen Stand auf seine Räder zu übertragen, das true bedeutet nur das wir ein Event nicht senden brauchen, da die anderen Spieler den Status ja bereits haben.


    Da ich jetzt eh die hälfte kopiert habe, habe ich gleich mal alles zusammen kopiert zu einer lua. Brauchst hier in der moddesc keinen extraSourceFiles eintragen.
    Am besten kann man das ganze an Standart Skripten erkennen, als einfachstes Beispiel dient dazu mal die Honk.lua und die HonkEvent.lua
    http://www.ls-mods.de/scriptDo…cles/specializations/Honk
    http://www.ls-mods.de/scriptDo…specializations/HonkEvent



    Ich bin aber nun auch kein Profi, falls ich hier also etwas total falsches geschrieben habe, dann korregiert mich bitte.

  • Tja und wieder einmal falle ich vor Erfurcht auf die Knie.
    Super erklärt, werde das mal umsetzten und testen.


    Vielen Dank für deine Mühe. :thumbsup:


    Hier zeigt sich wieder mal sehr gut, das man auch die vermeintlich kompliziertesten Sache verstehen kann, wenn man es gut erklärt bekommt ;)


    Lg
    Webby

Jetzt mitmachen!

Sie haben noch kein Benutzerkonto auf unserer Seite? Registrieren Sie sich kostenlos und nehmen Sie an unserer Community teil!