Add C4PropList

A Proplist is a map of C4Strings to C4Values which can chain lookups
to "Prototype" Proplists. This can be used to implement inheritance.

Proplists can be stored in C4Values.

C4Object now inherits from C4Proplist, C4Values can be converted between
those two.
Günther Brammer 2009-05-20 00:12:11 +02:00
parent 6274cf7a5e
commit 42d3b6e79a
23 changed files with 455 additions and 127 deletions

View File

@ -390,7 +390,9 @@ clonk_SOURCES = \
engine/res/Picker.h \
engine/res/Play.h \
engine/res/Rect.h \
engine/res/Static.h
engine/res/Static.h \
engine/src/C4PropList.cpp \
engine/inc/C4PropList.h
if WIN32
clonk_SOURCES += engine/src/C4FileClasses.cpp

View File

@ -9,7 +9,7 @@ msgid ""
msgstr ""
"Project-Id-Version: Clonk Doku\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2009-05-15 20:27+0200\n"
"POT-Creation-Date: 2009-05-20 00:11+0200\n"
"PO-Revision-Date: 2008-05-30 14:30+0100\n"
"Last-Translator: matthes <matthes@clonk.de>\n"
"Language-Team: English\n"
@ -1219,6 +1219,7 @@ msgstr "Removes all objects."
#: sdk/script/fn/SetShape.xml:7(category)
#: sdk/script/fn/SetRDir.xml:7(category)
#: sdk/script/fn/SetR.xml:7(category)
#: sdk/script/fn/SetProperty.xml:7(category)
#: sdk/script/fn/SetPosition.xml:7(category)
#: sdk/script/fn/SetPortrait.xml:7(category)
#: sdk/script/fn/SetPicture.xml:7(category)
@ -1320,6 +1321,7 @@ msgstr "Removes all objects."
#: sdk/script/fn/GetRank.xml:7(category)
#: sdk/script/fn/GetRDir.xml:7(category)
#: sdk/script/fn/GetR.xml:7(category)
#: sdk/script/fn/GetProperty.xml:7(category)
#: sdk/script/fn/GetProcedure.xml:7(category)
#: sdk/script/fn/GetPortrait.xml:7(category)
#: sdk/script/fn/GetPhysical.xml:7(category)
@ -3008,6 +3010,31 @@ msgstr "Sets the rotation speed of an object."
msgid "Setzt die Drehung eines Objekts."
msgstr "Sets the rotation of an object."
#: sdk/script/fn/SetProperty.xml:7(subcat)
#: sdk/script/fn/GetProperty.xml:7(subcat)
#: sdk/particle/index.xml:154(h)
msgid "Eigenschaften"
msgstr "Properties"
#: sdk/script/fn/SetProperty.xml:12(desc)
#, fuzzy
msgid "Zu setzende Eigenschaft."
msgstr "Value to be set."
#: sdk/script/fn/SetProperty.xml:13(desc)
#, fuzzy
msgid "Wert, auf den die Eigenschaft gesetzt werden soll."
msgstr "Coordinate value to be set."
#: sdk/script/fn/SetProperty.xml:14(desc)
#, fuzzy
msgid "Objekt, das geändert wird. Null bei lokalem Aufruf."
msgstr "Object to be killed. Can be 0 in local calls."
#: sdk/script/fn/SetProperty.xml:17(desc)
msgid "Setzt die Eigenschaft <code>key</code> von <code>object</code> auf <code>value</code>. Die Eigenschaft muss vorher nicht existiert haben."
msgstr ""
#: sdk/script/fn/SetPosition.xml:7(subcat)
#: sdk/script/fn/SetObjectOrder.xml:8(subcat)
#: sdk/script/fn/ResortObjects.xml:7(subcat)
@ -4652,6 +4679,7 @@ msgstr "Call"
#: sdk/script/fn/SetCommand.xml:79(col)
#: sdk/script/fn/SetCommand.xml:104(col)
#: sdk/script/fn/SetCommand.xml:107(col)
#: sdk/script/Typechecks.xml:57(col)
msgid "Objekt"
msgstr "Object"
@ -7252,6 +7280,20 @@ msgstr "Object of which you want to determine rotation. Can be 0 in local calls.
msgid "Liefert die Rotation in Grad von *pObj. Der Rückgabewert liegt zwischen -180° und 180°. 0° ist der Normalzustand."
msgstr "Returns the rotation of an object. Values range from -180° to +180°. 0° is unrotated."
#: sdk/script/fn/GetProperty.xml:12(desc)
#, fuzzy
msgid "Abzufragende Eigenschaft."
msgstr "Name of the physical property requested."
#: sdk/script/fn/GetProperty.xml:13(desc)
#, fuzzy
msgid "Objekt, das untersucht wird. Null bei lokalem Aufruf."
msgstr "Object being sold. Can be 0 in local calls."
#: sdk/script/fn/GetProperty.xml:16(desc)
msgid "Liefert die Eigenschaft <code>key</code> von <code>object</code>."
msgstr ""
#: sdk/script/fn/GetProcedure.xml:12(desc)
#: sdk/script/fn/GetKiller.xml:12(desc)
#: sdk/script/fn/GetAction.xml:12(desc)
@ -11489,131 +11531,156 @@ msgid "Verweis auf ein im Spiel existierendes Objekt. Hat keine direkte Darstell
msgstr "Reference to an existing object at runtime. No direct representation. See <placeholder-1/>()"
#: sdk/script/Typechecks.xml:51(col)
msgid "Feld"
msgstr "array"
#, fuzzy
msgid "Array"
msgstr "Arrays"
#: sdk/script/Typechecks.xml:52(col)
msgid "Ein Typ, der eine Reihe weiterer durchnummerierter Variablen enthält, deren Anzahl mit <placeholder-1/> abgefragt werden kann, und die mit <code><em>array</em>[<em>index</em>]</code> abgerufen werden können. Ab CR."
msgstr "A type containing multiple variables, whose number can be enquired with <placeholder-1/>, and which can be recalled with <code><em>array</em>[<em>index</em>]</code>. Since CR."
#: sdk/script/Typechecks.xml:57(text)
#: sdk/script/Typechecks.xml:58(col)
msgid "Ein allgemeiner Objekttyp. Mit <placeholder-1/> und <placeholder-2/> können Eigenschaften abgefragt bzw. gesetzt werden. Wenn die Eigenschaft <code>\"Prototype\"</code> gesetzt ist und eine nicht gesetzte Eigenschaft abgefragt wird, wird im Prototyp nachgeguckt."
msgstr ""
#: sdk/script/Typechecks.xml:64(text)
msgid "Außerdem gibt es noch zwei spezielle Typen:"
msgstr "Additionally, there are two special types:"
#: sdk/script/Typechecks.xml:60(li)
#: sdk/script/Typechecks.xml:67(li)
msgid "<code>any</code>: Der Typ ist nicht bekannt oder egal. \"0\" hat immer diesen Typ."
msgstr "<code>any</code>: The type is unknown or does not make a difference. \"0\" always has this type."
#: sdk/script/Typechecks.xml:61(li)
#: sdk/script/Typechecks.xml:68(li)
msgid "<code>&amp;</code>: Der Wert ist eine Referenz - z.B. auf eine Variable. Er verhält sich genau wie der Zielwert, kann aber gesetzt werden (z.B. mit dem Operator \"<code>=</code>\"). Siehe auch <emlink href=\"script/Funcs.html#referenzen\">Referenzparameter</emlink>."
msgstr "<code>&amp;</code>: The value is a reference, for example to a variable. It behaves exactly as the target value, but can be changed (for example with the operator \"<code>=</code>\"). See also <emlink href=\"script/Funcs.html#referenzen\">Reference parameters</emlink>."
#: sdk/script/Typechecks.xml:64(h)
#: sdk/script/Typechecks.xml:71(h)
msgid "Arrays"
msgstr "Arrays"
#: sdk/script/Typechecks.xml:66(text)
#: sdk/script/Typechecks.xml:73(text)
msgid "Arrays können entweder direkt durch <code>[<em>Ausdruck 1</em>, <em>Ausdruck 2</em>, ...]</code> oder <placeholder-1/>() erstellt werden. Sie werden bei Zugriff auf ein Element gegebenenfalls automatisch verlängert, jedoch ist es schneller, das Array gleich mit der benötigten Länge zu erstellen. Wird ein Array einer Variablen zugewiesen oder einer Funktion übergeben, bekommt diese Variable eine eigene Kopie des Arrays. Das eigentliche Kopieren wird aber erst ausgeführt, wenn es nötig ist. Wenn das Array einer Funktion zum Ändern übergeben werden soll, muss ein Referenzparameter verwendet werden."
msgstr "Arrays can be created directly with <code>[<em>expression 1</em>, <em>expression 2</em>, ...]</code> or indirectly with <placeholder-1/>(). They are automatically enlarged if necessary on element access, but it's faster to create them with the needed length from the start. If an array is stored in a variable or used as a parameter to a function, the new variable has it's own copy of the array. The actual copy is deferred if possible, though. If an array is passed to a function for modification, a reference has to be used."
#: sdk/script/Typechecks.xml:68(text)
#: sdk/script/Typechecks.xml:75(text)
msgid "Zugriff auf ein Element <code>i</code> eines Arrays <code>a</code> erfolgt über <code>a[i]</code>. Dabei entspricht <code>i=0</code> dem ersten Element."
msgstr "Access to element <code>i</code> of array <code>a</code> is achieved through <code>a[i]</code>. <code>i=0</code> is the first element."
#: sdk/script/Typechecks.xml:69(h)
#: sdk/script/Typechecks.xml:76(h)
msgid "Beispiel 1"
msgstr "Example 1"
#: sdk/script/Typechecks.xml:80(text)
#: sdk/script/Typechecks.xml:87(text)
msgid "Diese Funktion summiert alle Elemente eines Arrays."
msgstr "This function adds up all elements of an array."
#: sdk/script/Typechecks.xml:81(h)
#: sdk/script/Typechecks.xml:88(h)
msgid "Beispiel 2"
msgstr "Example 2"
#: sdk/script/Typechecks.xml:87(text)
#: sdk/script/Typechecks.xml:94(text)
msgid "Diese Funktion wählt zufällig aus einer der vier ids aus und gibt diese zurück."
msgstr "This function randomly chooses one out of four ids and returns it."
#: sdk/script/Typechecks.xml:90(h)
#: sdk/script/Typechecks.xml:97(h)
msgid "Konvertierung"
msgstr "Conversion"
#: sdk/script/Typechecks.xml:92(text)
#: sdk/script/Typechecks.xml:99(text)
msgid "Aus folgender Tabelle kann entnommen werden, welche Typen automatisch konvertiert werden und wo ein Fehler ausgelöst wird:"
msgstr "Consult the following table to determine which types can be converted and which conversions might cause errors:"
#: sdk/script/Typechecks.xml:96(col)
#: sdk/script/Typechecks.xml:103(col)
msgid "nach -&gt;"
msgstr "to -&gt;"
#: sdk/script/Typechecks.xml:106(col)
#: sdk/script/Typechecks.xml:107(col)
#: sdk/script/Typechecks.xml:114(col)
#: sdk/script/Typechecks.xml:115(col)
#: sdk/script/Typechecks.xml:116(col)
#: sdk/script/Typechecks.xml:124(col)
#: sdk/script/Typechecks.xml:125(col)
#: sdk/script/Typechecks.xml:126(col)
#: sdk/script/Typechecks.xml:134(col)
#: sdk/script/Typechecks.xml:135(col)
#: sdk/script/Typechecks.xml:136(col)
#: sdk/script/Typechecks.xml:143(col)
#: sdk/script/Typechecks.xml:146(col)
#: sdk/script/Typechecks.xml:152(col)
#: sdk/script/Typechecks.xml:156(col)
#: sdk/script/Typechecks.xml:145(col)
#: sdk/script/Typechecks.xml:147(col)
#: sdk/script/Typechecks.xml:150(col)
#: sdk/script/Typechecks.xml:155(col)
#: sdk/script/Typechecks.xml:158(col)
#: sdk/script/Typechecks.xml:165(col)
#: sdk/script/Typechecks.xml:169(col)
#: sdk/script/Typechecks.xml:175(col)
#: sdk/script/Typechecks.xml:179(col)
msgid "OK"
msgstr "OK"
#: sdk/script/Typechecks.xml:108(col)
#: sdk/script/Typechecks.xml:116(col)
msgid "if &lt;= 9999"
msgstr "if &lt;= 9999"
#: sdk/script/Typechecks.xml:109(col)
#: sdk/script/Typechecks.xml:110(col)
#: sdk/script/Typechecks.xml:111(col)
#: sdk/script/Typechecks.xml:117(col)
#: sdk/script/Typechecks.xml:118(col)
#: sdk/script/Typechecks.xml:119(col)
#: sdk/script/Typechecks.xml:120(col)
#: sdk/script/Typechecks.xml:126(col)
#: sdk/script/Typechecks.xml:127(col)
#: sdk/script/Typechecks.xml:128(col)
#: sdk/script/Typechecks.xml:129(col)
#: sdk/script/Typechecks.xml:135(col)
#: sdk/script/Typechecks.xml:130(col)
#: sdk/script/Typechecks.xml:137(col)
#: sdk/script/Typechecks.xml:138(col)
#: sdk/script/Typechecks.xml:144(col)
#: sdk/script/Typechecks.xml:145(col)
#: sdk/script/Typechecks.xml:147(col)
#: sdk/script/Typechecks.xml:151(col)
#: sdk/script/Typechecks.xml:153(col)
#: sdk/script/Typechecks.xml:154(col)
#: sdk/script/Typechecks.xml:155(col)
#: sdk/script/Typechecks.xml:139(col)
#: sdk/script/Typechecks.xml:140(col)
#: sdk/script/Typechecks.xml:146(col)
#: sdk/script/Typechecks.xml:148(col)
#: sdk/script/Typechecks.xml:149(col)
#: sdk/script/Typechecks.xml:156(col)
#: sdk/script/Typechecks.xml:157(col)
#: sdk/script/Typechecks.xml:159(col)
#: sdk/script/Typechecks.xml:160(col)
#: sdk/script/Typechecks.xml:164(col)
#: sdk/script/Typechecks.xml:166(col)
#: sdk/script/Typechecks.xml:167(col)
#: sdk/script/Typechecks.xml:168(col)
#: sdk/script/Typechecks.xml:170(col)
#: sdk/script/Typechecks.xml:174(col)
#: sdk/script/Typechecks.xml:176(col)
#: sdk/script/Typechecks.xml:177(col)
#: sdk/script/Typechecks.xml:178(col)
msgid "Error"
msgstr "Error"
#: sdk/script/Typechecks.xml:124(col)
#: sdk/script/Typechecks.xml:133(col)
#: sdk/script/Typechecks.xml:142(col)
#: sdk/script/Typechecks.xml:134(col)
#: sdk/script/Typechecks.xml:144(col)
#: sdk/script/Typechecks.xml:154(col)
#: sdk/script/Strict.xml:5(title)
#: sdk/script/Strict.xml:6(h)
msgid "#strict"
msgstr "#strict"
#: sdk/script/Typechecks.xml:160(h)
#: sdk/script/Typechecks.xml:180(col)
msgid "maybe"
msgstr ""
#: sdk/script/Typechecks.xml:184(h)
msgid "Erklärung der Tabelle:"
msgstr "Additional information:"
#: sdk/script/Typechecks.xml:162(li)
#: sdk/script/Typechecks.xml:186(li)
msgid "Wo #strict steht, wird nur ein Fehler ausgelöst wenn der Script <emlink href=\"script/Strict.html\">#strict</emlink> ist. Hierbei handelt es sich um \"ungefährliche\" aber sinnlose Konvertierungen, die nur in einigen \"trickreichen\" Scripts zur Anwendung kamen."
msgstr "Conversions marked #strict will only throw an error if the script is <emlink href=\"script/Strict.html\">#strict</emlink>. This only concerns harmless but nonsense conversions which might have appeared in older scripts."
#: sdk/script/Typechecks.xml:163(li)
#: sdk/script/Typechecks.xml:187(li)
msgid "Die Konvertierung int zu id ist nur erlaubt, wenn die Zahl größer gleich 0 und kleiner gleich 9999 ist. Auf diese Weise werden auch IDs, die nur aus Zahlen bestehen, unterstützt (z.B. 0001)"
msgstr "Conversion to id is valid only if the number is greater than or equal to 0 and less that or equal to 9999. This procedure also supports IDs that contain digits only."
#: sdk/script/Typechecks.xml:164(li)
#: sdk/script/Typechecks.xml:188(li)
msgid "Konvertierung nach bool ist generell erlaubt. Sie ergibt für jeden Wert außer 0 <code>true</code>."
msgstr "Conversion to bool is generally allowed. All values except 0 are <code>true</code>."
#: sdk/script/Typechecks.xml:189(li)
msgid "Wenn ein Objekt in eine Proplist konvertiert wurde, kann es wieder in ein Objekt konvertiert werden. Ansonsten können Proplists nicht in Objekte konvertiert werden."
msgstr ""
#: sdk/script/Strict.xml:8(text)
msgid "Neu geschriebene Scripte sollten #strict sein. Dabei werden einige Altlasten der Engine ignoriert und es können unter anderem strengere Typüberprüfungen angesetzt werden. Scripte ohne #strict werden nur aus Gründen der Abwärtskompatibilität akzeptiert."
msgstr "Any new script should be #strict. In this way various old scripting inaccuracies will be ignored and proper type checking can be applied. Scripts without #strict are accepted only for backwards compatibility reasons."
@ -15223,10 +15290,6 @@ msgstr "Attach"
msgid "0 oder 1. Bei 1 bewegt sich das Partikel bei angegebenem Zielobjekt relativ zu diesem. Ab 4.95.4."
msgstr "0 or 1. If 1 the particle is moving relative to its target object's position. From CE 4.95.4."
#: sdk/particle/index.xml:154(h)
msgid "Eigenschaften"
msgstr "Properties"
#: sdk/particle/index.xml:155(text)
msgid "Jedes Partikel hat eine Position (x, y), Impulse horizontal (xdir) und vertikal (ydir), sowie eine Lebenszeit (life) und zwei Extraparameter (a und b). Diese werden von den <a href=\"#funcs\">Partikelfunktionen</a> verwaltet, und können bei der Erzeugung im Script nur mit Startwerten versehen werden. Für die Bedeutung der Attribute im Einzelnen siehe <a href=\"#funcs\">Partikelfunktionen</a> und <a href=\"#drawfuncs\">Zeichenfunktionen</a>."
msgstr "Each particle has a position (x, y), horizontal and vertical impulse (xdir and ydir), life time (life), and two extra parameters (a and b). These are initialized by script and then processed by the <a href=\"#funcs\">particle functions</a>. For more information see <a href=\"#funcs\">particle functions</a> and <a href=\"#drawfuncs\">drawing functions</a>."
@ -19520,6 +19583,9 @@ msgstr "c4group.exe (Windows) c4group (Linux) c4group (Mac)"
msgid "Dieses Kommandozeilen-Programm dient zum Bearbeiten von Gruppendateien. Es kann nicht per Doppelklick, sondern nur per Kommandozeile (Eingabeaufforderung) gestartet werden. Auskunft über alle verfügbaren Kommandozeilenparameter erhält man, indem man das Programm ohne weitere Parameter über die Kommandozeile startet."
msgstr "This command line program is used for processing group files. A list of command line options is available by starting the program without parameters via command line (<i>not</i> by double clicking)."
#~ msgid "Feld"
#~ msgstr "array"
#~ msgid "IncVar"
#~ msgstr "IncVar"
@ -19625,9 +19691,6 @@ msgstr "This command line program is used for processing group files. A list of
#~ msgid "Die threadlokale Variable, die gesetzt werden soll."
#~ msgstr "Thread local variable to be set."
#~ msgid "Zu setzender Wert."
#~ msgstr "Value to be set."
#~ msgid "Weist den Wert iValue einer beliebigen Thread-lokalen Variablen (ab 0) zu. Der Datentyp ist variabel. Thread-lokale Variablen gelten nur für die Dauer des aktuellen Funktionsaufrufes. Numerierte Variablen wurden durch Variablen mit Namen abgelöst, sind aber für Arrays nützlich."
#~ msgstr "Assigns a value to an indexed thread local variable. The data type is variant. Thread local variables are valid for the duration of a function execution only. Indexed variables are more old-fashioned than named variables but are still good for emulating local arrays."

