Stationskommando / Task nur einmal erlauben

Hier ist der ideale Ort um über Scripts und Mods für X³: Terran Conflict und X³: Albion Prelude zu diskutieren.

Moderators: Moderatoren für Deutsches X-Forum, Scripting / Modding Moderators

Post Reply
darkangel666
Posts: 525
Joined: Mon, 16. Feb 09, 13:57
xr

Stationskommando / Task nur einmal erlauben

Post by darkangel666 » Thu, 18. Nov 10, 10:35

Hallo an alle.

Also ich habe folgendes Problem:
Ich habe ein Stationskommando welches nur einmal aufrufbar sein soll. Das Kommando ist ein endlosscript. Jetzt möchte ich aber das dieses Kommando pro station nur einmal aufgerufen werden kann.

Ich habe folgende Abfrage im Script:

Code: Select all

* Stationstasks 1 - 10
$task.min = 10
$task.max = 19

$task.curr = $task.min
* Scanne ob Script aktiv
while $task.curr <= $task.max
  if [THIS] -> is script MeinSkript on stack of task= $task.curr
* Wenn ja script beenden und meldung ausgeben
     display subtitle text: text= 'Kommando auf dieser station schon aktiv' duration= 7000 ms
     return [FALSE]
  end
  * nächstes Kommando 'scannen'
  inc $task.curr =
end
* Wenn script nicht aktiv dann starte

...(scriptcode)
So allerdings kommt jetzt das Problem. Ich insgesamt 3 solcher scripts. Bei jedem steht jeweils der eigene Scriptname drinnen. Aber es kann immer nur Script1 gestartet werden. Die anderen beiden Scripts unterbrechen an der Stelle 'Kommando auf dieser station schon aktiv' obwohl sie gar nicht aktiv sind. Und Script 1 lässt sich beliebig oft starten. Was mach ich falsch :'(

|K.O.S.H.
Posts: 3724
Joined: Fri, 19. Dec 03, 10:36
x3tc

Post by |K.O.S.H. » Thu, 18. Nov 10, 10:55

ich kann dir die frage nicht direkt beantworten, aber eine alternative anbieten.

benutze einen mutex als lokale variabel auf der station.

also (in pseudocode):

Code: Select all

mutex_name = "my_mutex";

mutex_value = get.local.var(mutex_name);

if (mutex_value == 1) 
{
return 0;  //return if script is running
}                  
else
{
$station.set.local.var(mutex_name, 1);
//your code
//e.g. while(true)
$station.set.local.var(mutex_name, 0);
return 0;
}

also ne lokale var setzen und gucken ob sie 1/true/sonstwas != NULL ist.
falls ja: script beenden, falls nein, die var auf 1 setzen udn script starten.


edit:
das ganze hat ein paar vorteile:
-performanter, da nur eine var gecheckt wird
-einfacher, da man sich nicht mit dem stack rumschlagen muss
-fast idiotensicher(außer du setzt die lokale var in einem anderen script)
-von außen kontrollierbar(nämlich wenn du die var in nem anderen script setzt ;))
Wing Commander Mod - German Topic
06.07.11 - v1.1 RELEASED!

darkangel666
Posts: 525
Joined: Mon, 16. Feb 09, 13:57
xr

Post by darkangel666 » Thu, 18. Nov 10, 11:04

naja aber wenn ich in der Endlosschleife die lokale var (in dem sinne jetzt mutex ;) ) auf 0 zurücksetze wird das script ja wieder ausführbar. ^^'

Oder wird die endlosschleife bei manuellem abbruch im Kommandomenü automatisch beendet? Wenn ja könnte ich mutex nach der schleife auf 0 setzen. wenn dem dann nicht so ist kann das script nur einmal aufgerufen werden und nach beendigung nie wieder ^^'

EDIT:

Funktioniert so weit ganz gut nur das Script wird komplett abgebrochen. Wenn ich die lokale var in der schleife zurücksetz dann ist das script ja wieder "startbar". Und wenn nicht dann kann das Kommando nur ein einziges Mal gestartet werden und dann nie wieder. Es soll nur einmal laufen aber nicht 1 mal startbar sein ;)

User avatar
ScRaT_GER
Posts: 1962
Joined: Tue, 8. Jan 08, 18:19
x3tc

Post by ScRaT_GER » Thu, 18. Nov 10, 11:17

