Banner left   Banner center   Banner right

Germanenglish Home · News · Diary · Screenshots · Documentation (Wiki) · Downloads · Guestbook · Forum

Home · Benutzer registrieren · Suchen · Statistik · FAQ · Benutzerliste

Zur Zeit online: keiner ausser dir

 X-Force - Fight For Destiny - Forum —› X-Skript / Developer-Pack —› Abfragen ob ein bestimmtes Gebäude auf einer Basis existiert

Autor Mitteilung
verfasst am: 16.01.2010, 11:12 · Edited by: Kamor
Registrierdatum: 20.07.2005, 00:01

 Beiträge: 203
Ich will in einen Skript abfragen, ob ein bestimmtes Gebäude dort gebaut wurde. Habe dazu in TBASE das

RoomArray: Array of TRoom; read;

gefunden. Dies würde ich gerne nach meiner gewünschten GebäudeID durchsuchen, weiss aber nicht so genau, wie ich mit dem Typen Array hier hantieren muss. Ich finde keine Größe des Arrays, muss ich hier solange das Array durchsuchen, bis ich eine Endekennung (Nil) erreiche? Und naja, wenn ich ehrlich bin, kenne ich hier den Syntax auch nicht, um auf das Array dann per Index zuzugreifen.

Edit: Die Lösung per Event auf die Fertigstellung des Gebäudes zu reagieren, kommt für mich nicht in Frage, weil ich nicht sofort nach Fertigstellung des Gebäudes reagieren will, sondern zu einem späteren Zeitpunkt überprüfen muss, ob das Gebäude existiert.
verfasst am: 16.01.2010, 11:44
Registrierdatum: 12.06.2005, 11:08

 Beiträge: 465
Hm... Ich kenne mich zwar nicht so wirklich damit aus, aber könnte man bei Errichten des Gebäudes nicht eine globale Variable von False auf True setzen und später einfach überprüfen?

Wenn ich derbst auf dem Holzweg bin, entschuldige ich mich schon mal.
verfasst am: 16.01.2010, 12:29 · Edited by: Natter
Programmierer, allgemeines

Registrierdatum: 06.06.2004, 17:19

 Beiträge: 3186
Per Event würde das so auch nicht Funktionieren. Gebäude sind nur Records, keine Objekte und können daher auch nicht für Events genutzt werden. Es gibt daher nur ein SpecialEvent für den Gebäudebau - das wird aber für jedes Gebäude ausgelöst, und man muss immernoch selbst ermitteln, ob das gewünschte Gebäude gebaut wurde.

Zum Array - schau doch mal in unser Wiki.
http://doc.xforce-online.de/ger_pages/XSkriptTutorial/AnhangB.html
verfasst am: 16.01.2010, 12:37 · Edited by: Kamor
Registrierdatum: 20.07.2005, 00:01

 Beiträge: 203
Zitat: Jens Evering
Hm... Ich kenne mich zwar nicht so wirklich damit aus, aber könnte man bei Errichten des Gebäudes nicht eine globale Variable von False auf True setzen und später einfach überprüfen?

Wenn ich derbst auf dem Holzweg bin, entschuldige ich mich schon mal.


Jo, das hatte ich auch schon im Ansatz versucht. Wenn das Gebäude fertiggestellt ist, wird ein Flag gesetzt. Nur muss ich dann auch noch das Flag, wieder zurücksetzen, falls das Gebäude irgendwie wieder abgerissen oder zerstört wird. Wäre aber möglich, einfacher ginge es aber, wenn ich das Array einfach schnell nach meiner ID durchsuche. Brauche halt nur den Zugriffssyntax auf die Datenstruktur Array. Dann werde ich mich erstmal hier weiter vertiefen.
verfasst am: 16.01.2010, 13:16
Admin, Spielsatz GalWar

Registrierdatum: 31.08.2005, 21:51

 Beiträge: 5596
zusätzlich auch mal das hier versuchen, könnte auch helfen:-)

XSkriptReferenz.Getarraylength
verfasst am: 16.01.2010, 13:25 · Edited by: Kamor
Registrierdatum: 20.07.2005, 00:01

 Beiträge: 203
Zitat: DirkF
zusätzlich auch mal das hier versuchen, könnte auch helfen:-)

XSkriptReferenz.Getarraylength