View File

@ -48,10 +48,17 @@
</row>
<row>
<col><code>array</code></col>
<col>Feld</col>
<col>Array</col>
<col>Ein Typ, der eine Reihe weiterer durchnummerierter Variablen enthält, deren Anzahl mit <funclink>GetLength</funclink> abgefragt werden kann, und die mit <code><em>array</em>[<em>index</em>]</code> abgerufen werden können. Ab CR.</col>
<col><code>[0,42,CLNK] </code></col>
</row>
<row>
<col><code>proplist</code></col>
<col>Objekt</col>
<col>Ein allgemeiner Objekttyp. Mit <funclink>GetProperty</funclink> und <funclink>SetProperty</funclink> können Eigenschaften abgefragt bzw. gesetzt werden.
Wenn die Eigenschaft <code>"Prototype"</code> gesetzt ist und eine nicht gesetzte Eigenschaft abgefragt wird, wird im Prototyp nachgeguckt.</col>
<col><code>[0,42,CLNK] </code></col>
</row>
</table></text>
<text>Außerdem gibt es noch zwei spezielle Typen:</text>
@ -100,6 +107,7 @@
<col><code>object</code></col>
<col><code>string</code></col>
<col><code>array</code></col>
<col><code>proplist</code></col>
</rowh>
<row>
<col><code>int</code></col>
@ -109,6 +117,7 @@
<col>Error</col>
<col>Error</col>
<col>Error</col>
<col>Error</col>
</row>
<row>
<col><code>bool</code></col>
@ -118,6 +127,7 @@
<col>Error</col>
<col>Error</col>
<col>Error</col>
<col>Error</col>
</row>
<row>
<col><code>id</code></col>
@ -127,6 +137,7 @@
<col>Error</col>
<col>Error</col>
<col>Error</col>
<col>Error</col>
</row>
<row>
<col><code>object</code></col>
@ -136,6 +147,7 @@
<col>OK</col>
<col>Error</col>
<col>Error</col>
<col>OK</col>
</row>
<row>
<col><code>string</code></col>
@ -145,6 +157,7 @@
<col>Error</col>
<col>OK</col>
<col>Error</col>
<col>Error</col>
</row>
<row>
<col><code>array</code></col>
@ -154,6 +167,17 @@
<col>Error</col>
<col>Error</col>
<col>OK</col>
<col>Error</col>
</row>
<row>
<col><code>proplist</code></col>
<col>Error</col>
<col>OK</col>
<col>Error</col>
<col>Error</col>
<col>Error</col>
<col>OK</col>
<col>maybe</col>
</row>
</table></text>
@ -162,6 +186,7 @@
<li>Wo #strict steht, wird nur ein Fehler ausgelöst wenn der Script <emlink href="script/Strict.html">#strict</emlink> ist. Hierbei handelt es sich um "ungefährliche" aber sinnlose Konvertierungen, die nur in einigen "trickreichen" Scripts zur Anwendung kamen.</li>
<li>Die Konvertierung int zu id ist nur erlaubt, wenn die Zahl größer gleich 0 und kleiner gleich 9999 ist. Auf diese Weise werden auch IDs, die nur aus Zahlen bestehen, unterstützt (z.B. 0001)</li>
<li>Konvertierung nach bool ist generell erlaubt. Sie ergibt für jeden Wert außer 0 <code>true</code>.</li>
<li>Wenn ein Objekt in eine Proplist konvertiert wurde, kann es wieder in ein Objekt konvertiert werden. Ansonsten können Proplists nicht in Objekte konvertiert werden.</li>
</ul></text>
</part>