naja aber wenn ich in der Endlosschleife die lokale var (in dem sinne jetzt mutex Wink ) auf 0 zurücksetze wird das script ja wieder ausführbar. ^^'
Ja, aber warum solltest du das machen? Der Mutex gibt ja nur an, ob das Skript momentan läuft oder nicht. D.h. du setzt die lokale Variable nach der Schleife zu null.
Das einzige Problem ist, dass der Mutex nicht wieder geöffnet wird (also die lokale Variable auf null gesetzt wird), wenn man das Kommando manuell abbricht oder durch ein anderes ersetzt.
Aus diesem Grund würde ich ein Watcher-Skript auf irgendeinem hohen Task laufen lassen, das überprüft, ob das Skript noch läuft und ggf. die Variable auf null setzt damit man es wieder aufrufen kann. Dieses Watcher-Skript wird dann einfach am Anfang des Hauptskripts gestartet und beendet sich selbst wieder, wenn das Hauptskript nicht mehr läuft.

Ansonsten finde ich deinen Stack-Ansatz gar nicht schlecht und eigentlich sollte er auch gut funktionieren. Warum es das bei dir nicht tut, weiß ich allerdings nicht.
Wenn du das ganze in ein Check-Skript packst, kannst du sogar dafür sorgen, dass das Kommando gar nicht aufrufbar ist, wenn das Skript läuft.

MfG,
ScRaT

darkangel666
Posts: 525
Joined: Mon, 16. Feb 09, 13:57
xr

Post by darkangel666 » Thu, 18. Nov 10, 11:27

ach verdammt^^ fehler gefunden^^
Wenn ich in dem Skript abfrage ob das Script schon läuft ist es klar das da immer true rauskommt...

EDIT:
Habs jetzt so gelöst:

Code: Select all

* Stationstasks 1 - 10
$task.min = 10
$task.max = 19
$running = get local variable name = 'LOCALE'
$task.curr = $task.min
* Scanne ob Script aktiv
while $task.curr <= $task.max
  if $running
    if [THIS] -> is script MeinSkript on stack of task= $task.curr
       * Wenn ja script beenden und meldung ausgeben
       [THIS] -> set locale variable: name='LOCALE' value=null
       display subtitle text: text= 'Kommando auf dieser station schon aktiv' duration= 7000 ms
       return [FALSE]
    end
  end
  * nächstes Kommando 'scannen'
  inc $task.curr =
end
* Wenn script nicht aktiv dann starte
[THIS] -> set locale variable: name='LOCALE' value=[TRUE]
...(scriptcode) 

EDIT2:

Werds aber mit externem Watch-Script machen. Erscheint mir irgendwie sinnvoller. Aber danke für die schnelle Hilfe^^

( Das ich da nicht selber drauf gekommen bin... :roll: )

User avatar
Gazz
Posts: 13244
Joined: Fri, 13. Jan 06, 16:39
x4

Post by Gazz » Thu, 18. Nov 10, 11:46

Geht aber auch viel einfacher.

Statt das Script "direkt" zu starten, gibst du ihm ein PRELOAD script.

Das startet dann zuerst und ohne einen Stationstask zu belegen. Da werden auch alle Argumente eingegeben genauso als ob es das eigentliche Script wäre.
Wenn alles OK ist und das Script so gestartet werden kann, guckt das preload script erstmal nach, ob "das" Script schon auf einem Stationstask läuft.
Wenn ja, wird vom preload script genau dieser task mit dem eigentlichen Script überschrieben.

Mit einem so kontrollierten Start kann das Script nur 1x gestartet werden und ein watcher script wird niemals gebraucht.

Die MARS Frachtbergung wird z.B. so gestartet.
Es gibt ja nur zwei slots für "besondere Schiffsbefehle". Die sind schnell belegt.
Wenn also gerade keiner frei ist und jemand trotzdem die Frachtbergung starten möchte, dann wird das preload script das eigentliche script starten - aber eben auf task 4895723 oder so.
So gibts keinen Ärger mit den knapp bemessenen slots und natürlich prüft das Script auch, ob die FB schon auf einem dieser slots läuft...
My complete script download page. . . . . . I AM THE LAW!
There is no sense crying over every mistake. You just keep on trying till you run out of cake.

darkangel666
Posts: 525
Joined: Mon, 16. Feb 09, 13:57
xr

Post by darkangel666 » Thu, 18. Nov 10, 11:52