Ja danke, habe jetzt erstmal den length(Array) Syntax gefunden, der scheint auch zu funktionieren. Direkt auf das Array of TRoom per Index zugreifen funktionierte irgendwie nicht, aber wenn ich eine Kopie des Arrays erstelle, kann ich sauber mit dem Index zugreifen. Hier der Code, der mir testweise alle Gebäude der Startbasis per Namen ausgibt. Damit komme ich weiter und kann meine Gebäude ID suchen.

procedure StartMission;
var
  i : Integer;
  Basis : TBase;
  Gebaeude : TRoom;
  Gebaeudearray : Array of TRoom;
begin
  Basis:=base_api_GetMainBase;
  Gebaeudearray:=Basis.RoomArray;
  if (length(Basis.RoomArray)>0) then
  begin
    for i := 0 to length(Basis.RoomArray)-1 do
    begin
      Gebaeude:=Gebaeudearray[i];
      savegame_api_Message(Gebaeude.Name,lmMissionMessage,Nil);
    end;
  end;
end;

verfasst am: 16.01.2010, 17:34
Admin, Spielsatz GalWar

Registrierdatum: 31.08.2005, 21:51

 Beiträge: 5596
Zitat: Kamor
length(Array) Syntax gefunden, der scheint auch zu funktionieren.

FALSCH!!!!!

length ist für Zeichenketten, nicht für Arrays - der liefert nur in Spezialfällen (Zeichenarrays, d.h. Arrays mit 1 Byte pro Datenwert) die korrekte Länge.

Für echte Arrays muss zwangsweise der getarraylength benutzt werden.

Bitte ändere das, auch wenn es auf den ersten Blick zu funktionieren scheint - das bringt sonst nur spätere Skripter durcheinander, und es ist auch nicht gesichert das die length()-Funktion immer den richtigen Wert zurückgeben wird.
verfasst am: 16.01.2010, 18:32
Registrierdatum: 16.07.2007, 16:03

 Beiträge: 86
sollte man nicht mit High(Array) den höchsten Index eines Arrays bekommen können?
verfasst am: 16.01.2010, 19:05 · Edited by: Kamor
Registrierdatum: 20.07.2005, 00:01

 Beiträge: 203
Ich habe den Befehl ausm Delphi-Treff

http://www.delphi-treff.de/sprachen/object-pascal/komplexe-datentypen/

der bezieht sich da schon ausdrücklich auf dynamische Arrays, also das der Probleme verursachen wird, kaufe ich dir nicht so ganz ab. Vielleicht wenn ihr irgendwann eure Arraystruktur soweit weg vom Originalpascal bringt und dort einen eigenen Arraytypen entwerft, dann vielleicht? ;-)

Zitat: DirkF
length ist für Zeichenketten, nicht für Arrays - der liefert nur in Spezialfällen (Zeichenarrays, d.h. Arrays mit 1 Byte pro Datenwert) die korrekte Länge.


Das stimmt nicht, er arbeitet auch mit mehr wie 1 Byte pro Datenwert, das zeigt auch mein funktionierendes Skript, mit einem Datenwert von mehreren Bytes für den Typen TRoom.

Ich habe mich mal in C++ sehr intensiv mit Arrays beschäftigt. Die bekommen auch nur Speicher zugewiesen und können dort auch alternativ zum Index über Pointer abgefragt werden, Pascal kennt auch Zeiger und dem zufolge müsste auch in Pascal der Zugriff über Zeiger auf Arrays kein Problem sein.
Das gleiche steht auch in der Delphiseite. Dem dynamischen Array in Pascal wird Speicher zugeordnet, der dem Maximum an möglichen Einträgen entspricht. Dabei berechnet sich der zugewiesene Speicher nach Maximum*Datensatzgröße. Die Funktion length ist nichts anderes, wie das Gegenstück zu SetLength(dynArray, Maximum), der das dynamische Array überhaupt erst anlegt.

Aber du hast recht, der Befehl ist nicht X-Scriptkonform und umgeht den X-Scriptsyntax und könnte später Skripter verwirren.

Aber was mache ich bei den Befehlen, wo X-Skript keine Alternative für hat, da gehe ich doch dann automatisch eine Ebene tiefer und bediene mich an den direkten Pascalelementen? X-Script ist nunmal auf der Basis von Pascal aufgebaut und mit den richtigen Kenntnissen kann ich wahrscheinlich mit ner Pointerprogrammierung auch über X-Scripte eure Arrays auslesen. ;-)
verfasst am: 16.01.2010, 19:09
Registrierdatum: 20.07.2005, 00:01

 Beiträge: 203