View File

@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<!DOCTYPE funcs SYSTEM "../../../clonk.dtd">
<?xml-stylesheet type="text/xsl" href="../../../clonk.xsl"?>
<funcs>
<func>
<title>GetProperty</title>
<category>Objekte</category><subcat>Eigenschaften</subcat>
<version>4.10.0.0</version>
<syntax>
<rtype>any</rtype>
<params>
<param><type>string</type><name>key</name><desc>Abzufragende Eigenschaft.</desc><optional /></param>
<param><type>proplist</type><name>object</name><desc>Objekt, das untersucht wird. Null bei lokalem Aufruf.</desc><optional /></param>
</params>
</syntax>
<desc>Liefert die Eigenschaft <code>key</code> von <code>object</code>.</desc>
<related>
<funclink>SetProperty</funclink>
</related>
</func>
<author>Günther</author><date>Mai 2009</date>
</funcs>

View File

@ -0,0 +1,24 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<!DOCTYPE funcs SYSTEM "../../../clonk.dtd">
<?xml-stylesheet type="text/xsl" href="../../../clonk.xsl"?>
<funcs>
<func>
<title>SetProperty</title>
<category>Objekte</category><subcat>Eigenschaften</subcat>
<version>4.10.0.0</version>
<syntax>
<rtype>bool</rtype>
<params>
<param><type>string</type><name>key</name><desc>Zu setzende Eigenschaft.</desc><optional /></param>
<param><type>any</type><name>value</name><desc>Wert, auf den die Eigenschaft gesetzt werden soll.</desc><optional /></param>
<param><type>proplist</type><name>object</name><desc>Objekt, das geändert wird. Null bei lokalem Aufruf.</desc><optional /></param>
</params>
</syntax>
<desc>Setzt die Eigenschaft <code>key</code> von <code>object</code> auf <code>value</code>. Die Eigenschaft muss vorher nicht existiert haben.</desc>
<related>
<funclink>GetProperty</funclink>
</related>
</func>
<author>Günther</author><date>Mai 2009</date>
</funcs>