Sprich das Preloadscript übernimmt alle Parameter und jedes Untermenü für die Scripts? Und nur die Hauptroutinen in der Schleife werden als seperates Script mit den Parametern gestartet?

EDIT:
Das Stationskommando soll aber auch in der Liste auftauchen.
Ich bräuchte also sozusagen für jedes Script ein Preloadscript. Das is ja nicht so schwer zu realiesieren^^ und das Watchscript entfällt :)
Ich glaub so mach ichs^^

User avatar
Gazz
Posts: 13244
Joined: Fri, 13. Jan 06, 16:39
x4

Post by Gazz » Thu, 18. Nov 10, 12:08

darkangel666 wrote:Sprich das Preloadscript übernimmt alle Parameter und jedes Untermenü für die Scripts? Und nur die Hauptroutinen in der Schleife werden als seperates Script mit den Parametern gestartet?
Im Prinzip ja.
darkangel666 wrote:Ich bräuchte also sozusagen für jedes Script ein Preloadscript.
Hast du praktisch schon.

Du kopierst dein aktuelles Script und aus dem einen machst du das Hauptscript, aus dem anderen (mit Menüs und Kram) das Preload zum Starten.
Wenn du dadurch mehr als 5 Argumente übergeben mußt, na und? Dann wird eben nur ein Argument übergeben... ein Array mit beliebig vielen Elementen.

Ist ne geradlinige und sichere Sache und watcher scripts (die ja auch irgendwie überwacht werden müssen und so wartungsintensiv sind) gibts nicht.

darkangel666 wrote:Das Stationskommando soll aber auch in der Liste auftauchen.
set script command

Nur bei manuellem Start wird der Scriptname automatisch angezeigt.
My complete script download page. . . . . . I AM THE LAW!
There is no sense crying over every mistake. You just keep on trying till you run out of cake.

darkangel666
Posts: 525
Joined: Mon, 16. Feb 09, 13:57
xr

Post by darkangel666 » Thu, 18. Nov 10, 12:28

Wie bekomm ich jetzt durch das preload-script den Kommandoname in die liste? die bleibt jetzt irgendwie leer :(

EDIT:

Habs gerad im vorherigen Post gelesen^^

EDIT2:

Irgendwie erkennt der die Scripte im Stack nicht mehr. Sprich die können schon wieder mehr als 1x gleichzeitig ausgeführt werden...

Hätte evtl jemand einen sample code für mich? Wäre euch echt dankbar. :)
Bin so langsam am verzweifeln.

EDIT3:

So hab Fehler entdeckt.^^ Is eig recht dumm das zu übersehen aber naja...bastel ja schon seit 6 Stunden XD
Da ich mit dem exscriptor gearbeitet hab sind in den Scripts ein paar Schreibfehler aufgetreten. Und X3 ist anscheinend sehr pingelig was Groß- und Kleinschreibung angeht.^^
Last edited by darkangel666 on Thu, 18. Nov 10, 14:37, edited 1 time in total.

User avatar
Gazz
Posts: 13244
Joined: Fri, 13. Jan 06, 16:39
x4

Post by Gazz » Thu, 18. Nov 10, 14:36

darkangel666 wrote:Irgendwie erkennt der die Scripte im Stack nicht mehr. Sprich die können schon wieder mehr als 1x gleichzeitig ausgeführt werden...
Wie das jetzt? Und du prüfst schon sicher das richtige Objekt...?
My complete script download page. . . . . . I AM THE LAW!
There is no sense crying over every mistake. You just keep on trying till you run out of cake.

darkangel666
Posts: 525
Joined: Mon, 16. Feb 09, 13:57
xr

Post by darkangel666 » Thu, 18. Nov 10, 14:44

Naja hab mitm Exscriptor aus versehen bei den scriptnamen statt 'cmd' 'Cmd' geschrieben. Und X3 ist da pingelig und sieht das als anderes Script an.^^

|K.O.S.H.
Posts: 3724
Joined: Fri, 19. Dec 03, 10:36
x3tc

Post by |K.O.S.H. » Thu, 18. Nov 10, 17:08

nur ein kurzer kommentar meienrseits zu meinem vorschlag:
natürlich sollst du nicht in de rwhile schleife den mutex wieder auf 0 setzen, sondern danach ;)

ich dachte das wäre logisch.
bei while(true) gibts halt kein danach.
Wing Commander Mod - German Topic
06.07.11 - v1.1 RELEASED!