Zitat: Dragonblade
sollte man nicht mit High(Array) den höchsten Index eines Arrays bekommen können?


Ja hier bin ich auch noch am grübeln, laut Delphihilfe heisst es

high(dynArray) entspricht dem höchstmöglichen Index. Über length(a) lässt sich die Länge des Arrays ermitteln, welche immer high(dynArray)+1 ist. Dabei handelt es sich um den Wert, den man mit SetLength gesetzt hat.

Also im Prinzip müsste high nur um 1 Verschoben zum length sein?
verfasst am: 16.01.2010, 21:15
Admin, Spielsatz GalWar

Registrierdatum: 31.08.2005, 21:51

 Beiträge: 5596
Zitat: Kamor
Aber was mache ich bei den Befehlen, wo X-Skript keine Alternative für hat, da gehe ich doch dann automatisch eine Ebene tiefer und bediene mich an den direkten Pascalelementen? X-Script ist nunmal auf der Basis von Pascal aufgebaut und mit den richtigen Kenntnissen kann ich wahrscheinlich mit ner Pointerprogrammierung auch über X-Scripte eure Arrays auslesen. ;-)

X-Skript ist eine Modifikation von Pascal-Script, und schon Pascalskript unterstützt nicht die gesamte Delphi/Pascal-Syntax. Gerade bei den Arrays ist einiges von Jim_Raynor in X-Skript hinzuprogrammiert worden.

Du kannst nicht automatisch davon ausgehen das ein Pascal-Befehl auch in X-Skript funktioniert. Viele sind identisch, aber keineswegs alle. Und vor allen Dingen ist selbst Pascalscript kein kompletter Pascal-Compiler, d.h. viele indirekte Tricks sind nur mit sehr viel Vorsicht zu genießen.
verfasst am: 16.01.2010, 21:30
Registrierdatum: 20.07.2005, 00:01

 Beiträge: 203
Ja, glaube ich dir, war gerade auch am grübeln wegen Pascalskript und Pascal, ob meine Aussagen so alle richtig sind. Aber deine Aussage zum length, das der nur 1 Byte per Datenwert schafft war definitiv falsch und da musst ich einfach posten. ;-)

Werde ich dann ändern und die Pascalscriptfunktion dann nutzen anstatt die Pascalfunktion.
verfasst am: 16.01.2010, 23:59 · Edited by: Natter
Programmierer, allgemeines

Registrierdatum: 06.06.2004, 17:19

 Beiträge: 3186
Zum Thema length() in X-Script. Bevor hier irgendwelche Gerüchte entstehen, hier die Umsetzung von Length in der upsRuntime:
function Length_(Caller: TPSExec; p: TPSExternalProcRec; Global, Stack: TPSStack): Boolean;
var
  arr: TPSVariantIFC;
begin
  arr:=NewTPSVariantIFC(Stack[Stack.Count-2],false);
  case arr.aType.BaseType of
    btArray:
      begin
        Stack.SetInt(-1,PSDynArrayGetLength(Pointer(arr.Dta^),arr.aType));
        Result:=true;
      end;
    btStaticArray:
      begin
        Stack.SetInt(-1,TPSTypeRec_StaticArray(arr.aType).Size);
        Result:=true;
      end;
    btString:
      begin
        Stack.SetInt(-1,length(tbtstring(arr.Dta^)));
        Result:=true;
      end;
    {$IFNDEF PS_NOWIDESTRING}
    btWideString:
      begin
        Stack.SetInt(-1,length(tbtWidestring(arr.Dta^)));
        Result:=true;
      end;
    btUnicodeString:
      begin
        Stack.SetInt(-1,length(tbtUnicodeString(arr.Dta^)));
        Result:=true;
      end;
    {$ENDIF}
    btvariant:
      begin
        Stack.SetInt(-1,length(Variant(arr.Dta^)));
        Result:=true;
      end;
  else
    begin
      Caller.CMD_Err(ErTypeMismatch);
      result := true;
    end;
  end;
end;


Length ist also durchaus geeignet, um die Länge eines dyn. arrays zu bestimmen (und getarraylength macht auch nichts anderes - dort spart man sich nur die case-Abfrage, und geht gleich von einem Array aus). Einfacher ist natürlich trotzdem high().



Du musst dich registrieren um auf dieses Thema zu antworten.
Login :: » Name » Passwort

Ladezeit (sec.): 0.006 · Powered by miniBB 1.6 with parts of 1.7 © 2001-2003