View File

@ -236,7 +236,7 @@ class C4Game
BOOL ReloadDef(C4ID id);
BOOL ReloadParticle(const char *szName);
// Object functions
void ClearPointers(C4Object *cobj);
void ClearPointers(C4PropList *cobj);
C4Object *CreateObject(C4ID type, C4Object *pCreator, int32_t owner=NO_OWNER,
int32_t x=50, int32_t y=50, int32_t r=0,
FIXED xdir=Fix0, FIXED ydir=Fix0, FIXED rdir=Fix0, int32_t iController=NO_OWNER);

View File

@ -53,7 +53,7 @@ class C4GameObjects : public C4NotifyingObjectList
C4Object *FindInternal(C4ID id); // find object in first sector
virtual C4Object *ObjectPointer(int32_t iNumber); // object pointer by number
long ObjectNumber(C4Object *pObj); // object number by pointer
long ObjectNumber(C4PropList *pObj); // object number by pointer
C4ObjectList &ObjectsInt(); // return object list containing system objects

View File

@ -27,6 +27,7 @@
#include "C4ValueList.h"
#include "C4Effects.h"
#include "C4Particles.h"
#include "C4PropList.h"
/* Object status */
@ -103,15 +104,13 @@ class C4Action
void GetBridgeData(int32_t &riBridgeTime, bool &rfMoveClonk, bool &rfWall, int32_t &riBridgeMaterial);
};
class C4Object
class C4Object: public C4PropList
{
public:
C4Object();
~C4Object();
int32_t Number; // int32_t, for sync safety on all machines
C4ID id;
StdStrBuf Name;
int32_t Status; // NoSave //
int32_t RemovalDelay; // NoSave //
int32_t Owner;
int32_t Controller;
@ -191,8 +190,6 @@ class C4Object
int32_t nContained;
StdCopyStrBuf nInfo;
C4Value *FirstRef; // No-Save
class C4GraphicsOverlay *pGfxOverlay; // singly linked list of overlay graphics
protected:
bool OnFire;
@ -399,9 +396,6 @@ class C4Object
bool AdjustWalkRotation(int32_t iRangeX, int32_t iRangeY, int32_t iSpeed);
void AddRef(C4Value *pRef);
void DelRef(const C4Value *pRef, C4Value * pNextRef);
StdStrBuf GetInfoString(); // return def desc plus effects
bool CanConcatPictureWith(C4Object *pOtherObject); // return whether this object should be grouped with the other in activation lists, contents list, etc.

View File

@ -123,7 +123,7 @@ class C4ObjectList
BOOL Write(char *szTarget);
void CompileFunc(StdCompiler *pComp, bool fSaveRefs = true, bool fSkipPlayerObjects = false);
long ObjectNumber(C4Object *pObj);
long ObjectNumber(C4PropList *pObj);
bool IsContained(C4Object *pObj);
int ClearPointers(C4Object *pObj);
int ObjectCount(C4ID id=C4ID_None, int32_t dwCategory=C4D_All) const;

View File

@ -0,0 +1,37 @@
/* Property lists */
#ifndef C4PROPLIST_H
#define C4PROPLIST_H
#include "C4Value.h"
#include "C4StringTable.h"
class C4Property {
public:
C4String * Key;
C4Value Value;
operator void * () { return Key; }
C4Property & operator = (void * p) { assert(!p); Key = 0; Value.Set0(); return *this; }
};
class C4PropList {
public:
int32_t Number;
int32_t Status; // NoSave //
void AddRef(C4Value *pRef);
void DelRef(const C4Value *pRef, C4Value * pNextRef);
void AssignRemoval();
const char *GetName() { return "FIXME"; }
bool GetProperty(C4String * k, C4Value & to);
void SetProperty(C4String * k, C4Value & to);
C4PropList();
virtual ~C4PropList();
private:
C4Value *FirstRef; // No-Save
C4Set<C4Property> Properties;
C4PropList * prototype;
};
#endif // C4PROPLIST_H

View File

@ -92,6 +92,7 @@ class C4FacetSurface;
class C4Surface;
class C4League;
class C4RoundResults;
class C4PropList;
namespace C4GUI { class Screen; }
typedef C4GUI::Screen C4GUIScreen;

View File

@ -77,15 +77,25 @@ public:
for (unsigned int i = 0; i < Capacity; ++i)
Table[i] = 0;
}
template<typename H> T Get(H e)
template<typename H> T & Get(H e)
{
unsigned int h = Hash(e);
T r = Table[h % Capacity];
while (r && !Equals(r, e))
T * r = &Table[h % Capacity];
while (*r && !Equals(*r, e))
{
r = Table[++h % Capacity];
r = &Table[++h % Capacity];
}
return r;
return *r;
}
template<typename H> bool Has(H e)
{
unsigned int h = Hash(e);
T * r = &Table[h % Capacity];
while (*r && !Equals(*r, e))
{
r = &Table[++h % Capacity];
}
return !!*r;
}
unsigned int GetSize() { return Size; }
void Add(T e)
@ -150,6 +160,11 @@ inline unsigned int C4Set<C4String *>::Hash<C4String *>(C4String * e)
return e->Hash;
}
enum {
P_PROTOTYPE,
P_NAME,
P_LAST };
// There is only one Stringtable in Game.ScriptEngine
class C4StringTable
{
@ -173,6 +188,7 @@ public:
C4Set<C4String *> Set;
std::vector<C4String *> Stringstxt;
C4String * P[P_LAST];
};
#endif