User avatar
Lucike
Posts: 12969
Joined: Sun, 9. May 04, 21:26
x4

Post by Lucike » Thu, 18. Nov 10, 17:20


Also ich finde die erste Variante am besten. Diese Schleife läuft ja auch nur dann, wenn der Spieler tatsächlich einen Slot wählt. Mein Vorschlag:

Code: Select all

001   $TaskID = get task ID
002   
003   $While = 20
004   while $While > 10
005   |dec $While = 
006   |skip if not $While == $TaskID
007   ||continue
008   |skip if not [THIS] -> is script '!init.set.modified' on stack of task=$While
009   ||return null
010   end
011   
012   * Script-Code
013   
014   return null
Eigentlich ähnlich, wie der Code von darkangel666.

Gruß
Lucike
Image

User avatar
ScRaT_GER
Posts: 1962
Joined: Tue, 8. Jan 08, 18:19
x3tc

Post by ScRaT_GER » Thu, 18. Nov 10, 19:07

001 $TaskID = get task ID
002
003 $While = 20
004 while $While > 10
005 |dec $While =
006 |skip if not $While == $TaskID
007 ||continue
008 |skip if not [THIS] -> is script '!init.set.modified' on stack of task=$While
009 ||return null
Wozu die Schleife, wenn du sowieso nur überprüftst, wenn $While == $TaskID? Da kannst du auch gleich die Schleife weglassen und nur die $TaskID überprüfen.

MfG,
ScRaT

UniTrader
Moderator (Script&Mod)
Moderator (Script&Mod)
Posts: 14571
Joined: Sun, 20. Nov 05, 22:45
x4

Post by UniTrader » Thu, 18. Nov 10, 19:16

das siehst du genau falsch:

er überprüft alle Tasks, aber überspringt dabei den Task auf dem das Script selber läuft (würde sich ja sonst immer beim start beenden ; skip if not == einzeiliges if ;) von Gazz deswegen auch zu do if umbenannt ^^) und das continue bedeutet nicht, dass die Schleife unterbrochen wird sondern dass sie nochmal von vorne anfängt (oder sich beendet, wenn die bedingungen nicht mehr zutreffen)
if not stated otherwise everything i post is licensed under WTFPL

Ich mache keine S&M-Auftragsarbeiten, aber wenn es fragen gibt wie man etwas umsetzen kann helfe ich gerne weiter ;)

I wont do Script&Mod Request work, but if there are questions how to do something i will GLaDly help ;)

darkangel666
Posts: 525
Joined: Mon, 16. Feb 09, 13:57
xr

Post by darkangel666 » Sat, 20. Nov 10, 08:09

Ich finds eig hauptsächlich schade das man bei der stacküberprüfung immer den name des scripts übergeben muss als parameter und nicht einfach ne string-variable. so könnte man z.B. das script so verallgemeinern, dass es als einzige lib existiert und wenn der task abgefragt weden soll ob er läuft oder nicht dann bräuchte man nur die lib aufrufen und den scriptname als parameter übergeben. Also in etwa so:

lib.task.running

Code: Select all


* Stationstasks 1 - 10
$task.min = 10
$task.max = 19

$task.curr = $task.min
* Scanne ob Script aktiv
while $task.curr <= $task.max
  if [THIS] -> is script $script on stack of task= $task.curr
* Wenn ja script beenden und meldung ausgeben
     display subtitle text: text= 'Kommando auf dieser station schon aktiv' duration= 7000 ms
     return [FALSE]
  end
  * nächstes Kommando 'scannen'
  inc $task.curr =
end 
return [FALSE]
und das statiosnsscript

station.cmd.test
lib.task.running

Code: Select all


skip if not [THIS] -> call script 'lib.task.running' : scriptname='Scriptblabla'
  return null

* (scriptcode)...
Das wäre doch mal noch was für nen neuen patch für ego XD
Und nebenbei können sie gleich noch die Kollisionsabfrage für Formationsflüge verbessern, dass die schiffe nich mehr eiern. Und die Andockmanöver für Aldrin/Torus könnten auch verbessert werden. :roll:

Jaja ich weiß, Spieler und ihre Sonderwünsche *feix*


Nebenbei kennt eig jemand den genauen aufbau der 00749.bod? Spiel mit dem Gedanken einen Editor dafür zu schreiben und natürlich auch für alle User bereitzustellen ;)

Post Reply

Return to “X³: Terran Conflict / Albion Prelude - Scripts und Modding”