script implementation of GetComponent and SetComponent

This allows to remove the engine functionality and is based on the property Components = [[def1, amount1], [def2, amount2], ...]. Follow up commits will remove the engine functionality.
qteditor
Maikel de Vries 2016-04-30 22:41:15 +02:00
parent c40edd3fbd
commit 4833f839d2
5 changed files with 128 additions and 44 deletions

View File

@ -185,6 +185,11 @@ Stand = {
<col>bool</col>
<col>True or false. If true, <emlink href="definition/cnat.html">ContactCalls</emlink> are called in the object script.</col>
</row>
<row>
<literal_col>Components</literal_col>
<col>array</col>
<col>List of definitions and counts specifying the components of an object. Example: Components = [[Rock, 1], [Wood, 3]];</col>
</row>
</table>
</text>
</part>

View File

@ -23,26 +23,15 @@
<desc>Index of the component to be returned. This parameter is ignored if component is specified. Returns the id of the indicated component which can then be used to determine the count in a subsequent call to GetComponent.</desc>
<optional />
</param>
<param>
<type>object</type>
<name>obj</name>
<desc>Object of which to determine components. Can be <code>nil</code> in local calls. If definition is specified, this parameter is ignored.</desc>
<optional />
</param>
<param>
<type>id</type>
<name>definition</name>
<desc>Definition of which to determine components. If <code>nil</code>, the specified object is checked instead.</desc>
<optional />
</param>
</params>
</syntax>
<desc>Used to determine object components.</desc>
<remark>Also see <emlink href="definition/properties.html">Properties</emlink>.</remark>
<examples>
<example>
<code>var i,cid,num;
<funclink>while</funclink> (id = GetComponent(nil, i++, nil, <funclink>GetID</funclink>()))
if ((num = GetComponent(id) - GetComponent(id, 0, nil, <funclink>GetID</funclink>())) &gt; 0)
<funclink>while</funclink> (id = <funclink>GetID</funclink>()->GetComponent(nil, i++))
if ((num = GetComponent(id) - <funclink>GetID</funclink>()->GetComponent(id)) &gt; 0)
<funclink>while</funclink> (num--) <funclink>CreateObject</funclink>(id);</code>
<text>Creates all components which are still missing in the calling object (e.g. in a construction site) in front of the object.</text>
</example>

View File

@ -23,8 +23,8 @@
</param>
</params>
</syntax>
<desc>Sets the component count of the calling object.</desc>
<remark>Also see <emlink href="definition/defcore.html">DefCore</emlink>.</remark>
<desc>Sets the component count of the calling object or definition.</desc>
<remark>Also see <emlink href="definition/properties.html">Properties</emlink>.</remark>
<related>
<funclink>GetComponent</funclink>
<funclink>Split2Components</funclink>

View File

@ -0,0 +1,118 @@
/**
Components.c
Handles the components of an object, which are a property of the object / definition.
Components are a property of the form
local Components = [[def1, cnt1], [def2, cnt2], ...];
which can be modified directly or via the script functions in this file:
SetComponent2(id component, int count)
GetComponent(id component, int index)
Split2Components()
@author Maikel
*/
// Sets the component of an object or definition.
global func SetComponent(id component, int count)
{
// Safety: can only be called from object or definition context.
if (!this || (GetType(this) != C4V_C4Object && GetType(this) != C4V_Def))
return FatalError(Format("SetComponent must be called from object or definition context and not from %v", this));
// Safety: component must be specified.
if (!component || GetType(component) != C4V_Def)
return FatalError(Format("First parameter (id component) of SetComponent must be a definition but was %v.", component));
// Ensure count is non-negative.
count = Max(count, 0);
// Initialize Components if it does not exist yet.
if (!this.Components || GetType(this.Components) != C4V_Array)
this.Components = [];
// Loop over all existing components and change count if the specified one has been found.
for (var entry in this.Components)
{
if (GetType(entry) != C4V_Array || GetLength(entry) < 2)
continue;
if (entry[0] == component)
{
entry[1] = count;
return;
}
}
// If it did not succeed changing an existing component, then append the new component.
PushBack(this.Components, [component, count]);
return;
}
// Returns the amount if the component parameter is specified. If the component parameter is nil
// it returns the definition of the component for the given index.
global func GetComponent(id component, int index)
{
// Safety: can only be called from object or definition context.
if (!this || (GetType(this) != C4V_C4Object && GetType(this) != C4V_Def))
return FatalError(Format("GetComponent must be called from object or definition context and not from %v", this));
// If component is specified return the count for that definition.
if (GetType(component) == C4V_Def)
{
if (!this.Components || GetType(this.Components) != C4V_Array)
return 0;
for (var entry in this.Components)
{
if (GetType(entry) != C4V_Array || GetLength(entry) < 2)
continue;
if (entry[0] == component)
return entry[1];
}
return 0;
}
// If component is not specified return the definition of the component at the index.
if (!this.Components || GetType(this.Components) != C4V_Array)
return;
// Ensure index is valid.
index = Max(index, 0);
var cnt = 0;
for (var entry in this.Components)
{
if (GetType(entry) != C4V_Array || GetLength(entry) < 2)
continue;
if (index == cnt)
return entry[0];
cnt++;
}
return;
}
// Splits the calling object into its components.
global func Split2Components()
{
// Safety: can only be called from object context.
if (!this || GetType(this) != C4V_C4Object)
return FatalError(Format("Split2Components must be called from object context and not from %v", this));
// Transfer all contents to container.
var ctr = Contained();
while (Contents())
if (!ctr || !Contents()->Enter(ctr))
Contents()->Exit();
// Split components.
for (var i = 0, compid; compid = GetComponent(nil, i); ++i)
for (var j = 0; j < GetComponent(compid); ++j)
{
var comp = CreateObjectAbove(compid, nil, nil, GetOwner());
if (OnFire()) comp->Incinerate();
if (!ctr || !comp->Enter(ctr))
{
comp->SetR(Random(360));
comp->SetXDir(Random(3) - 1);
comp->SetYDir(Random(3) - 1);
comp->SetRDir(Random(3) - 1);
}
}
return RemoveObject();
}

View File

@ -298,34 +298,6 @@ global func RemoveAll(p, ...)
return cnt;
}
// Splits the calling object into its components.
global func Split2Components()
{
if (!this)
return false;
var ctr = Contained();
// Transfer all contents to container.
while (Contents())
if (!ctr || !Contents()->Enter(ctr))
Contents()->Exit();
// Split components.
for (var i = 0, compid; compid = GetComponent(nil, i); ++i)
for (var j = 0; j < GetComponent(compid); ++j)
{
var comp = CreateObjectAbove(compid, nil, nil, GetOwner());
if (OnFire()) comp->Incinerate();
if (!ctr || !comp->Enter(ctr))
{
comp->SetR(Random(360));
comp->SetXDir(Random(3) - 1);
comp->SetYDir(Random(3) - 1);
comp->SetRDir(Random(3) - 1);
}
}
RemoveObject();
return;
}
// Pulls an object above ground if it was buried (e.g. by PlaceVegetation).
// The object must have 'Bottom' and 'Center' CNAT to use this.
// (bottom is the point which should be buried, center the lowest point that must not be buried)