View File

@ -36,14 +36,12 @@ enum C4V_Type
C4V_Bool=2, // Boolean
C4V_C4ID=3, // C4ID
C4V_C4Object=4, // Pointer on Object
C4V_String=5, // String
C4V_Array=6, // pointer on array of values
C4V_PropList=7,
C4V_pC4Value=8, // reference on a value (variable)
C4V_pC4Value=7, // reference on a value (variable)
C4V_C4ObjectEnum=8, // enumerated object
C4V_C4ObjectEnum=9, // enumerated object
};
#define C4V_Last (int) C4V_pC4Value
@ -55,6 +53,7 @@ C4V_Type GetC4VFromID(char C4VID);
union C4V_Data {
long Int;
C4Object * Obj;
C4PropList * PropList;
C4String * Str;
C4Value * Ref;
C4ValueArray * Array;
@ -92,6 +91,8 @@ public:
{ Data.Str = pStr; AddDataRef(); }
explicit C4Value(C4ValueArray *pArray): Type(pArray ? C4V_Array : C4V_Any), HasBaseArray(false), NextRef(NULL), FirstRef(NULL)
{ Data.Array = pArray; AddDataRef(); }
explicit C4Value(C4PropList *p): Type(p ? C4V_PropList : C4V_Any), HasBaseArray(false), NextRef(NULL), FirstRef(NULL)
{ Data.PropList = p; AddDataRef(); }
explicit C4Value(C4Value *pVal): Type(pVal ? C4V_pC4Value : C4V_Any), HasBaseArray(false), NextRef(NULL), FirstRef(NULL)
{ Data.Ref = pVal; AddDataRef(); }
@ -104,10 +105,11 @@ public:
int32_t getIntOrID() { Deref(); if (Type == C4V_Int || Type == C4V_Bool || Type == C4V_C4ID) return Data.Int; else return 0; }
bool getBool() { return ConvertTo(C4V_Bool) ? !! Data : 0; }
C4ID getC4ID() { return ConvertTo(C4V_C4ID) ? Data.Int : 0; }
C4Object *getObj() { return ConvertTo(C4V_C4Object) ? Data.Obj : NULL; }
C4String *getStr() { return ConvertTo(C4V_String) ? Data.Str : NULL; }
C4ValueArray *getArray() { return ConvertTo(C4V_Array) ? Data.Array : NULL; }
C4Value *getRef() { return ConvertTo(C4V_pC4Value) ? Data.Ref : NULL; }
C4Object * getObj() { return ConvertTo(C4V_C4Object) ? Data.Obj : NULL; }
C4PropList * getPropList() { return ConvertTo(C4V_PropList) ? Data.PropList : NULL; }
C4String * getStr() { return ConvertTo(C4V_String) ? Data.Str : NULL; }
C4ValueArray * getArray() { return ConvertTo(C4V_Array) ? Data.Array : NULL; }
C4Value * getRef() { return ConvertTo(C4V_pC4Value) ? Data.Ref : NULL; }
// Unchecked getters
int32_t _getInt() const { return Data.Int; }
@ -116,6 +118,7 @@ public:
C4Object *_getObj() const { return Data.Obj; }
C4String *_getStr() const { return Data.Str; }
C4ValueArray *_getArray() const { return Data.Array; }
C4PropList *_getPropList() const { return Data.PropList; }
C4Value *_getRef() { return Data.Ref; }
long _getRaw() const { return Data.Int; }
@ -139,6 +142,8 @@ public:
void SetArray(C4ValueArray * Array) { C4V_Data d; d.Array = Array; Set(d, C4V_Array); }
void SetPropList(C4PropList * PropList) { C4V_Data d; d.PropList = PropList; Set(d, C4V_PropList); }
void SetRef(C4Value* nValue) { C4V_Data d; d.Ref = nValue; Set(d, C4V_pC4Value); }
void Set0();
@ -227,8 +232,9 @@ protected:
static C4VCnvFn C4ScriptCnvMap[C4V_Last+1][C4V_Last+1];
static bool FnCnvInt2Id(C4Value *Val, C4V_Type toType, BOOL fStrict);
static bool FnCnvGuess(C4Value *Val, C4V_Type toType, BOOL fStrict);
static bool FnCnvObject(C4Value *Val, C4V_Type toType, BOOL fStrict);
friend class C4Object;
friend class C4PropList;
friend class C4AulDefFunc;
};
@ -237,6 +243,7 @@ inline C4Value C4VInt(int32_t iVal) { C4V_Data d; d.Int = iVal; return C4Value(d
inline C4Value C4VBool(bool fVal) { C4V_Data d; d.Int = fVal; return C4Value(d, C4V_Bool); }
inline C4Value C4VID(C4ID iVal) { C4V_Data d; d.Int = iVal; return C4Value(d, C4V_C4ID); }
inline C4Value C4VObj(C4Object *pObj) { return C4Value(pObj); }
inline C4Value C4VPropList(C4PropList * p) { return C4Value(p); }
inline C4Value C4VString(C4String *pStr) { return C4Value(pStr); }
inline C4Value C4VArray(C4ValueArray *pArray) { return C4Value(pArray); }
inline C4Value C4VRef(C4Value *pVal) { return pVal->GetRef(); }
@ -287,6 +294,13 @@ template <> struct C4ValueConv<C4ValueArray *>
inline static C4ValueArray *_FromC4V(C4Value &v) { return v._getArray(); }
inline static C4Value ToC4V(C4ValueArray *v) { return C4VArray(v); }
};
template <> struct C4ValueConv<C4PropList *>
{
inline static C4V_Type Type() { return C4V_PropList; }
inline static C4PropList *FromC4V(C4Value &v) { return v.getPropList(); }
inline static C4PropList *_FromC4V(C4Value &v) { return v._getPropList(); }
inline static C4Value ToC4V(C4PropList *v) { return C4VPropList(v); }
};
template <> struct C4ValueConv<C4Value *>
{
inline static C4V_Type Type() { return C4V_pC4Value; }

View File

@ -73,6 +73,7 @@
#define C4AUL_TypeBool "bool"
#define C4AUL_TypeC4ID "id"
#define C4AUL_TypeC4Object "object"
#define C4AUL_TypePropList "proplist"
#define C4AUL_TypeString "string"
#define C4AUL_TypeArray "array"
@ -1567,6 +1568,7 @@ void C4AulParseState::Parse_FuncHead()
else if (SEqual(Idtf, C4AUL_TypeBool)) { Fn->ParType[cpar] = C4V_Bool; Shift(Discard,false); }
else if (SEqual(Idtf, C4AUL_TypeC4ID)) { Fn->ParType[cpar] = C4V_C4ID; Shift(Discard,false); }
else if (SEqual(Idtf, C4AUL_TypeC4Object)) { Fn->ParType[cpar] = C4V_C4Object; Shift(Discard,false); }
else if (SEqual(Idtf, C4AUL_TypePropList)) { Fn->ParType[cpar] = C4V_PropList; Shift(Discard,false); }
else if (SEqual(Idtf, C4AUL_TypeString)) { Fn->ParType[cpar] = C4V_String; Shift(Discard,false); }
else if (SEqual(Idtf, C4AUL_TypeArray)) { Fn->ParType[cpar] = C4V_Array; Shift(Discard,false); }
// ampersand?

View File

@ -925,8 +925,10 @@ void C4Game::ClearObjectPtrs(C4Object *pObj)
Application.SoundSystem.ClearPointers(pObj);
}
void C4Game::ClearPointers(C4Object *pObj)
{
void C4Game::ClearPointers(C4PropList * PropList)
{
C4Object * pObj = dynamic_cast<C4Object *>(PropList);
if (!pObj) return; // FIXME
BackObjects.ClearPointers(pObj);
ForeObjects.ClearPointers(pObj);
Messages.ClearPointers(pObj);

View File

@ -283,7 +283,7 @@ C4Object *C4GameObjects::ObjectPointer(int32_t iNumber)
return InactiveObjects.ObjectPointer(iNumber);
}
long C4GameObjects::ObjectNumber(C4Object *pObj)
long C4GameObjects::ObjectNumber(C4PropList * pObj)
{
// search own list
long iNum = C4ObjectList::ObjectNumber(pObj);

View File

@ -548,8 +548,8 @@ BOOL C4Object::ExecMovement() // Every Tick1 by Execute
{
fRemove = false;
if (GetX()>GBackWdt || GetY()>GBackHgt) fRemove = true; // except if they are really out of the viewport to the right...
else if (GetX()<0 && Local[0].Data) fRemove = true; // ...or it's not HUD horizontally and it's out to the left
else if (!Local[0].Data && GetX()<-GBackWdt) fRemove = true; // ...or it's HUD horizontally and it's out to the left
else if (GetX()<0 && Local[0].getBool()) fRemove = true; // ...or it's not HUD horizontally and it's out to the left
else if (!Local[0].getBool() && GetX()<-GBackWdt) fRemove = true; // ...or it's HUD horizontally and it's out to the left
}
if (fRemove)
{

View File

@ -141,7 +141,6 @@ void C4Object::Default()
pGraphics=NULL;
pDrawTransform=NULL;
pEffects=NULL;
FirstRef=NULL;
pGfxOverlay=NULL;
iLastAttachMovementFrame=-1;
}
@ -310,9 +309,8 @@ void C4Object::AssignRemoval(BOOL fExitContents)
// Object info
if (Info) Info->Retire();
Info = NULL;
// Object system operation
while(FirstRef) FirstRef->Set(0);
Game.ClearPointers(this);
// Object system operation
C4PropList::AssignRemoval();
ClearCommands();
if (pSolidMaskData)
{
@ -3178,7 +3176,6 @@ void C4Object::Clear()
}
if (pDrawTransform) { delete pDrawTransform; pDrawTransform=NULL; }
if (pGfxOverlay) { delete pGfxOverlay; pGfxOverlay=NULL; }
while (FirstRef) FirstRef->Set(0);
}
BOOL C4Object::ContainedControl(BYTE byCom)
@ -5644,7 +5641,7 @@ void C4Object::ApplyParallaxity(float &riTx, float &riTy, const C4Facet &fctView
{
// parallaxity by locals
// special: Negative positions with parallaxity 0 mean HUD elements positioned to the right/bottom
int iParX = Local[0].Data.Int, iParY = Local[1].Data.Int;
int iParX = Local[0].getInt(), iParY = Local[1].getInt();
if (!iParX && GetX()<0)
riTx = -fctViewport.Wdt;
else
@ -5677,7 +5674,7 @@ void C4Object::UnSelect(BOOL fCursor)
void C4Object::GetViewPosPar(float &riX, float &riY, float tx, float ty, const C4Facet &fctViewport)
{
float iParX = float(Local[0].Data.Int), iParY = float(Local[1].Data.Int);
float iParX = float(Local[0].getInt()), iParY = float(Local[1].getInt());
// get drawing pos, then subtract original target pos to get drawing pos on landscape
if (!iParX && GetX()<0)
// HUD element at right viewport pos
@ -5945,27 +5942,6 @@ void C4Object::UpdateInLiquid()
}
}
void C4Object::AddRef(C4Value *pRef)
{
pRef->NextRef = FirstRef;
FirstRef = pRef;
}
void C4Object::DelRef(const C4Value * pRef, C4Value * pNextRef)
{
// References to objects never have HasBaseArray set
if(pRef == FirstRef)
FirstRef = pNextRef;
else
{
C4Value *pVal = FirstRef;
while(pVal->NextRef && pVal->NextRef != pRef)
pVal = pVal->NextRef;
assert(pVal->NextRef);
pVal->NextRef = pNextRef;
}
}
StdStrBuf C4Object::GetInfoString()
{
StdStrBuf sResult;

View File

@ -457,7 +457,7 @@ void C4ObjectList::Enumerate()
cLnk->Obj->EnumeratePointers();
}
long C4ObjectList::ObjectNumber(C4Object *pObj)
long C4ObjectList::ObjectNumber(C4PropList *pObj)
{
C4ObjectLink *cLnk;
if(!pObj) return 0;

View File

@ -0,0 +1,87 @@
#include <C4Include.h>
#include <C4PropList.h>
#include <C4Game.h>
void C4PropList::AddRef(C4Value *pRef)
{
pRef->NextRef = FirstRef;
FirstRef = pRef;
}
void C4PropList::DelRef(const C4Value * pRef, C4Value * pNextRef)
{
// References to objects never have HasBaseArray set
if(pRef == FirstRef)
FirstRef = pNextRef;
else
{
C4Value *pVal = FirstRef;
while(pVal->NextRef && pVal->NextRef != pRef)
pVal = pVal->NextRef;
assert(pVal->NextRef);
pVal->NextRef = pNextRef;
}
}
void C4PropList::AssignRemoval()
{
while(FirstRef) FirstRef->Set(0);
Game.ClearPointers(this);
}
C4PropList::C4PropList():
FirstRef(NULL), prototype(0)
{
}
C4PropList::~C4PropList()
{
assert(!FirstRef);
while (FirstRef) FirstRef->Set(0);
}
template<> template<>
unsigned int C4Set<C4Property>::Hash<C4String *>(C4String * e)
{
return e->Hash;
}
template<> template<>
bool C4Set<C4Property>::Equals<C4String *>(C4Property a, C4String * b)
{
return a.Key == b;
}
template<> template<>
unsigned int C4Set<C4Property>::Hash<C4Property>(C4Property p)
{
return p.Key->Hash;
}
bool C4PropList::GetProperty(C4String * k, C4Value & to)
{
if (Properties.Has(k))
{
to.SetRef(&Properties.Get(k).Value);
return true;
}
if (prototype)
{
return prototype->GetProperty(k, to);
}
return false;
}
void C4PropList::SetProperty(C4String * k, C4Value & to)
{
if (Properties.Has(k))
{
Properties.Get(k).Value = to;
}
else
{
C4Property p = { k, to };
Properties.Add(p);
}
if (k == Game.ScriptEngine.Strings.P[P_PROTOTYPE])
prototype = to.getPropList();
}

View File

@ -73,8 +73,6 @@ static StdStrBuf FnStringFormat(C4AulContext *cthr, const char *szFormatPar, C4V
// Field
if (*cpFormat=='%')
{
// arrays now valid in %v
//if (Par[cPar] && Par[cPar]->Type == C4V_Array) throw new C4AulExecError(0, cthr, 0, "array argument to format");
// Scan field type
for (cpType=cpFormat+1; *cpType && (*cpType=='.' || Inside(*cpType,'0','9')); cpType++) {}
// Copy field
@ -966,6 +964,27 @@ static C4String *FnGetAction(C4AulContext *cthr, C4Object *pObj)
return String(pObj->Def->ActMap[pObj->Action.Act].Name);
}
static C4Value FnGetProperty_C4V(C4AulContext *cthr, C4Value * key_C4V, C4Value * pObj_C4V)
{
C4PropList * pObj = pObj_C4V->_getPropList();
if (!pObj) pObj=cthr->Obj; if (!pObj) return C4VFalse;
C4String * key = key_C4V->_getStr();
if(!key) return C4VFalse;
C4Value r;
pObj->GetProperty(key, r);
return r;
}
static C4Value FnSetProperty_C4V(C4AulContext *cthr, C4Value * key_C4V, C4Value * to, C4Value * pObj_C4V)
{
C4PropList * pObj = pObj_C4V->_getPropList();
if (!pObj) pObj=cthr->Obj; if (!pObj) return C4VFalse;
C4String * key = key_C4V->_getStr();
if(!key) return C4VFalse;
pObj->SetProperty(key, *to);
return C4VTrue;
}
static C4String *FnGetName(C4AulContext *cthr, C4Object *pObj, C4ID idDef/*, bool fFilename, long idx*/)
{
// Def name
@ -1523,7 +1542,8 @@ static C4Value FnAddMenuItem(C4AulContext *cthr, C4Value *pPars)
sprintf(parameter, "%s", C4IdText(Parameter.getC4ID()));
break;
case C4V_C4Object:
sprintf(parameter, "Object(%d)", Parameter.getObj()->Number);
case C4V_PropList:
sprintf(parameter, "Object(%d)", Parameter.getPropList()->Number);
break;
case C4V_String:
// note this breaks if there is '"' in the string.
@ -6869,6 +6889,7 @@ C4ScriptConstDef C4ScriptConstMap[]={
{ "C4V_C4Object" ,C4V_Int, C4V_C4Object},
{ "C4V_String" ,C4V_Int, C4V_String},
{ "C4V_Array" ,C4V_Int, C4V_Array},
{ "C4V_PropList" ,C4V_Int, C4V_PropList},
{ "COMD_None" ,C4V_Int, COMD_None},
{ "COMD_Stop" ,C4V_Int, COMD_Stop},
@ -7166,6 +7187,8 @@ C4ScriptFnDef C4ScriptFnMap[]={
{ "Global", 1 ,C4V_Any ,{ C4V_Int ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any} ,MkFnC4V FnGlobal_C4V , 0 },
{ "SetLocal", 1 ,C4V_Any ,{ C4V_Int ,C4V_Any ,C4V_C4Object,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any} ,MkFnC4V FnSetLocal_C4V , 0 },
{ "Local", 1 ,C4V_Any ,{ C4V_Int ,C4V_C4Object,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any} ,MkFnC4V FnLocal_C4V , 0 },
{ "SetProperty", 1 ,C4V_Any ,{ C4V_String ,C4V_Any ,C4V_PropList,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any} ,MkFnC4V FnSetProperty_C4V , 0 },
{ "GetProperty", 1 ,C4V_Any ,{ C4V_String ,C4V_PropList,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any} ,MkFnC4V FnGetProperty_C4V , 0 },
{ "Explode", 1 ,C4V_Bool ,{ C4V_Int ,C4V_C4Object,C4V_C4ID ,C4V_String ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any} ,0 , FnExplode },
{ "Incinerate", 1 ,C4V_Bool ,{ C4V_C4Object,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any} ,0 , FnIncinerate },
{ "IncinerateLandscape", 1 ,C4V_Bool ,{ C4V_Int ,C4V_Int ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any} ,0 , FnIncinerateLandscape },

View File

@ -78,11 +78,14 @@ void C4String::DecRef()
C4StringTable::C4StringTable()
{
P[P_PROTOTYPE] = RegString("Prototype");
for (unsigned int i = 0; i < P_LAST; ++i) P[i]->IncRef();
}
C4StringTable::~C4StringTable()
{
Clear();
for (unsigned int i = 0; i < P_LAST; ++i) P[i]->DecRef();
assert(!Set.GetSize());
}

View File

@ -63,13 +63,14 @@ void C4Value::AddDataRef()
case C4V_Array: Data.Array = Data.Array->IncRef(); break;
case C4V_String: Data.Str->IncRef(); break;
case C4V_C4Object:
Data.Obj->AddRef(this);
case C4V_PropList:
Data.PropList->AddRef(this);
#ifdef _DEBUG
// check if the object actually exists
if(!Game.Objects.ObjectNumber(Data.Obj))
{ LogF("Warning: using wild object ptr %p!", Data.Obj); }
else if(!Data.Obj->Status)
{ LogF("Warning: using ptr on deleted object %p (%s)!", Data.Obj, Data.Obj->GetName()); }
if(!Game.Objects.ObjectNumber(Data.PropList))
{ LogF("Warning: using wild object ptr %p!", Data.PropList); }
else if(!Data.PropList->Status)
{ LogF("Warning: using ptr on deleted object %p (%s)!", Data.PropList, Data.PropList->GetName()); }
#endif
break;
#endif
@ -88,7 +89,7 @@ void C4Value::DelDataRef(C4V_Data Data, C4V_Type Type, C4Value * pNextRef, C4Val
Data.Ref->DelRef(this, pNextRef, pBaseArray);
break;
#ifdef C4ENGINE
case C4V_C4Object: Data.Obj->DelRef(this, pNextRef); break;
case C4V_C4Object: case C4V_PropList: Data.PropList->DelRef(this, pNextRef); break;
case C4V_Array: Data.Array->DecRef(); break;
case C4V_String: Data.Str->DecRef(); break;
#endif
@ -302,6 +303,8 @@ const char* GetC4VName(const C4V_Type Type)
return "string";
case C4V_Array:
return "array";
case C4V_PropList:
return "proplist";
case C4V_pC4Value:
return "&";
default:
@ -331,6 +334,8 @@ char GetC4VID(const C4V_Type Type)
return 'O';
case C4V_Array:
return 'a';
case C4V_PropList:
return 'p';
}
return ' ';
}
@ -357,6 +362,8 @@ C4V_Type GetC4VFromID(const char C4VID)
return C4V_C4ObjectEnum;
case 'a':
return C4V_Array;
case 'p':
return C4V_PropList;
}
return C4V_Any;
}
@ -390,6 +397,13 @@ static bool FnCnvDeref(C4Value *Val, C4V_Type toType, BOOL fStrict)
return Val->ConvertTo(toType, fStrict);
}
bool C4Value::FnCnvObject(C4Value *Val, C4V_Type toType, BOOL fStrict)
{
// try casting
if (dynamic_cast<C4Object *>(Val->Data.PropList)) return true;
return false;
}
bool C4Value::FnCnvGuess(C4Value *Val, C4V_Type toType, BOOL fStrict)
{
if (Val->Data)
@ -422,6 +436,7 @@ bool C4Value::FnCnvInt2Id(C4Value *Val, C4V_Type toType, BOOL fStrict)
#define CnvInt2Id C4Value::FnCnvInt2Id, false
#define CnvDirectOld FnCnvDirectOld, true
#define CnvDeref FnCnvDeref, false
#define CnvObject FnCnvObject, false
C4VCnvFn C4Value::C4ScriptCnvMap[C4V_Last+1][C4V_Last+1] = {
{ // C4V_Any - always try guess
@ -432,6 +447,7 @@ C4VCnvFn C4Value::C4ScriptCnvMap[C4V_Last+1][C4V_Last+1] = {
{ CnvGuess }, // C4Object
{ CnvGuess }, // String
{ CnvGuess }, // Array
{ CnvGuess }, // PropList
{ CnvError }, // pC4Value
},
{ // C4V_Int
@ -442,6 +458,7 @@ C4VCnvFn C4Value::C4ScriptCnvMap[C4V_Last+1][C4V_Last+1] = {
{ CnvError }, // C4Object NEVER!
{ CnvError }, // String NEVER!
{ CnvError }, // Array NEVER!
{ CnvError }, // PropList NEVER!
{ CnvError }, // pC4Value
},
{ // C4V_Bool
@ -452,6 +469,7 @@ C4VCnvFn C4Value::C4ScriptCnvMap[C4V_Last+1][C4V_Last+1] = {
{ CnvError }, // C4Object NEVER!
{ CnvError }, // String NEVER!
{ CnvError }, // Array NEVER!
{ CnvError }, // PropList NEVER!
{ CnvError }, // pC4Value
},
{ // C4V_C4ID
@ -462,6 +480,7 @@ C4VCnvFn C4Value::C4ScriptCnvMap[C4V_Last+1][C4V_Last+1] = {
{ CnvError }, // C4Object NEVER!
{ CnvError }, // String NEVER!
{ CnvError }, // Array NEVER!
{ CnvError }, // PropList NEVER!
{ CnvError }, // pC4Value
},
{ // C4V_Object
@ -472,6 +491,7 @@ C4VCnvFn C4Value::C4ScriptCnvMap[C4V_Last+1][C4V_Last+1] = {
{ CnvOK }, // C4Object same
{ CnvError }, // String NEVER!
{ CnvError }, // Array NEVER!
{ CnvOK }, // PropList
{ CnvError }, // pC4Value
},
{ // C4V_String
@ -482,6 +502,7 @@ C4VCnvFn C4Value::C4ScriptCnvMap[C4V_Last+1][C4V_Last+1] = {
{ CnvError }, // C4Object NEVER!
{ CnvOK }, // String same
{ CnvError }, // Array NEVER!
{ CnvError }, // PropList NEVER!
{ CnvError }, // pC4Value
},
{ // C4V_Array
@ -492,6 +513,18 @@ C4VCnvFn C4Value::C4ScriptCnvMap[C4V_Last+1][C4V_Last+1] = {
{ CnvError }, // C4Object NEVER!
{ CnvError }, // String NEVER!
{ CnvOK }, // Array same
{ CnvError }, // PropList NEVER!
{ CnvError }, // pC4Value NEVER!
},
{ // C4V_PropList
{ CnvOK }, // any
{ CnvError }, // int NEVER!
{ CnvOK }, // Bool
{ CnvError }, // C4ID NEVER!
{ CnvObject }, // C4Object NEVER!
{ CnvError }, // String NEVER!
{ CnvError }, // Array NEVER!
{ CnvOK }, // PropList same
{ CnvError }, // pC4Value NEVER!
},
{ // C4V_pC4Value - resolve reference and retry type check
@ -501,6 +534,7 @@ C4VCnvFn C4Value::C4ScriptCnvMap[C4V_Last+1][C4V_Last+1] = {
{ CnvDeref }, // C4ID
{ CnvDeref }, // C4Object
{ CnvDeref }, // String
{ CnvDeref }, // PropList
{ CnvDeref }, // Array
{ CnvOK }, // pC4Value same
},
@ -544,6 +578,8 @@ StdStrBuf C4Value::GetDataString()
else
return StdStrBuf("0"); // (impossible)
}
case C4V_PropList:
return StdStrBuf("FIXME");
case C4V_String:
return (Data.Str && Data.Str->GetCStr()) ? FormatString("\"%s\"", Data.Str->GetCStr()) : StdStrBuf("(nullstring)");
case C4V_Array:
@ -601,12 +637,12 @@ void C4Value::DenumeratePointer()
if(Type != C4V_C4ObjectEnum && !Inside(Data.Int, C4EnumPointer1, C4EnumPointer2)) return;
// get obj id, search object
int iObjID = (Data.Int >= C4EnumPointer1 ? Data.Int - C4EnumPointer1 : Data.Int);
C4Object *pObj = Game.Objects.ObjectPointer(iObjID);
C4PropList *pObj = Game.Objects.ObjectPointer(iObjID);
if (!pObj)
pObj = Game.Objects.InactiveObjects.ObjectPointer(iObjID);
if(pObj)
// set
SetObject(pObj);
SetPropList(pObj);
else
{
// any: guess type
@ -688,10 +724,10 @@ void C4Value::CompileFunc(StdCompiler *pComp)
break;
// object: save object number instead
case C4V_C4Object:
case C4V_C4Object: case C4V_PropList:
#ifdef C4ENGINE
if(!fCompiler)
iTmp = Game.Objects.ObjectNumber(getObj());
iTmp = Game.Objects.ObjectNumber(getPropList());
#else
if(!fCompiler) iTmp = 0;
#endif
@ -796,7 +832,7 @@ bool C4Value::operator == (const C4Value& Value2) const
default:
return false;
}
case C4V_C4Object:
case C4V_C4Object: case C4V_PropList:
return Data == Value2.Data && Type == Value2.Type;
case C4V_String:
return Type == Value2.Type && Data.Str == Value2.Data.Str;