Merge default into rope
|
@ -530,6 +530,7 @@ set(OC_CLONK_SOURCES
|
|||
src/script/C4AulDefFunc.h
|
||||
src/script/C4AulExec.cpp
|
||||
src/script/C4AulExec.h
|
||||
src/script/C4AulFunc.cpp
|
||||
src/script/C4AulFunc.h
|
||||
src/script/C4Aul.h
|
||||
src/script/C4AulLink.cpp
|
||||
|
@ -957,6 +958,7 @@ add_executable(c4script
|
|||
src/lib/C4Random.cpp
|
||||
src/script/C4Aul.cpp
|
||||
src/script/C4AulExec.cpp
|
||||
src/script/C4AulFunc.cpp
|
||||
src/script/C4AulLink.cpp
|
||||
src/script/C4AulParse.cpp
|
||||
src/script/C4StringTable.cpp
|
||||
|
@ -1093,9 +1095,6 @@ endforeach()
|
|||
|
||||
if(CMAKE_COMPILER_IS_GNUCXX)
|
||||
include(GccPchSupport)
|
||||
if(NOT DEFINED USE_GCC_PCH)
|
||||
message("Using GCC precompiled headers! USE_GCC_PCH=Off to disable.")
|
||||
endif()
|
||||
option(USE_GCC_PCH "Use GCC precompiled headers" ON)
|
||||
endif()
|
||||
if(USE_GCC_PCH)
|
||||
|
|
|
@ -511,6 +511,7 @@ src/script/C4AulDebug.h \
|
|||
src/script/C4AulDefFunc.h \
|
||||
src/script/C4AulExec.cpp \
|
||||
src/script/C4AulExec.h \
|
||||
src/script/C4AulFunc.cpp \
|
||||
src/script/C4AulFunc.h \
|
||||
src/script/C4Aul.h \
|
||||
src/script/C4AulLink.cpp \
|
||||
|
@ -687,6 +688,7 @@ src/lib/C4Real.cpp \
|
|||
src/lib/C4Random.cpp \
|
||||
src/script/C4Aul.cpp \
|
||||
src/script/C4AulExec.cpp \
|
||||
src/script/C4AulFunc.cpp \
|
||||
src/script/C4AulLink.cpp \
|
||||
src/script/C4AulParse.cpp \
|
||||
src/script/C4StringTable.cpp \
|
||||
|
|
|
@ -72,7 +72,6 @@
|
|||
</examples>
|
||||
<related>
|
||||
<funclink>InsertMaterial</funclink>
|
||||
<funclink>SetLandscapePixel</funclink>
|
||||
</related>
|
||||
</func>
|
||||
<author>Sven2</author><date>2002-05</date>
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
<?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>GetProperties</title>
|
||||
<category>Objects</category>
|
||||
<subcat>Properties</subcat>
|
||||
<version>5.3 OC</version>
|
||||
<syntax>
|
||||
<rtype>array</rtype>
|
||||
<params>
|
||||
<param>
|
||||
<type>proplist</type>
|
||||
<name>object</name>
|
||||
<desc>Object to request property from, <code>nil</code> in local calls.</desc>
|
||||
<optional />
|
||||
</param>
|
||||
</params>
|
||||
</syntax>
|
||||
<desc>Returns the names of all properties of <code>object</code>.</desc>
|
||||
<related><funclink>SetProperty</funclink></related>
|
||||
<related><funclink>GetProperty</funclink></related>
|
||||
<examples>
|
||||
<example>
|
||||
<code>GetProperties({foo = 1, bar = 2}) == ["bar", "foo"]</code>
|
||||
</example>
|
||||
</examples>
|
||||
</func>
|
||||
<author>Günther</author><date>2012</date>
|
||||
</funcs>
|
|
@ -27,6 +27,7 @@
|
|||
</syntax>
|
||||
<desc>Returns the property <code>key</code> of <code>object</code>.</desc>
|
||||
<related><funclink>SetProperty</funclink></related>
|
||||
<related><funclink>GetProperties</funclink></related>
|
||||
</func>
|
||||
<author>Günther</author><date>2009-05</date>
|
||||
</funcs>
|
||||
|
|
|
@ -1,40 +0,0 @@
|
|||
<?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>SetLandscapePixel</title>
|
||||
<category>Landscape</category>
|
||||
<version>5.1 OC</version>
|
||||
<syntax>
|
||||
<rtype>bool</rtype>
|
||||
<params>
|
||||
<param>
|
||||
<type>int</type>
|
||||
<name>x</name>
|
||||
<desc>X position of the pixel to be set; relative coordinates in local calls</desc>
|
||||
</param>
|
||||
<param>
|
||||
<type>int</type>
|
||||
<name>y</name>
|
||||
<desc>Y position of the pixel to be set; relative coordinates in local calls</desc>
|
||||
</param>
|
||||
<param>
|
||||
<type>int</type>
|
||||
<name>dwValue</name>
|
||||
<desc>32 bit color value of the pixel</desc>
|
||||
</param>
|
||||
</params>
|
||||
</syntax>
|
||||
<desc>Sets a pixel in the landscape. Not available in the old 8 bit graphics system.</desc>
|
||||
<examples>
|
||||
<example>
|
||||
<code>SetLandscapePixel(0, 0, <funclink>RGB</funclink>(185, 127, 0));</code>
|
||||
<text>Colors the landscape pixel directly behind the calling object brown.</text>
|
||||
</example>
|
||||
</examples>
|
||||
<related><funclink>RGB</funclink></related>
|
||||
</func>
|
||||
<author>Sven2</author><date>2002-04</date>
|
||||
</funcs>
|
|
@ -1,42 +0,0 @@
|
|||
/* larger dynamite explosion */
|
||||
|
||||
#appendto RelaunchContainer
|
||||
|
||||
private func OpenWeaponMenu(object clonk)
|
||||
{
|
||||
if (!menu)
|
||||
{
|
||||
var weapons = WeaponList();
|
||||
if(weapons)
|
||||
{
|
||||
menu = clonk->CreateRingMenu(Clonk, this);
|
||||
for (var weapon in weapons)
|
||||
{
|
||||
if(weapon == Firestone) menu->AddItem(weapon,2);
|
||||
else if(weapon == Dynamite) menu->AddItem(weapon,2);
|
||||
else menu->AddItem(weapon);
|
||||
}
|
||||
menu->Show();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public func Selected(object menu, object selector, bool alt)
|
||||
{
|
||||
if (!selector)
|
||||
return false;
|
||||
|
||||
for (var i = 0; i < selector->GetAmount(); i++)
|
||||
{
|
||||
var newobj = CreateObject(selector->GetSymbol());
|
||||
if (newobj->GetID() == Bow)
|
||||
newobj->CreateContents(Arrow);
|
||||
if (newobj->GetID() == Musket)
|
||||
newobj->CreateContents(LeadShot);
|
||||
Contents()->Collect(newobj);
|
||||
}
|
||||
menu->Show();
|
||||
RelaunchClonk();
|
||||
return true;
|
||||
}
|
|
@ -1,5 +1,3 @@
|
|||
/* larger dynamite explosion */
|
||||
|
||||
#appendto RelaunchContainer
|
||||
|
||||
private func OpenWeaponMenu(object clonk)
|
||||
|
@ -14,30 +12,10 @@ private func OpenWeaponMenu(object clonk)
|
|||
{
|
||||
if(weapon == Firestone) menu->AddItem(weapon,2);
|
||||
else if(weapon == Dynamite) menu->AddItem(weapon,2);
|
||||
else menu->AddItem(weapon);
|
||||
else menu->AddItem(weapon, 1);
|
||||
}
|
||||
menu->Show();
|
||||
menu->SetUncloseable();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public func Selected(object menu, object selector, bool alt)
|
||||
{
|
||||
if (!selector)
|
||||
return false;
|
||||
|
||||
for (var i = 0; i < selector->GetAmount(); i++)
|
||||
{
|
||||
var newobj = CreateObject(selector->GetSymbol());
|
||||
if (newobj->GetID() == Bow)
|
||||
newobj->CreateContents(Arrow);
|
||||
if (newobj->GetID() == Musket)
|
||||
newobj->CreateContents(LeadShot);
|
||||
Contents()->Collect(newobj);
|
||||
}
|
||||
menu->Show();
|
||||
RelaunchClonk();
|
||||
return true;
|
||||
}
|
|
@ -64,9 +64,9 @@ public func IsProjectileTarget(target,shooter)
|
|||
|
||||
public func OnProjectileHit(object shot)
|
||||
{
|
||||
DoFireworks();
|
||||
var gol = FindObject(Find_ID(Goal_SaveTheWindmills));
|
||||
if(gol) gol->IncShotScore(shot->GetController());
|
||||
DoFireworks();
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
|
@ -12,22 +12,22 @@ Rules=Rule_TeamAccount=1
|
|||
[Player1]
|
||||
Wealth=0
|
||||
Crew=Clonk=1
|
||||
Knowledge=Idol=1;Foundry=1;SteamEngine=1;ToolsWorkshop=1;WindGenerator=1;Flagpole=1;Sawmill=1;Elevator=1;Lorry=1;Pickaxe=1;Axe=1;Hammer=1;Shovel=1;Firestone=1;Barrel=1;Dynamite=1;DynamiteBox=1;Loam=1;
|
||||
Knowledge=Idol=1;Foundry=1;SteamEngine=1;ToolsWorkshop=1;WindGenerator=1;Flagpole=1;Sawmill=1;Elevator=1;Lorry=1;Pickaxe=1;Axe=1;Hammer=1;Shovel=1;ToolsWorkshop_SplitFirestone=1;Barrel=1;Dynamite=1;DynamiteBox=1;Loam=1;
|
||||
|
||||
[Player2]
|
||||
Wealth=0
|
||||
Crew=Clonk=1
|
||||
Knowledge=Idol=1;Foundry=1;SteamEngine=1;ToolsWorkshop=1;WindGenerator=1;Flagpole=1;Sawmill=1;Elevator=1;Lorry=1;Pickaxe=1;Axe=1;Hammer=1;Shovel=1;Firestone=1;Barrel=1;Dynamite=1;DynamiteBox=1;Loam=1;
|
||||
Knowledge=Idol=1;Foundry=1;SteamEngine=1;ToolsWorkshop=1;WindGenerator=1;Flagpole=1;Sawmill=1;Elevator=1;Lorry=1;Pickaxe=1;Axe=1;Hammer=1;Shovel=1;ToolsWorkshop_SplitFirestone=1;Barrel=1;Dynamite=1;DynamiteBox=1;Loam=1;
|
||||
|
||||
[Player3]
|
||||
Wealth=0
|
||||
Crew=Clonk=1
|
||||
Knowledge=Idol=1;Foundry=1;SteamEngine=1;ToolsWorkshop=1;WindGenerator=1;Flagpole=1;Sawmill=1;Elevator=1;Lorry=1;Pickaxe=1;Axe=1;Hammer=1;Shovel=1;Firestone=1;Barrel=1;Dynamite=1;DynamiteBox=1;Loam=1;
|
||||
Knowledge=Idol=1;Foundry=1;SteamEngine=1;ToolsWorkshop=1;WindGenerator=1;Flagpole=1;Sawmill=1;Elevator=1;Lorry=1;Pickaxe=1;Axe=1;Hammer=1;Shovel=1;ToolsWorkshop_SplitFirestone=1;Barrel=1;Dynamite=1;DynamiteBox=1;Loam=1;
|
||||
|
||||
[Player4]
|
||||
Wealth=0
|
||||
Crew=Clonk=1
|
||||
Knowledge=Idol=1;Foundry=1;SteamEngine=1;ToolsWorkshop=1;WindGenerator=1;Flagpole=1;Sawmill=1;Elevator=1;Lorry=1;Pickaxe=1;Axe=1;Hammer=1;Shovel=1;Firestone=1;Barrel=1;Dynamite=1;DynamiteBox=1;Loam=1;
|
||||
Knowledge=Idol=1;Foundry=1;SteamEngine=1;ToolsWorkshop=1;WindGenerator=1;Flagpole=1;Sawmill=1;Elevator=1;Lorry=1;Pickaxe=1;Axe=1;Hammer=1;Shovel=1;ToolsWorkshop_SplitFirestone=1;Barrel=1;Dynamite=1;DynamiteBox=1;Loam=1;
|
||||
|
||||
[Landscape]
|
||||
Sky=Clouds2
|
||||
|
|
|
@ -14,26 +14,26 @@ Rules=Rule_TeamAccount=1;
|
|||
[Player1]
|
||||
Wealth=10
|
||||
Crew=Clonk=2
|
||||
Knowledge=Foundry=1;SteamEngine=1;ToolsWorkshop=1;WindGenerator=1;Flagpole=1;Sawmill=1;Elevator=1;Pump=1;Chest=1;Idol=1;Lorry=1;Pickaxe=1;Axe=1;Hammer=1;Shovel=1;Firestone=1;Barrel=1;Dynamite=1;DynamiteBox=1;Bucket=1;Pipe=1;
|
||||
HomeBaseMaterial=Shovel=2;Pickaxe=2;Axe=2;Hammer=2;Dynamite=10;Loam=10;Wood=20;Metal=10;Clonk=2;Lorry=1;
|
||||
Knowledge=Foundry=1;SteamEngine=1;ToolsWorkshop=1;WindGenerator=1;Flagpole=1;Sawmill=1;Elevator=1;Pump=1;Chest=1;Idol=1;Lorry=1;Pickaxe=1;Axe=1;Hammer=1;Shovel=1;Barrel=1;Dynamite=1;DynamiteBox=1;Bucket=1;Pipe=1;
|
||||
HomeBaseMaterial=Shovel=2;Pickaxe=2;Axe=2;Hammer=2;Dynamite=10;Loam=10;Wood=20;Metal=10;Clonk=2;Lorry=1;ToolsWorkshop_SplitFirestone=1;
|
||||
|
||||
[Player2]
|
||||
Wealth=10
|
||||
Crew=Clonk=2
|
||||
Knowledge=Foundry=1;SteamEngine=1;ToolsWorkshop=1;WindGenerator=1;Flagpole=1;Sawmill=1;Elevator=1;Pump=1;Chest=1;Idol=1;Lorry=1;Pickaxe=1;Axe=1;Hammer=1;Shovel=1;Firestone=1;Barrel=1;Dynamite=1;DynamiteBox=1;Bucket=1;Pipe=1;
|
||||
HomeBaseMaterial=Shovel=2;Pickaxe=2;Axe=2;Hammer=2;Dynamite=10;Loam=10;Wood=20;Metal=10;Clonk=2;Lorry=1;
|
||||
Knowledge=Foundry=1;SteamEngine=1;ToolsWorkshop=1;WindGenerator=1;Flagpole=1;Sawmill=1;Elevator=1;Pump=1;Chest=1;Idol=1;Lorry=1;Pickaxe=1;Axe=1;Hammer=1;Shovel=1;Barrel=1;Dynamite=1;DynamiteBox=1;Bucket=1;Pipe=1;
|
||||
HomeBaseMaterial=Shovel=2;Pickaxe=2;Axe=2;Hammer=2;Dynamite=10;Loam=10;Wood=20;Metal=10;Clonk=2;Lorry=1;ToolsWorkshop_SplitFirestone=1;
|
||||
|
||||
[Player3]
|
||||
Wealth=10
|
||||
Crew=Clonk=2
|
||||
Knowledge=Foundry=1;SteamEngine=1;ToolsWorkshop=1;WindGenerator=1;Flagpole=1;Sawmill=1;Elevator=1;Pump=1;Chest=1;Idol=1;Lorry=1;Pickaxe=1;Axe=1;Hammer=1;Shovel=1;Firestone=1;Barrel=1;Dynamite=1;DynamiteBox=1;Bucket=1;Pipe=1;
|
||||
HomeBaseMaterial=Shovel=2;Pickaxe=2;Axe=2;Hammer=2;Dynamite=10;Loam=10;Wood=20;Metal=10;Clonk=2;Lorry=1;
|
||||
Knowledge=Foundry=1;SteamEngine=1;ToolsWorkshop=1;WindGenerator=1;Flagpole=1;Sawmill=1;Elevator=1;Pump=1;Chest=1;Idol=1;Lorry=1;Pickaxe=1;Axe=1;Hammer=1;Shovel=1;Barrel=1;Dynamite=1;DynamiteBox=1;Bucket=1;Pipe=1;
|
||||
HomeBaseMaterial=Shovel=2;Pickaxe=2;Axe=2;Hammer=2;Dynamite=10;Loam=10;Wood=20;Metal=10;Clonk=2;Lorry=1;ToolsWorkshop_SplitFirestone=1;
|
||||
|
||||
[Player4]
|
||||
Wealth=10
|
||||
Crew=Clonk=2
|
||||
Knowledge=Foundry=1;SteamEngine=1;ToolsWorkshop=1;WindGenerator=1;Flagpole=1;Sawmill=1;Elevator=1;Pump=1;Chest=1;Idol=1;Lorry=1;Pickaxe=1;Axe=1;Hammer=1;Shovel=1;Firestone=1;Barrel=1;Dynamite=1;DynamiteBox=1;Bucket=1;Pipe=1;
|
||||
HomeBaseMaterial=Shovel=2;Pickaxe=2;Axe=2;Hammer=2;Dynamite=10;Loam=10;Wood=20;Metal=10;Clonk=2;Lorry=1;
|
||||
Knowledge=Foundry=1;SteamEngine=1;ToolsWorkshop=1;WindGenerator=1;Flagpole=1;Sawmill=1;Elevator=1;Pump=1;Chest=1;Idol=1;Lorry=1;Pickaxe=1;Axe=1;Hammer=1;Shovel=1;Barrel=1;Dynamite=1;DynamiteBox=1;Bucket=1;Pipe=1;
|
||||
HomeBaseMaterial=Shovel=2;Pickaxe=2;Axe=2;Hammer=2;Dynamite=10;Loam=10;Wood=20;Metal=10;Clonk=2;Lorry=1;ToolsWorkshop_SplitFirestone=1;
|
||||
|
||||
[Landscape]
|
||||
InEarth=Rock=1;Firestone=3;Loam=2
|
||||
|
|
|
@ -13,16 +13,13 @@ protected func Initialize()
|
|||
goal->SetWealthGoal(400);
|
||||
|
||||
// Place some trees.
|
||||
for (var i = 0; i < 16 + Random(4); i++)
|
||||
PlaceVegetation(Tree_Coniferous, 0, LandscapeHeight() / 3, LandscapeWidth(), LandscapeHeight(), 1000 * (61 + Random(40)));
|
||||
|
||||
// place some sprout berries
|
||||
var bush = PlaceVegetation(SproutBerryBush, 0, LandscapeHeight() / 3, LandscapeWidth(), LandscapeHeight(), 100000);
|
||||
if(bush)
|
||||
for (var i = 0; i < 2; i++)
|
||||
PlaceVegetation(SproutBerryBush, bush->GetX() - 200, bush->GetY() - 200, 400, 400, 100000);
|
||||
//Tree_Coniferous->Place(16+Random(4), Rectangle(0,LandscapeHeight()/3, LandscapeWidth(), LandscapeHeight()));
|
||||
PlaceForest([Tree_Coniferous, SproutBerryBush],0, LandscapeHeight()/2+50,nil, true);
|
||||
|
||||
PlaceGrass(100);
|
||||
|
||||
|
||||
CreateEnvironmentObjects("Temperate");
|
||||
|
||||
// Set time of day to evening and create some clouds and celestials.
|
||||
Cloud->Place(10);
|
||||
Cloud->SetPrecipitation("Water", 15);
|
||||
|
|
|
@ -14,25 +14,25 @@ Rules=Rule_TeamAccount=1;
|
|||
[Player1]
|
||||
Wealth=40
|
||||
Crew=Clonk=2
|
||||
Knowledge=Idol=1;Foundry=1;SteamEngine=1;ToolsWorkshop=1;WindGenerator=1;Flagpole=1;Sawmill=1;Elevator=1;Lorry=1;Pickaxe=1;Axe=1;Hammer=1;Shovel=1;Firestone=1;Barrel=1;Dynamite=1;DynamiteBox=1;Bucket=1;
|
||||
Knowledge=Idol=1;Foundry=1;SteamEngine=1;ToolsWorkshop=1;WindGenerator=1;Flagpole=1;Sawmill=1;Elevator=1;Lorry=1;Pickaxe=1;Axe=1;Hammer=1;Shovel=1;ToolsWorkshop_SplitFirestone=1;Barrel=1;Dynamite=1;DynamiteBox=1;Bucket=1;
|
||||
HomeBaseMaterial=Shovel=2;Pickaxe=2;Axe=2;Hammer=2;Dynamite=10;Loam=10;Wood=20;Metal=10;Clonk=2;Lorry=1;
|
||||
|
||||
[Player2]
|
||||
Wealth=40
|
||||
Crew=Clonk=2
|
||||
Knowledge=Idol=1;Foundry=1;SteamEngine=1;ToolsWorkshop=1;WindGenerator=1;Flagpole=1;Sawmill=1;Elevator=1;Lorry=1;Pickaxe=1;Axe=1;Hammer=1;Shovel=1;Firestone=1;Barrel=1;Dynamite=1;DynamiteBox=1;Bucket=1;
|
||||
Knowledge=Idol=1;Foundry=1;SteamEngine=1;ToolsWorkshop=1;WindGenerator=1;Flagpole=1;Sawmill=1;Elevator=1;Lorry=1;Pickaxe=1;Axe=1;Hammer=1;Shovel=1;ToolsWorkshop_SplitFirestone=1;Barrel=1;Dynamite=1;DynamiteBox=1;Bucket=1;
|
||||
HomeBaseMaterial=Shovel=2;Pickaxe=2;Axe=2;Hammer=2;Dynamite=10;Loam=10;Wood=20;Metal=10;Clonk=2;Lorry=1;
|
||||
|
||||
[Player3]
|
||||
Wealth=40
|
||||
Crew=Clonk=2
|
||||
Knowledge=Idol=1;Foundry=1;SteamEngine=1;ToolsWorkshop=1;WindGenerator=1;Flagpole=1;Sawmill=1;Elevator=1;Lorry=1;Pickaxe=1;Axe=1;Hammer=1;Shovel=1;Firestone=1;Barrel=1;Dynamite=1;DynamiteBox=1;Bucket=1;
|
||||
Knowledge=Idol=1;Foundry=1;SteamEngine=1;ToolsWorkshop=1;WindGenerator=1;Flagpole=1;Sawmill=1;Elevator=1;Lorry=1;Pickaxe=1;Axe=1;Hammer=1;Shovel=1;ToolsWorkshop_SplitFirestone=1;Barrel=1;Dynamite=1;DynamiteBox=1;Bucket=1;
|
||||
HomeBaseMaterial=Shovel=2;Pickaxe=2;Axe=2;Hammer=2;Dynamite=10;Loam=10;Wood=20;Metal=10;Clonk=2;Lorry=1;
|
||||
|
||||
[Player4]
|
||||
Wealth=40
|
||||
Crew=Clonk=2
|
||||
Knowledge=Idol=1;Foundry=1;SteamEngine=1;ToolsWorkshop=1;WindGenerator=1;Flagpole=1;Sawmill=1;Elevator=1;Lorry=1;Pickaxe=1;Axe=1;Hammer=1;Shovel=1;Firestone=1;Barrel=1;Dynamite=1;DynamiteBox=1;Bucket=1;
|
||||
Knowledge=Idol=1;Foundry=1;SteamEngine=1;ToolsWorkshop=1;WindGenerator=1;Flagpole=1;Sawmill=1;Elevator=1;Lorry=1;Pickaxe=1;Axe=1;Hammer=1;Shovel=1;ToolsWorkshop_SplitFirestone=1;Barrel=1;Dynamite=1;DynamiteBox=1;Bucket=1;
|
||||
HomeBaseMaterial=Shovel=2;Pickaxe=2;Axe=2;Hammer=2;Dynamite=10;Loam=10;Wood=20;Metal=10;Clonk=2;Lorry=1;
|
||||
|
||||
[Landscape]
|
||||
|
|
|
@ -38,12 +38,10 @@ protected func Initialize()
|
|||
// TODO: Make sure lorry stays on mountains.
|
||||
|
||||
// Place some coniferous trees, but only up to 2/3 of the mountain.
|
||||
for (var i = 0; i < 16 + Random(5); i++)
|
||||
PlaceVegetation(Tree_Coniferous, 0, LandscapeHeight() / 3, LandscapeWidth(), 2 * LandscapeHeight() / 3, 1000 * (61 + Random(40)));
|
||||
Tree_Coniferous->Place(16+Random(5), Rectangle(0,LandscapeHeight()/3, LandscapeWidth(), 2*LandscapeHeight()/3));
|
||||
|
||||
// Some mushrooms as source of food.
|
||||
for (var i = 0; i < 30 + Random(10); i++)
|
||||
PlaceVegetation(Mushroom, 0, 0, LandscapeWidth(), LandscapeHeight());
|
||||
Mushroom->Place(30+Random(10));
|
||||
|
||||
// Set time of day to evening and create some clouds and celestials.
|
||||
Cloud->Place(20);
|
||||
|
|
|
@ -13,28 +13,28 @@ ValueOverloads=Nugget=10;GoldBar=50;
|
|||
[Player1]
|
||||
Wealth=50,0,0,250
|
||||
Crew=Clonk=2
|
||||
Knowledge=Plane_Engine=1;Foundry=1;ToolsWorkshop=1;WindGenerator=1;Flagpole=1;Sawmill=1;Elevator=1;Lorry=1;Pickaxe=1;Axe=1;Hammer=1;Shovel=1;Firestone=1;Barrel=1;Dynamite=1;DynamiteBox=1;LiftTower=1;Pump=1
|
||||
Knowledge=Plane_Engine=1;Foundry=1;ToolsWorkshop=1;WindGenerator=1;Flagpole=1;Sawmill=1;Elevator=1;Lorry=1;Pickaxe=1;Axe=1;Hammer=1;Shovel=1;ToolsWorkshop_SplitFirestone=1;Barrel=1;Dynamite=1;DynamiteBox=1;LiftTower=1;Pump=1
|
||||
HomeBaseMaterial=Loam=99;Wood=5;Metal=3;Shovel=2;Axe=2;Hammer=2;Clonk=5;Bread=5
|
||||
HomeBaseProduction=Loam=10;Wood=5;Metal=3;Shovel=2;Axe=2;Hammer=2;Clonk=5;Bread=5
|
||||
|
||||
[Player2]
|
||||
Wealth=50,0,0,250
|
||||
Crew=Clonk=2
|
||||
Knowledge=Plane_Engine=1;Foundry=1;ToolsWorkshop=1;WindGenerator=1;Flagpole=1;Sawmill=1;Elevator=1;Lorry=1;Pickaxe=1;Axe=1;Hammer=1;Shovel=1;Firestone=1;Barrel=1;Dynamite=1;DynamiteBox=1;LiftTower=1;Pump=1
|
||||
Knowledge=Plane_Engine=1;Foundry=1;ToolsWorkshop=1;WindGenerator=1;Flagpole=1;Sawmill=1;Elevator=1;Lorry=1;Pickaxe=1;Axe=1;Hammer=1;Shovel=1;ToolsWorkshop_SplitFirestone=1;Barrel=1;Dynamite=1;DynamiteBox=1;LiftTower=1;Pump=1
|
||||
HomeBaseMaterial=Loam=99;Wood=5;Metal=3;Shovel=2;Axe=2;Hammer=2;Clonk=5;Bread=5
|
||||
HomeBaseProduction=Loam=10;Wood=5;Metal=3;Shovel=2;Axe=2;Hammer=2;Clonk=5;Bread=5
|
||||
|
||||
[Player3]
|
||||
Wealth=50,0,0,250
|
||||
Crew=Clonk=2
|
||||
Knowledge=Plane_Engine=1;Foundry=1;ToolsWorkshop=1;WindGenerator=1;Flagpole=1;Sawmill=1;Elevator=1;Lorry=1;Pickaxe=1;Axe=1;Hammer=1;Shovel=1;Firestone=1;Barrel=1;Dynamite=1;DynamiteBox=1;LiftTower=1;Pump=1
|
||||
Knowledge=Plane_Engine=1;Foundry=1;ToolsWorkshop=1;WindGenerator=1;Flagpole=1;Sawmill=1;Elevator=1;Lorry=1;Pickaxe=1;Axe=1;Hammer=1;Shovel=1;ToolsWorkshop_SplitFirestone=1;Barrel=1;Dynamite=1;DynamiteBox=1;LiftTower=1;Pump=1
|
||||
HomeBaseMaterial=Loam=99;Wood=5;Metal=3;Shovel=2;Axe=2;Hammer=2;Clonk=5;Bread=5
|
||||
HomeBaseProduction=Loam=10;Wood=5;Metal=3;Shovel=2;Axe=2;Hammer=2;Clonk=5;Bread=5
|
||||
|
||||
[Player4]
|
||||
Wealth=50,0,0,250
|
||||
Crew=Clonk=2
|
||||
Knowledge=Plane_Engine=1;Foundry=1;ToolsWorkshop=1;WindGenerator=1;Flagpole=1;Sawmill=1;Elevator=1;Lorry=1;Pickaxe=1;Axe=1;Hammer=1;Shovel=1;Firestone=1;Barrel=1;Dynamite=1;DynamiteBox=1;LiftTower=1;Pump=1
|
||||
Knowledge=Plane_Engine=1;Foundry=1;ToolsWorkshop=1;WindGenerator=1;Flagpole=1;Sawmill=1;Elevator=1;Lorry=1;Pickaxe=1;Axe=1;Hammer=1;Shovel=1;ToolsWorkshop_SplitFirestone=1;Barrel=1;Dynamite=1;DynamiteBox=1;LiftTower=1;Pump=1
|
||||
HomeBaseMaterial=Loam=99;Wood=5;Metal=3;Shovel=2;Axe=2;Hammer=2;Clonk=5;Bread=5
|
||||
HomeBaseProduction=Loam=10;Wood=5;Metal=3;Shovel=2;Axe=2;Hammer=2;Clonk=5;Bread=5
|
||||
|
||||
|
|
|
@ -9,6 +9,12 @@ uniform sampler3D materialTex;
|
|||
// Resolution of the landscape texture
|
||||
uniform vec2 resolution;
|
||||
|
||||
// Use sampler if the GPU doesn't support enough uniforms to
|
||||
// get the matMap as an array
|
||||
#if MAX_FRAGMENT_UNIFORM_COMPONENTS < 259
|
||||
#define BROKEN_ARRAYS_WORKAROUND
|
||||
#endif
|
||||
|
||||
// Texture map
|
||||
#ifdef BROKEN_ARRAYS_WORKAROUND
|
||||
uniform sampler1D matMapTex;
|
||||
|
|
Before Width: | Height: | Size: 51 KiB After Width: | Height: | Size: 51 KiB |
|
@ -278,16 +278,31 @@ protected func Evaporation()
|
|||
//Shades the clouds based on iSize: the water density value of the cloud.
|
||||
private func ShadeCloud()
|
||||
{
|
||||
var shade = Min((rain+50)*425/1000, 255);
|
||||
var cloudAlpha = Min((rain+50)*425/1000, 255);
|
||||
if(rain > 600) cloudAlpha = 255;
|
||||
|
||||
//from RequestAlpha function
|
||||
if(requestAlpha != nil){
|
||||
cloudAlpha = cloudAlpha - (255 - requestAlpha);
|
||||
if(cloudAlpha < 0) cloudAlpha = 0;
|
||||
}
|
||||
|
||||
var shade2 = Min(rain-600, 255);
|
||||
|
||||
if (rain <= 600)
|
||||
SetObjAlpha(shade);
|
||||
if (rain > 600)
|
||||
SetClrModulation(RGBa(255-shade2, 255-shade2, 255-shade2, 255));
|
||||
|
||||
if (rain <= 600)
|
||||
SetObjAlpha(cloudAlpha);
|
||||
if (rain > 600)
|
||||
SetClrModulation(RGBa(255-shade2, 255-shade2, 255-shade2, cloudAlpha));
|
||||
return;
|
||||
}
|
||||
|
||||
//Utilized by time to make clouds invisible at night
|
||||
local requestAlpha;
|
||||
|
||||
public func RequestAlpha(int alpha){
|
||||
requestAlpha = alpha;
|
||||
}
|
||||
|
||||
local ActMap = {
|
||||
Fly = {
|
||||
Prototype = Action,
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/*--
|
||||
/**--
|
||||
Time Controller
|
||||
Author:Ringwall
|
||||
|
||||
|
@ -122,37 +122,74 @@ protected func FxIntTimeCycleTimer(object target)
|
|||
return 1;
|
||||
}
|
||||
|
||||
// Adjusts the sky, celestial and others to the current time.
|
||||
// Adjusts the sky, celestial and others to the current time. Use SetTime() at runtime, not this.
|
||||
private func AdjustToTime()
|
||||
{
|
||||
var skyshade;
|
||||
var skyshade = [0,0,0,0]; //R,G,B,A
|
||||
var nightcolour = [10,25,40]; //default darkest-night colour
|
||||
|
||||
//Darkness of night dependant on moon-phase
|
||||
var satellite = FindObject(Find_ID(Moon)); //pointer to the moon
|
||||
if(satellite){
|
||||
var phase = satellite->GetPhase();
|
||||
|
||||
if(phase == 1 || phase == 5) nightcolour = [4,7,9]; //super dark when moon is crescent
|
||||
else if(phase == 2 || phase == 4) nightcolour = [5,15,25]; //somewhat dark when moon is half
|
||||
else nightcolour = [10,25,40]; //deep-blue when moon is full
|
||||
}
|
||||
|
||||
|
||||
// Sunrise
|
||||
if (Inside(time, time_set["SunriseStart"], time_set["SunriseEnd"]))
|
||||
{
|
||||
skyshade = Sin((GetTime() - 180) / 4, 255);
|
||||
skyshade[0] = Sin((GetTime() - time_set["SunriseStart"]) / 4, 255 - nightcolour[0]) + nightcolour[0];
|
||||
skyshade[1] = Sin((GetTime() - time_set["SunriseStart"]) / 4, 255 - nightcolour[1]) + nightcolour[1];
|
||||
skyshade[2] = Sin((GetTime() - time_set["SunriseStart"]) / 4, 255 - nightcolour[2]) + nightcolour[2];
|
||||
|
||||
skyshade[3] = Sin((GetTime() - time_set["SunriseStart"]) / 4, 255);
|
||||
if (time == 540)
|
||||
if (FindObject(Find_ID(Moon)))
|
||||
FindObject(Find_ID(Moon))->Phase();
|
||||
if (satellite)
|
||||
satellite->Phase();
|
||||
}
|
||||
// Day
|
||||
else if (Inside(time, time_set["SunriseEnd"], time_set["SunsetStart"]))
|
||||
skyshade = 255;
|
||||
{
|
||||
skyshade[0] = 255;
|
||||
skyshade[1] = 255;
|
||||
skyshade[2] = 255;
|
||||
|
||||
skyshade[3] = 255;
|
||||
}
|
||||
//Sunset
|
||||
else if (Inside(time, time_set["SunsetStart"], time_set["SunsetEnd"]))
|
||||
skyshade = 255 - Sin((GetTime() - 900) / 4, 255);
|
||||
{
|
||||
skyshade[0] = 255 - Sin((GetTime() - time_set["SunsetStart"]) / 4, 255 - nightcolour[0]);
|
||||
skyshade[1] = 255 - Sin((GetTime() - time_set["SunsetStart"]) / 4, 255 - nightcolour[1]);
|
||||
skyshade[2] = 255 - Sin((GetTime() - time_set["SunsetStart"]) / 4, 255 - nightcolour[2]);
|
||||
|
||||
skyshade[3] = 255 - Sin((GetTime() - time_set["SunsetStart"]) / 4, 255);
|
||||
}
|
||||
// Night
|
||||
else if (time > time_set["SunsetEnd"] || time < time_set["SunriseStart"])
|
||||
skyshade = 0;
|
||||
{
|
||||
skyshade[0] = nightcolour[0];
|
||||
skyshade[1] = nightcolour[1];
|
||||
skyshade[2] = nightcolour[2];
|
||||
|
||||
skyshade[3] = 0;
|
||||
}
|
||||
|
||||
// Shade sky.
|
||||
SetSkyAdjust(RGB(skyshade, skyshade, skyshade));
|
||||
SetSkyAdjust(RGB(skyshade[0], skyshade[1], skyshade[2]));
|
||||
|
||||
// Adjust celestial objects.
|
||||
for (var celestial in FindObjects(Find_Func("IsCelestial")))
|
||||
celestial->SetObjAlpha(255 - skyshade);
|
||||
celestial->SetObjAlpha(255 - skyshade[3]);
|
||||
|
||||
// Adjust clouds, TODO remedie this special case of white clouds on black sky.
|
||||
|
||||
// Adjust clouds
|
||||
for(var cloud in FindObjects(Find_ID(Cloud))){
|
||||
cloud->RequestAlpha(skyshade[3]);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
[DefCore]
|
||||
id=Environment
|
||||
Version=4,10,0,0
|
||||
Category=C4D_StaticBack
|
||||
Width=1
|
||||
Height=1
|
||||
Offset=-1,-1
|
||||
|
After Width: | Height: | Size: 91 B |
|
@ -0,0 +1,108 @@
|
|||
/**
|
||||
VisualEnvironment
|
||||
Cares about the placement of purely visual objects.
|
||||
The placement uses categories and thus is forward-compatible.
|
||||
*/
|
||||
|
||||
// this proplist defines the selectable environment objects
|
||||
// "ID" might be nil or a valid id
|
||||
// "includes" specifies what objects are created when the selected object is created (no specific order)
|
||||
// any entry of "Environment_Attributes" might be nil or false instead of a proplist
|
||||
// nil will log a warning on creating that object and false will silently ignore it
|
||||
// thus something like Environment_Attributes["Foobar"] = false; will work to disable certain features
|
||||
static const Environment_Attributes =
|
||||
{
|
||||
All = {
|
||||
ID = nil,
|
||||
includes = ["Temperate", "Desert"],
|
||||
},
|
||||
|
||||
Temperate = {
|
||||
ID = nil,
|
||||
includes = ["Zicadas", "Frogs", "BackgroundBirds"],
|
||||
},
|
||||
|
||||
Desert = {
|
||||
ID = nil,
|
||||
includes = ["Zicadas"],
|
||||
},
|
||||
|
||||
Zicadas = {
|
||||
ID = Environment_Zicadas,
|
||||
},
|
||||
|
||||
Frogs = {
|
||||
ID = nil /* not yet implemented: Environment_Frogs */,
|
||||
},
|
||||
|
||||
BackgroundBirds = {
|
||||
ID = nil /* not yet implemented: Environment_BackgroundBirds */,
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
|
||||
// provides a simple interface for creation of environment objects and decoration with standard values
|
||||
// the objects are placed on a best-effort-basis. That means f.e. objects that rely on water will not be placed when there is no water in the landscape.
|
||||
global func CreateEnvironmentObjects(
|
||||
what /* array of strings or single string: what objects will be created, standard: "All" */
|
||||
, proplist area /* area where objects will be created, format {x = ??, y = ??, w = ??, h = ??}, standard: whole landscape */
|
||||
, int amount_percentage /* what percentage of the standard amount will be created, standard: 100 */
|
||||
)
|
||||
{
|
||||
/*
|
||||
// half desert, half temperate - but birds everywhere
|
||||
CreateEnvironmentObjects(["Desert", "BackgroundBirds"], Rectangle(0, 0, LandscapeWidth()/2, LandscapeHeight()));
|
||||
CreateEnvironmentObjects("Temperate", Rectangle(LandscapeWidth()/2, 0, LandscapeWidth()/2, LandscapeHeight()));
|
||||
*/
|
||||
what = what ?? "All";
|
||||
area = area ?? Rectangle(0, 0, LandscapeWidth(), LandscapeHeight());
|
||||
amount_percentage = amount_percentage ?? 100;
|
||||
|
||||
// might be a string to allow CreateEnvironmentObjects("All")
|
||||
if(GetType(what) != C4V_Array)
|
||||
what = [what];
|
||||
|
||||
// iteratively find all the objects that are included in the selection
|
||||
while(true)
|
||||
{
|
||||
var changed = false;
|
||||
var to_add = [];
|
||||
|
||||
// go through every object in the list
|
||||
for(var obj in what)
|
||||
{
|
||||
var p = Environment_Attributes[obj];
|
||||
if(p == nil) {Log("Warning: Environment object %s does not exist!", obj);}
|
||||
else if(p == false) continue; // disabled by the scenario designer
|
||||
|
||||
// add all objects included to the temporary list if existing
|
||||
if(!p["includes"]) continue;
|
||||
to_add = Concatenate(to_add, p["includes"]);
|
||||
}
|
||||
|
||||
// add every unique item from the temporary list to the object list
|
||||
for(var obj in to_add)
|
||||
{
|
||||
if(IsValueInArray(what, obj)) continue;
|
||||
|
||||
if(!!Environment_Attributes[obj]["includes"])
|
||||
changed = true; // found changes, need further checking
|
||||
|
||||
PushBack(what, obj);
|
||||
}
|
||||
|
||||
if(!changed)
|
||||
break;
|
||||
}
|
||||
|
||||
// now create all the selected objects
|
||||
for(var obj in what)
|
||||
{
|
||||
var p, p_id;
|
||||
if(!(p = Environment_Attributes[obj])) continue;
|
||||
if(!(p_id = p["ID"])) continue;
|
||||
|
||||
p_id->Place(amount_percentage, area);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
[DefCore]
|
||||
id=Environment_Zicadas
|
||||
Version=4,10,0,0
|
||||
Category=C4D_StaticBack
|
||||
Width=1
|
||||
Height=1
|
||||
Offset=-1,-1
|
After Width: | Height: | Size: 91 B |
|
@ -0,0 +1,26 @@
|
|||
/**
|
||||
Zicadas
|
||||
Zicada sounds.
|
||||
*/
|
||||
|
||||
local Name = "$Name$";
|
||||
local Description = "$Description$";
|
||||
|
||||
func Place(int amount_percentage, proplist area)
|
||||
{
|
||||
area = area ?? Rectangle(0, 0, LandscapeWidth(), LandscapeHeight());
|
||||
amount_percentage = amount_percentage ?? 100;
|
||||
|
||||
// calculate amount that has to be placed
|
||||
var amount = LandscapeWidth() / 100;
|
||||
amount = (amount_percentage * amount) / 100;
|
||||
if(!amount) return;
|
||||
|
||||
while(--amount)
|
||||
{
|
||||
// search for zicada spot position
|
||||
// ..
|
||||
// place zicada spot
|
||||
// ..
|
||||
}
|
||||
}
|
|
@ -0,0 +1,2 @@
|
|||
Name=Zikaden
|
||||
Description=Zikadengeräusche.
|
|
@ -0,0 +1,2 @@
|
|||
Name=Zicadas
|
||||
Description=Zicada sounds.
|
|
@ -62,7 +62,7 @@ private func OpenWeaponMenu(object clonk)
|
|||
{
|
||||
menu = clonk->CreateRingMenu(Clonk, this);
|
||||
for (var weapon in weapons)
|
||||
menu->AddItem(weapon);
|
||||
menu->AddItem(weapon, 1);
|
||||
menu->Show();
|
||||
menu->SetUncloseable();
|
||||
}
|
||||
|
@ -96,7 +96,11 @@ public func Selected(object menu, object selector, bool alt)
|
|||
if (!selector)
|
||||
return false;
|
||||
|
||||
for (var i = 0; i < selector->GetAmount(); i++)
|
||||
var amount = selector->GetAmount();
|
||||
if (amount > 1)
|
||||
alt = nil;
|
||||
|
||||
for (var i = 0; i < amount; i++)
|
||||
GiveWeapon(selector->GetSymbol(), alt);
|
||||
|
||||
has_selected = true;
|
||||
|
|
|
@ -21,12 +21,11 @@ public func Update()
|
|||
// Display wealth via text.
|
||||
CustomMessage(Format("@%d", wealth), this, plr, 0, 90);
|
||||
// Display wealth via graphics.
|
||||
var num;
|
||||
if (wealth < 180) num = 4;
|
||||
if (wealth < 120) num = 3;
|
||||
if (wealth < 70) num = 2;
|
||||
if (wealth < 30) num = 1;
|
||||
if (wealth < 10) num = 0;
|
||||
var num = 0;
|
||||
if (wealth >= 10) num = 1;
|
||||
if (wealth >= 30) num = 2;
|
||||
if (wealth >= 70) num = 3;
|
||||
if (wealth >= 120) num = 4;
|
||||
SetGraphics(Format("%d", num));
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -40,12 +40,8 @@ public func SetBG(bool newbg) {
|
|||
|
||||
public func SetNothing() // No item, no image, no whatever, just a plain button
|
||||
{
|
||||
SetAmount(0);
|
||||
SetAmount(nil);
|
||||
SetSymbol();
|
||||
SetGraphics(nil,nil,9);
|
||||
SetGraphics(nil,nil,10);
|
||||
SetGraphics(nil,nil,11);
|
||||
SetGraphics(nil,nil,12);
|
||||
}
|
||||
|
||||
public func SetSize(int s) // in px *1000
|
||||
|
@ -122,9 +118,15 @@ public func SetExtraData(extradata)
|
|||
}
|
||||
public func SetAmount(Amount)
|
||||
{
|
||||
|
||||
amnt=Amount;
|
||||
if(Amount==1) return ;
|
||||
amnt = Amount;
|
||||
if (Amount == nil)
|
||||
{
|
||||
SetGraphics(nil,nil,MI_AMOUNTX_LAYER);
|
||||
SetGraphics(nil,nil,MI_AMOUNT1_LAYER);
|
||||
SetGraphics(nil,nil,MI_AMOUNT10_LAYER);
|
||||
SetGraphics(nil,nil,MI_AMOUNT100_LAYER);
|
||||
return;
|
||||
}
|
||||
var one = Amount%10;
|
||||
var ten = (Amount/10)%10;
|
||||
var hun = (Amount/100)%10;
|
||||
|
|
|
@ -102,14 +102,7 @@ public func AddItem(new_item, int amount, extra)
|
|||
menu_icons[index] = CreateObject(GUI_RingMenu_Icon,0,0,menu_object->GetOwner());
|
||||
menu_icons[index]->SetSymbol(new_item);
|
||||
menu_icons[index]->SetExtraData(extra);
|
||||
if(amount == nil)
|
||||
{
|
||||
menu_icons[index]->SetAmount(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
menu_icons[index]->SetAmount(amount);
|
||||
}
|
||||
menu_icons[index]->SetAmount(amount);
|
||||
menu_icons[index].Visibility = VIS_None;
|
||||
return index;
|
||||
}
|
||||
|
|
|
@ -11,8 +11,7 @@ VertexY=1,-1
|
|||
VertexFriction=20
|
||||
Value=5
|
||||
Mass=10
|
||||
Components=Sulphur=1
|
||||
Components=Sulphur=1;Coal=1
|
||||
Projectile=1
|
||||
Fragile=1
|
||||
Explosive=1
|
||||
|
||||
Explosive=1
|
|
@ -12,8 +12,6 @@ func Hit()
|
|||
Explode(20);
|
||||
}
|
||||
|
||||
public func IsToolProduct() { return true; }
|
||||
|
||||
local Collectible = 1;
|
||||
local Name = "$Name$";
|
||||
local Description = "$Description$";
|
||||
|
|
|
@ -77,7 +77,7 @@ func FxIntFusingTimer()
|
|||
if( (fuse_vertex == 0 && fuse_dir == -1) || (fuse_vertex == GetVertexNum()-1 && fuse_dir == +1))
|
||||
{
|
||||
fuse_call->~OnFuseFinished(this);
|
||||
RemoveObject();
|
||||
if (fuse_call) RemoveObject();
|
||||
return -1;
|
||||
}
|
||||
fuse_x = GetVertex(fuse_vertex, 0)*10;
|
||||
|
|
|
@ -82,6 +82,18 @@ public func GetItems()
|
|||
return inv;
|
||||
}
|
||||
|
||||
/** Returns how many items are in the clonks inventory
|
||||
Does not have to be the same as ContentCounts() because of objects with special handling, like CarryHeavy */
|
||||
public func GetItemCount()
|
||||
{
|
||||
var count = 0;
|
||||
for(var i=0; i < GetLength(inventory); i++)
|
||||
if(inventory[i])
|
||||
count++;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
/** Get the 'i'th item in hands.
|
||||
These are the items that will be used with use-commands. (Left mouse click, etc...) */
|
||||
public func GetHandItem(int i)
|
||||
|
@ -494,7 +506,7 @@ protected func RejectCollect(id objid, object obj)
|
|||
// collection of that object magically disabled?
|
||||
if(GetEffect("NoCollection", obj)) return true;
|
||||
|
||||
// Carry heavy only gets picked up if non held already
|
||||
// Carry heavy only gets picked up if none held already
|
||||
if(obj->~IsCarryHeavy())
|
||||
{
|
||||
if(IsCarryingHeavy())
|
||||
|
@ -540,7 +552,7 @@ protected func RejectCollect(id objid, object obj)
|
|||
public func AllowTransfer(object obj)
|
||||
{
|
||||
// Only check max contents.
|
||||
if (ContentsCount() >= MaxContentsCount())
|
||||
if (GetItemCount() >= MaxContentsCount())
|
||||
return false;
|
||||
|
||||
// don't allow picking up multiple carryheavy-objects
|
||||
|
|
|
@ -181,8 +181,6 @@ func CreateConstructionSite(object clonk, id structure_id, int x, int y, int dir
|
|||
|
||||
// Set owner for CreateConstruction
|
||||
SetOwner(clonk->GetOwner());
|
||||
// Save direction so the structure can ask for it
|
||||
this.constructionDirection = dir;
|
||||
// Create construction site
|
||||
var site;
|
||||
site = CreateObject(ConstructionSite, x, y, Contained()->GetOwner());
|
||||
|
@ -229,9 +227,4 @@ func CreateConstructionSite(object clonk, id structure_id, int x, int y, int dir
|
|||
// Message
|
||||
clonk->Message("$TxtConstructions$", structure_id->GetName());
|
||||
return true;
|
||||
}
|
||||
// Returns the desired direction for a construction
|
||||
func GetConstructionDirection()
|
||||
{
|
||||
return this.constructionDirection;
|
||||
}
|
|
@ -11,21 +11,6 @@ public func IsPlant()
|
|||
return true;
|
||||
}
|
||||
|
||||
/** Chance to reproduce plant. Chances are one out of return value. Default is 500.
|
||||
@return the chance, higher = less chance.
|
||||
*/
|
||||
private func SeedChance() { return 500; }
|
||||
|
||||
/** Distance the seeds may travel. Default is 250.
|
||||
@return the maximum distance.
|
||||
*/
|
||||
private func SeedArea() { return 250; }
|
||||
|
||||
/** The amount of plants allowed within SeedAreaSize. Default is 10.
|
||||
@return the maximum amount of plants.
|
||||
*/
|
||||
private func SeedAmount() { return 10; }
|
||||
|
||||
/** Automated positioning via RootSurface, make sure to call this if needed (in case Construction is overloaded)
|
||||
*/
|
||||
protected func Construction()
|
||||
|
@ -35,6 +20,73 @@ protected func Construction()
|
|||
_inherited(...);
|
||||
}
|
||||
|
||||
/* Placement */
|
||||
|
||||
/** Places the given amount of plants inside the area. If no area is given, the whole landscape is used.
|
||||
@param amount The amount of plants to be created (not necessarily every plant is created).
|
||||
@param rectangle The area where to put the plants.
|
||||
@param settings A proplist defining further setttings: { growth = 100000, keep_area = false }. Growth will get passed over to PlaceVegetation, keep_area will confine the plants and their offspring to rectangle.
|
||||
@return Returns an array of all objects created.
|
||||
*/
|
||||
public func Place(int amount, proplist rectangle, proplist settings)
|
||||
{
|
||||
// No calls to objects, only definitions
|
||||
if (GetType(this) == C4V_C4Object) return;
|
||||
// Default parameters
|
||||
if (!settings) settings = { growth = 100000, keep_area = false };
|
||||
if (!settings.growth) settings.growth = 100000;
|
||||
if (!rectangle)
|
||||
rectangle = Rectangle(0,0, LandscapeWidth(), LandscapeHeight());
|
||||
|
||||
var plants = CreateArray(), plant;
|
||||
for (var i = 0 ; i < amount ; i++)
|
||||
{
|
||||
plant = PlaceVegetation(this, rectangle.x, rectangle.y, rectangle.w, rectangle.h, settings.growth);
|
||||
if (plant)
|
||||
{
|
||||
plants[GetLength(plants)] = plant;
|
||||
if (settings.keep_area)
|
||||
plant->KeepArea(rectangle);
|
||||
}
|
||||
plant = nil;
|
||||
}
|
||||
return plants;
|
||||
}
|
||||
|
||||
/* Reproduction */
|
||||
|
||||
/** Will confine the the plant and its offspring to a certain area.
|
||||
@params rectangle The confinement area.
|
||||
*/
|
||||
func KeepArea(proplist rectangle)
|
||||
{
|
||||
this.Confinement = rectangle;
|
||||
}
|
||||
|
||||
/** Chance to reproduce plant. Chances are one out of return value. Default is 500.
|
||||
@return the chance, higher = less chance.
|
||||
*/
|
||||
private func SeedChance()
|
||||
{
|
||||
return 500;
|
||||
}
|
||||
|
||||
/** Distance the seeds may travel. Default is 250.
|
||||
@return the maximum distance.
|
||||
*/
|
||||
private func SeedArea()
|
||||
{
|
||||
return 250;
|
||||
}
|
||||
|
||||
/** The amount of plants allowed within SeedAreaSize. Default is 10.
|
||||
@return the maximum amount of plants.
|
||||
*/
|
||||
private func SeedAmount()
|
||||
{
|
||||
return 10;
|
||||
}
|
||||
|
||||
/** Reproduction of plants: Called every 2 seconds by a timer.
|
||||
*/
|
||||
public func Seed()
|
||||
|
@ -42,8 +94,10 @@ public func Seed()
|
|||
// Find number of plants in seed area.
|
||||
var size = SeedArea();
|
||||
var amount = SeedAmount();
|
||||
var offset = size / -2;
|
||||
var plant_cnt = ObjectCount(Find_ID(GetID()), Find_InRect(offset, offset, size, size));
|
||||
var area = Rectangle(AbsX(size / -2), AbsY(size / -2), size, size);
|
||||
if (this.Confinement)
|
||||
area = RectangleEnsureWithin(area, this.Confinement);
|
||||
var plant_cnt = ObjectCount(Find_ID(GetID()), Find_InRect(area.x - GetX(), area.y - GetY(), area.w, area.h));
|
||||
// If there are not much plants in the seed area compared to seed amount
|
||||
// the chance of seeding is improved, if there are much the chance is reduced.
|
||||
var chance = SeedChance();
|
||||
|
@ -52,7 +106,7 @@ public func Seed()
|
|||
if (!Random(chance))
|
||||
{
|
||||
// Place the plant but check if it is not close to another one.
|
||||
var plant = PlaceVegetation(GetID(), offset, offset, size, size, 3);
|
||||
var plant = PlaceVegetation(GetID(), area.x - GetX(), area.y - GetY(), area.w, area.h, 3);
|
||||
if (plant)
|
||||
{
|
||||
var neighbour = FindObject(Find_ID(GetID()), Find_Exclude(plant), Sort_Distance(plant->GetX() - GetX(), plant->GetY() - GetY()));
|
||||
|
@ -60,6 +114,8 @@ public func Seed()
|
|||
// Closeness determined by seedarea and amount.
|
||||
if (!Random(distance / (size/amount)))
|
||||
plant->RemoveObject();
|
||||
else if (this.Confinement)
|
||||
plant->KeepArea(this.Confinement);
|
||||
}
|
||||
}
|
||||
return;
|
||||
|
@ -106,7 +162,6 @@ protected func Damage()
|
|||
_inherited(...);
|
||||
}
|
||||
|
||||
|
||||
// restarts the growing of the tree (for example after taking damage)
|
||||
func RestartGrowth(int old_value)
|
||||
{
|
||||
|
|
|
@ -16,16 +16,4 @@ public func Damage(int change, int cause, int cause_plr)
|
|||
return RemoveObject();
|
||||
}
|
||||
return _inherited(change, cause, cause_plr);
|
||||
}
|
||||
|
||||
public func Construction(object creator)
|
||||
{
|
||||
if (creator)
|
||||
{
|
||||
// Set dir according to the direction specified by the creator.
|
||||
var dir = creator->~GetConstructionDirection();
|
||||
if (dir)
|
||||
SetDir(dir);
|
||||
}
|
||||
return _inherited(creator, ...);
|
||||
}
|
|
@ -15,6 +15,7 @@ Mass=30
|
|||
Components=Wood=1
|
||||
SolidMask=0,27,24,2,0,24
|
||||
TopFace=0,0,24,26,0,0
|
||||
Picture=24,0,152,128
|
||||
HorizontalFix=1
|
||||
NoPushEnter=1
|
||||
ContactCalls=1
|
Before Width: | Height: | Size: 316 B After Width: | Height: | Size: 13 KiB |
|
@ -91,8 +91,8 @@ local move_to, // Y-coordinate to move to on its own
|
|||
func Movement()
|
||||
{
|
||||
// Move back and front
|
||||
front->SetPosition(GetX(), GetY()-5);
|
||||
back->SetPosition(GetX(), GetY()-7);
|
||||
front->SetPosition(GetX(), GetY()-3);
|
||||
back->SetPosition(GetX(), GetY()-5);
|
||||
|
||||
// No elevator?!
|
||||
if (!elevator)
|
||||
|
|
|
@ -39,10 +39,10 @@ public func GetInteractionMetaInfo(object clonk)
|
|||
public func Interact(object clonk)
|
||||
{
|
||||
var menu;
|
||||
var i=0,item,player=clonk->GetOwner(), amount;
|
||||
while (item = GetHomebaseMaterial(player, nil, i++))
|
||||
var i = 0, item, amount;
|
||||
while (item = GetHomebaseMaterial(GetOwner(), nil, i++))
|
||||
{
|
||||
amount = GetHomebaseMaterial(player, item);
|
||||
amount = GetHomebaseMaterial(GetOwner(), item);
|
||||
// Add even if amount==0
|
||||
if (!menu) menu = clonk->CreateRingMenu(Flagpole, this);
|
||||
if (!menu) return false;
|
||||
|
@ -65,8 +65,11 @@ public func Selected(object menu, proplist menu_item, bool alt)
|
|||
// Excess objects exit flag (can't get them out...)
|
||||
var i = ContentsCount();
|
||||
var obj;
|
||||
while (i--) if (obj = Contents(i)) Contents(i)->Exit();
|
||||
while (i--)
|
||||
if (obj = Contents(i))
|
||||
Contents(i)->Exit(0, GetDefHeight() / 2);
|
||||
// Update available count
|
||||
menu_item->SetAmount(GetHomebaseMaterial(clonk->GetOwner(), def));
|
||||
menu_item->SetAmount(GetHomebaseMaterial(GetOwner(), def));
|
||||
menu->Show();
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -15,13 +15,13 @@ public func IsLiquidPump() { return true; }
|
|||
|
||||
public func Construction(object creator)
|
||||
{
|
||||
SetAction("Wait");
|
||||
return _inherited(creator, ...);
|
||||
}
|
||||
|
||||
protected func Initialize()
|
||||
{
|
||||
MakePowerConsumer(100);
|
||||
SetAction("Wait");
|
||||
turned_on = true;
|
||||
return;
|
||||
}
|
||||
|
@ -48,7 +48,10 @@ public func Interact(object clonk)
|
|||
SetAction("Wait");
|
||||
}
|
||||
else
|
||||
{
|
||||
OnWaitStart();
|
||||
turned_on = true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -189,7 +192,7 @@ local ActMap = {
|
|||
Name = "Wait",
|
||||
Procedure = DFA_NONE,
|
||||
Length = 1,
|
||||
Delay = 50,
|
||||
Delay = 10,
|
||||
Directions = 2,
|
||||
FlipDir = 1,
|
||||
X = 0,
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
[DefCore]
|
||||
id=ToolsWorkshop_SplitFirestone
|
||||
Version=4,10,0,0
|
||||
Category=C4D_Object
|
||||
Width=1
|
||||
Height=1
|
||||
Components=Firestone=1
|
||||
Picture=0,0,64,64
|
After Width: | Height: | Size: 8.8 KiB |
|
@ -0,0 +1,23 @@
|
|||
/**
|
||||
SplitFirestone
|
||||
Split a firestone to get its natural components, coal and sulphur.
|
||||
|
||||
@author Clonkonaut
|
||||
*/
|
||||
|
||||
local Name = "$Name$";
|
||||
local Description = "$Description$";
|
||||
|
||||
func Initialize()
|
||||
{
|
||||
ScheduleCall(this, "Split", 1);
|
||||
}
|
||||
func Split()
|
||||
{
|
||||
if (!Contained()) return RemoveObject();
|
||||
Contained()->CreateContents(Coal);
|
||||
Contained()->CreateContents(Sulphur);
|
||||
RemoveObject();
|
||||
}
|
||||
|
||||
func IsToolProduct() { return true; }
|
|
@ -0,0 +1,2 @@
|
|||
Name=Feuerstein spalten
|
||||
Description=Spaltet einen Feuerstein in dessen natürliche Komponenten, Kohle und Schwefel.
|
|
@ -0,0 +1,2 @@
|
|||
Name=Split firestone
|
||||
Description=Split a firestone to get its natural components, coal and sulphur.
|
|
@ -18,17 +18,6 @@ static const SproutBerryBush_water_per_berry = 10;
|
|||
static const SproutBerryBush_max_sprouts = 8;
|
||||
static const SproutBerryBush_evolve_steps_per_new_sprout = 2;
|
||||
|
||||
// static function
|
||||
func Place(int amount)
|
||||
{
|
||||
// place some sprout berries
|
||||
var bush = PlaceVegetation(SproutBerryBush, 0, LandscapeHeight() / 3, LandscapeWidth(), LandscapeHeight(), 100000);
|
||||
if(bush)
|
||||
for (var i = 1; i < amount; i++)
|
||||
PlaceVegetation(SproutBerryBush, bush->GetX() - 200, bush->GetY() - 200, 400, 400, 100000);
|
||||
return true;
|
||||
}
|
||||
|
||||
func Construction()
|
||||
{
|
||||
SetCon(100);
|
||||
|
|
|
@ -2,6 +2,18 @@
|
|||
|
||||
#include Library_Plant
|
||||
|
||||
// Overloaded from the plant library to add the foreground parameter, foreground = true will roughly make every 3rd tree foreground (not the offspring though)
|
||||
func Place(int amount, proplist rectangle, proplist settings, bool foreground)
|
||||
{
|
||||
// Default behaviour
|
||||
var trees = inherited(amount, rectangle, settings);
|
||||
if (GetLength(trees) < 1) return;
|
||||
|
||||
for (var tree in trees)
|
||||
if (!Random(3))
|
||||
tree.Plane = 510;
|
||||
}
|
||||
|
||||
private func SeedChance() { return 500; }
|
||||
private func SeedArea() { return 400; }
|
||||
private func SeedAmount() { return 12; }
|
||||
|
|
|
@ -140,4 +140,75 @@ global func DrawParticleLine (string particle, int x0, int y0, int x1, int y1, i
|
|||
}
|
||||
// Succes, return number of created particles.
|
||||
return prtnum;
|
||||
}
|
||||
|
||||
/** Place a nice shaped forest. If no area is given, the whole landscape is used (which is not recommended!).
|
||||
@param plants An array containing all plants that should be in the forest. plants[0] is the main plant, the others will be randomly scattered throughout the forest.
|
||||
@param x The starting X-coordinate of the forest.
|
||||
@param y The lowest line at which to start placing plants. Level ground is determined automatically, goind upwards.
|
||||
@param width The width of the forest
|
||||
@param foreground Will roughly make every third instance of plants[0] foreground
|
||||
*/
|
||||
global func PlaceForest(array plants, int x, int y, int width, bool foreground)
|
||||
{
|
||||
// Parameter check
|
||||
if (GetLength(plants) == 0) return;
|
||||
if (!x) x = 0;
|
||||
if (!y) y = LandscapeHeight();
|
||||
if (!width) width = LandscapeWidth();
|
||||
if (this) { x = AbsX(x); y = AbsY(y); }
|
||||
|
||||
// Roughly 20% of the size (10% per side) are taken for 'forest ending zones'. Plants will be smaller there.
|
||||
var end_zone = width * 10 / 100;
|
||||
// The width of the standard plants will roughly be the measure for our plant size
|
||||
var plant_size = plants[0]->GetDefWidth()/2;
|
||||
|
||||
var growth, y_pos, plant, x_variance, variance = 0, count, j, spot;
|
||||
for (var i = plant_size ; i < width ; i += plant_size)
|
||||
{
|
||||
growth = 100;
|
||||
y_pos = y;
|
||||
x_variance = RandomX(-10,10);
|
||||
// End zone check
|
||||
if (i < end_zone)
|
||||
growth = BoundBy(90 / ((end_zone * 100 / plant_size)/100) * (i/plant_size), 10,90);
|
||||
else if (i > width - end_zone)
|
||||
growth = BoundBy(90 / ((end_zone * 100 / plant_size)/100) * ((width-i)/plant_size), 10,90);
|
||||
else if (!Random(10) && GetLength(plants) > 1)
|
||||
{
|
||||
variance = Random(GetLength(plants)-1)+1;
|
||||
// Scatter some other plants
|
||||
count = RandomX(2,4);
|
||||
for (j = 0 ; j < count ; j++)
|
||||
{
|
||||
spot = (plant_size*2 / count) * j + RandomX(-5,5) - plant_size;
|
||||
y_pos = y;
|
||||
if (!GBackSolid(x + i + spot, y_pos)) continue;
|
||||
while (!GBackSky(x + i + spot, y_pos) && y_pos > 0) y_pos--;
|
||||
if (y_pos == 0) continue;
|
||||
plant = CreateObject(plants[variance], x + i + spot, y_pos+5, NO_OWNER);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
// No ground at y_pos?
|
||||
if (!GBackSolid(x + i + x_variance, y_pos)) continue;
|
||||
// Get level ground
|
||||
while (!GBackSky(x + i + x_variance, y_pos) && y_pos > 0) y_pos--;
|
||||
if (y_pos == 0) continue;
|
||||
|
||||
plant = CreateObject(plants[0], x + i + x_variance, y_pos+5, NO_OWNER);
|
||||
plant->SetCon(growth);
|
||||
if (foreground && !Random(3)) plant.Plane = 510;
|
||||
// Every ~7th plant: double plant!
|
||||
if (x_variance != 0 && !Random(7))
|
||||
{
|
||||
y_pos = y;
|
||||
if (!GBackSolid(x + i - x_variance, y_pos)) continue;
|
||||
while (!GBackSky(x + i - x_variance, y_pos) && y_pos > 0) y_pos--;
|
||||
if (y_pos == 0) continue;
|
||||
plant = CreateObject(plants[0], x + i - x_variance, y_pos+5, NO_OWNER);
|
||||
plant->SetCon(growth);
|
||||
if (foreground && !Random(3)) plant.Plane = 510;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -28,7 +28,7 @@ global func OnFire()
|
|||
}
|
||||
|
||||
// Extinguishes the calling object with specified strength.
|
||||
global func Extinguish(strength)
|
||||
global func Extinguish(strength /* strength between 0 and 100 */)
|
||||
{
|
||||
if (!this)
|
||||
return false;
|
||||
|
@ -47,7 +47,11 @@ global func Extinguish(strength)
|
|||
}
|
||||
|
||||
// Incinerates the calling object with specified strength.
|
||||
global func Incinerate(strength, int caused_by, blasted, incinerating_object)
|
||||
global func Incinerate(
|
||||
strength /* strength between 0 and 100 */
|
||||
, int caused_by /* the player that caused the incineration */
|
||||
, blasted /* whether the object was incinerated by an explosion */
|
||||
, incinerating_object /* the object that caused the incineration */)
|
||||
{
|
||||
if (!this)
|
||||
return false;
|
||||
|
|
|
@ -4,7 +4,10 @@
|
|||
Authors: Zapper
|
||||
--*/
|
||||
|
||||
global func GetFlagpoleForPosition(int x, int y)
|
||||
// returns the flagpole that is currently holding ownership of a specific point in the landscape
|
||||
global func GetFlagpoleForPosition(
|
||||
int x /* x position in local coordinates */
|
||||
, int y /* y position in local coordinates */)
|
||||
{
|
||||
if(GetType(LibraryFlag_flag_list) != C4V_Array) return nil;
|
||||
|
||||
|
@ -24,15 +27,19 @@ global func GetFlagpoleForPosition(int x, int y)
|
|||
return oldest;
|
||||
}
|
||||
|
||||
global func GetOwnerOfPosition(int x, int y)
|
||||
// returns the current owner that controls a certain point with a flagpole or NO_OWNER
|
||||
global func GetOwnerOfPosition(
|
||||
int x /* x position in local coordinates */
|
||||
, int y /* y position in local coordinates */)
|
||||
{
|
||||
var flag = GetFlagpoleForPosition(x, y);
|
||||
if(!flag) return NO_OWNER;
|
||||
return flag->GetOwner();
|
||||
}
|
||||
|
||||
// redraws all flag radiuses
|
||||
global func RedrawAllFlagRadiuses()
|
||||
{
|
||||
for(var f in LibraryFlag_flag_list)
|
||||
f->RedrawFlagRadius();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -79,8 +79,16 @@ global func ComDirLike(int comdir1, int comdir2)
|
|||
|
||||
// the shortest direction (left/right) to turn from one angle to another
|
||||
// (for example for homing projectiles or aiming)
|
||||
global func GetTurnDirection(int from, int to)
|
||||
global func GetTurnDirection(
|
||||
int from /* the angle at which the turning starts */
|
||||
, int to /* the angle that should be turned towards */)
|
||||
{
|
||||
/*
|
||||
// code for a homing missile
|
||||
var dir = GetTurnDirection(my_angle, target_angle);
|
||||
SetR(GetR() + dir / 10);
|
||||
SetSpeed(Sin(GetR(), 10), -Cos(GetR(), 10));
|
||||
*/
|
||||
var dir;
|
||||
/*if(to < from)*/dir=to-from;
|
||||
//else dir=from-to;
|
||||
|
@ -116,4 +124,21 @@ global func GetCalcDir()
|
|||
{
|
||||
if (!this) return 0;
|
||||
return GetDir() * 2 - 1;
|
||||
}
|
||||
|
||||
// Ensure that the first rectangle is fully with the second one and returns an adjusted rectangle. Both rectangles can be created with Rectangle()
|
||||
global func RectangleEnsureWithin(proplist first, proplist second)
|
||||
{
|
||||
if (GetType(first) != C4V_PropList) return {};
|
||||
if (GetType(second) != C4V_PropList) return {};
|
||||
|
||||
var adjusted = { x = first.x, y = first.y, w = first.w, h = first.h };
|
||||
if (first.x < second.x) adjusted.x = second.x;
|
||||
if (first.w > second.w) adjusted.w = second.w - (adjusted.x - second.x);
|
||||
if (adjusted.x + adjusted.w > second.x + second.w) adjusted.w = second.w - (adjusted.x - second.x);
|
||||
if (first.y < second.y) adjusted.y = second.y;
|
||||
if (first.h > second.h) adjusted.h = second.h - (adjusted.y - second.y);
|
||||
if (adjusted.y + adjusted.h > second.y + second.h) adjusted.h = second.h - (adjusted.y - second.y);
|
||||
|
||||
return adjusted;
|
||||
}
|
|
@ -148,7 +148,7 @@ global func GetMaxBreath()
|
|||
}
|
||||
|
||||
// Makes an object gain Con until it is FullCon
|
||||
global func StartGrowth(int value)
|
||||
global func StartGrowth(int value /* the value the object grows approx. every second, in tenths of percent */)
|
||||
{
|
||||
var effect;
|
||||
effect = AddEffect("IntGrowth", this, 1, 35, nil, nil, value);
|
||||
|
@ -330,4 +330,4 @@ global func InFrontOf(object back)
|
|||
return;
|
||||
|
||||
return front->FindObject(front->Find_AtPoint(), Find_Not(Find_Exclude(back))) != nil;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -85,7 +85,8 @@ global func DoWealth(int plr, int value)
|
|||
return SetWealth(plr, value + GetWealth(plr));
|
||||
}
|
||||
|
||||
global func IsAllied(int plr1, int plr2, bool check_one_way_only)
|
||||
// checks whether two players are allied - that means they are not hostile and neither of them is NO_OWNER
|
||||
global func IsAllied(int plr1, int plr2, bool check_one_way_only /* whether to check the hostility only in one direction */)
|
||||
{
|
||||
if(plr1 == NO_OWNER) return false;
|
||||
if(plr2 == NO_OWNER) return false;
|
||||
|
@ -113,4 +114,4 @@ global func MessageWindow(string msg, int for_plr, id icon, string caption)
|
|||
global func FindBase (int iPlr, int iIndex)
|
||||
{
|
||||
return FindObjects(Find_Owner(iPlr), Find_Func("IsBase"))[iIndex];
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
/*--
|
||||
Proplists.c
|
||||
|
||||
General helper functions that create or work with proplists.
|
||||
--*/
|
||||
|
||||
// creates a proplists with the properties x, y, w, h that represents a rectangle
|
||||
// satisfies that the resulting rectangle's x|y point is in the top-left corner and the width and height are positive
|
||||
global func Rectangle(int x2, int y2, int w2, int h2)
|
||||
{
|
||||
/*
|
||||
// creates a rectangle representing the landscape
|
||||
var rect = Rectangle(0, 0, LandscapeWidth(), LandscapeHeight());
|
||||
*/
|
||||
// normalize
|
||||
if(w2 < 0)
|
||||
{
|
||||
x2 += w2;
|
||||
w2 = -w2;
|
||||
}
|
||||
if(h2 < 0)
|
||||
{
|
||||
y2 += h2;
|
||||
h2 = - h2;
|
||||
}
|
||||
return {x = x2, y = y2, w = w2, h = h2};
|
||||
}
|
|
@ -34,8 +34,24 @@ global func FxIntScheduleTimer(object obj, proplist effect)
|
|||
}
|
||||
|
||||
// Adds a timed call to an object, replacement of DefCore TimerCall.
|
||||
global func AddTimer(string function, int interval)
|
||||
global func AddTimer(
|
||||
string function /* function that will be called every time step */
|
||||
, int interval /* interval in frames in which the function will be called */)
|
||||
{
|
||||
/*
|
||||
// script for a mine that checks for enemies every second
|
||||
func Initialize()
|
||||
{
|
||||
AddTimer("CheckForEnemies", 36);
|
||||
}
|
||||
|
||||
func CheckForEnemies()
|
||||
{
|
||||
if(FindObject(Find_AtPoint(), Find_OCF(OCF_Alive)))
|
||||
Explode(30);
|
||||
}
|
||||
*/
|
||||
|
||||
if (!this)
|
||||
return false;
|
||||
// Default to one second.
|
||||
|
|
|
@ -101,7 +101,7 @@ protected func FxRestoreStop(object target, effect, int reason, bool temporary)
|
|||
else
|
||||
to_restore->SetPosition(to_x, to_y);
|
||||
// Restored object might have been removed on enter (Stackable).
|
||||
if (to_restore)
|
||||
if (to_restore && !to_restore->~IsStackable())
|
||||
{
|
||||
// Add new restore mode, either standard one or effect supplied in EffectVar 4.
|
||||
if (ctrl_string)
|
||||
|
|
|
@ -50,8 +50,32 @@ don't need to include this file or any of the files it includes. */
|
|||
// solidmask debugging
|
||||
//#define SOLIDMASK_DEBUG
|
||||
|
||||
// debug memory management - must come after boost headers,
|
||||
// because boost uses placement new
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <cctype>
|
||||
#include <cerrno>
|
||||
#include <climits>
|
||||
|
||||
#include <cmath>
|
||||
#include <cstdarg>
|
||||
#include <cstddef>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <ctime>
|
||||
#include <iostream>
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <set>
|
||||
#include <sstream>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
// debug memory management - must come after standard and boost headers,
|
||||
// because those libraries use placement new
|
||||
#ifndef NODEBUGMEM
|
||||
#if defined(_DEBUG) && defined(_MSC_VER)
|
||||
#if _MSC_VER <= 1200
|
||||
|
@ -73,31 +97,7 @@ inline void operator delete(void *p, const char *, long)
|
|||
#define new new(__FILE__, __LINE__)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <cctype>
|
||||
#include <cerrno>
|
||||
#include <climits>
|
||||
|
||||
#include <cmath>
|
||||
#include <cstdarg>
|
||||
#include <cstddef>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <ctime>
|
||||
#include <iostream>
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <new>
|
||||
#include <set>
|
||||
#include <sstream>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "Standard.h"
|
||||
#include "C4Prototypes.h"
|
||||
|
|
|
@ -63,6 +63,12 @@
|
|||
|
||||
#define C4XVERTOC4XVERS(s) C4XVERTOC4XVERS2(s)
|
||||
#define C4XVERTOC4XVERS2(s) #s
|
||||
|
||||
// if C4XVER3 >= 90, this is a pre-release version; add VCS revision instead of build number
|
||||
#if C4XVER3 >= 90
|
||||
#define C4VERSION C4XVERTOC4XVERS(C4XVER1) "." C4XVERTOC4XVERS(C4XVER2) "." C4XVERTOC4XVERS(C4XVER3) " [" C4REVISION "]" C4VERSIONEXTRA C4BUILDOPT
|
||||
#else
|
||||
#define C4VERSION C4XVERTOC4XVERS(C4XVER1) "." C4XVERTOC4XVERS(C4XVER2) "." C4XVERTOC4XVERS(C4XVER3) " [" C4XVER4S "]" C4VERSIONEXTRA C4BUILDOPT
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
|
@ -405,7 +405,7 @@ void C4Console::UpdateInputCtrl()
|
|||
{
|
||||
ClearInput();
|
||||
// add global and standard functions
|
||||
std::list <const char*> functions = ::ScriptEngine.GetFunctionNames(&::GameScript);
|
||||
std::list <const char*> functions = ::ScriptEngine.GetFunctionNames(::GameScript.ScenPropList._getPropList());
|
||||
SetInputFunctions(functions);
|
||||
}
|
||||
|
||||
|
|
|
@ -993,7 +993,7 @@ void C4ConsoleGUI::PropertyDlgUpdate(C4ObjectList &rSelection)
|
|||
if (PropertyDlgObject == rSelection.GetObject()) return;
|
||||
PropertyDlgObject = rSelection.GetObject();
|
||||
|
||||
std::list<const char *> functions = ::ScriptEngine.GetFunctionNames(PropertyDlgObject ? &PropertyDlgObject->Def->Script : 0);
|
||||
std::list<const char *> functions = ::ScriptEngine.GetFunctionNames(PropertyDlgObject);
|
||||
GtkEntryCompletion* completion = gtk_entry_get_completion(GTK_ENTRY(state->propertydlg_entry));
|
||||
GtkListStore* store;
|
||||
|
||||
|
|
|
@ -893,7 +893,7 @@ void C4ConsoleGUI::PropertyDlgUpdate(C4ObjectList &rSelection)
|
|||
if (PropertyDlgObject == rSelection.GetObject()) return;
|
||||
PropertyDlgObject = rSelection.GetObject();
|
||||
|
||||
std::list<const char *> functions = ::ScriptEngine.GetFunctionNames(PropertyDlgObject ? &PropertyDlgObject->Def->Script : 0);
|
||||
std::list<const char *> functions = ::ScriptEngine.GetFunctionNames(PropertyDlgObject);
|
||||
HWND hCombo = GetDlgItem(state->hPropertyDlg, IDC_COMBOINPUT);
|
||||
wchar_t szLastText[500+1];
|
||||
// Remember old window text
|
||||
|
|
|
@ -497,15 +497,15 @@ void C4Effect::SetPropertyByS(C4String * k, const C4Value & to)
|
|||
{
|
||||
case P_Name:
|
||||
if (!to.getStr() || !*to.getStr()->GetCStr())
|
||||
throw new C4AulExecError(0, "effect: Name has to be a nonempty string");
|
||||
throw new C4AulExecError("effect: Name has to be a nonempty string");
|
||||
C4PropListNumbered::SetPropertyByS(k, to);
|
||||
ReAssignCallbackFunctions();
|
||||
return;
|
||||
case P_Priority:
|
||||
throw new C4AulExecError(0, "effect: Priority is readonly");
|
||||
throw new C4AulExecError("effect: Priority is readonly");
|
||||
case P_Interval: iInterval = to.getInt(); return;
|
||||
case P_CommandTarget:
|
||||
throw new C4AulExecError(0, "effect: CommandTarget is readonly");
|
||||
throw new C4AulExecError("effect: CommandTarget is readonly");
|
||||
case P_Time: iTime = to.getInt(); return;
|
||||
}
|
||||
}
|
||||
|
@ -519,12 +519,12 @@ void C4Effect::ResetProperty(C4String * k)
|
|||
switch(k - &Strings.P[0])
|
||||
{
|
||||
case P_Name:
|
||||
throw new C4AulExecError(0, "effect: Name has to be a nonempty string");
|
||||
throw new C4AulExecError("effect: Name has to be a nonempty string");
|
||||
case P_Priority:
|
||||
throw new C4AulExecError(0, "effect: Priority is readonly");
|
||||
throw new C4AulExecError("effect: Priority is readonly");
|
||||
case P_Interval: iInterval = 0; return;
|
||||
case P_CommandTarget:
|
||||
throw new C4AulExecError(0, "effect: CommandTarget is readonly");
|
||||
throw new C4AulExecError("effect: CommandTarget is readonly");
|
||||
case P_Time: iTime = 0; return;
|
||||
}
|
||||
}
|
||||
|
@ -556,6 +556,20 @@ bool C4Effect::GetPropertyByS(C4String *k, C4Value *pResult) const
|
|||
return C4PropListNumbered::GetPropertyByS(k, pResult);
|
||||
}
|
||||
|
||||
C4ValueArray * C4Effect::GetProperties() const
|
||||
{
|
||||
C4ValueArray * a = C4PropList::GetProperties();
|
||||
int i;
|
||||
i = a->GetSize();
|
||||
a->SetSize(i + 5);
|
||||
(*a)[i++] = C4VString(&::Strings.P[P_Name]);
|
||||
(*a)[i++] = C4VString(&::Strings.P[P_Priority]);
|
||||
(*a)[i++] = C4VString(&::Strings.P[P_Interval]);
|
||||
(*a)[i++] = C4VString(&::Strings.P[P_CommandTarget]);
|
||||
(*a)[i++] = C4VString(&::Strings.P[P_Time]);
|
||||
return a;
|
||||
}
|
||||
|
||||
// Some other, internal effects -------------------------------------------------------------
|
||||
|
||||
static int32_t GetSmokeLevel()
|
||||
|
|
|
@ -133,6 +133,7 @@ public:
|
|||
virtual void SetPropertyByS(C4String * k, const C4Value & to);
|
||||
virtual void ResetProperty(C4String * k);
|
||||
virtual bool GetPropertyByS(C4String *k, C4Value *pResult) const;
|
||||
virtual C4ValueArray * GetProperties() const;
|
||||
|
||||
protected:
|
||||
void TempRemoveUpperEffects(C4Object *pObj, bool fTempRemoveThis, C4Effect **ppLastRemovedEffect); // temp remove all effects with higher priority
|
||||
|
|
|
@ -45,24 +45,6 @@ struct C4ScriptConstDef
|
|||
long Data; // raw data
|
||||
};
|
||||
|
||||
|
||||
|
||||
// ** a definition of a script-function.
|
||||
// includes two versions of the Function to be called:
|
||||
// * the first (C4V) takes 10 parameters
|
||||
// * the second (C4V2) takes an array of 10 parameters
|
||||
// only one may be set.
|
||||
struct C4ScriptFnDef
|
||||
{
|
||||
const char* Identifier; // the name of the func in the script
|
||||
bool Public;
|
||||
C4V_Type RetType; // type returned. ignored when C4V
|
||||
C4V_Type ParType[10];// type of the parameters. error when wrong parameter type.
|
||||
C4Value (*FunctionC4V)(struct C4AulContext *cthr, C4Value*, C4Value*, C4Value*, C4Value*, C4Value*,
|
||||
C4Value*, C4Value*, C4Value*, C4Value*, C4Value*);
|
||||
C4Value (*FunctionC4V2)(struct C4AulContext *, C4Value *);
|
||||
};
|
||||
|
||||
// add functions to engine
|
||||
void InitGameFunctionMap(C4AulScriptEngine *pEngine);
|
||||
void InitObjectFunctionMap(C4AulScriptEngine *pEngine);
|
||||
|
|
|
@ -2069,11 +2069,29 @@ void CStdGL::ResetTexture()
|
|||
|
||||
bool CStdGL::Error(const char *szMsg)
|
||||
{
|
||||
#ifdef USE_WIN32_WINDOWS
|
||||
DWORD err = GetLastError();
|
||||
#endif
|
||||
bool r = C4Draw::Error(szMsg);
|
||||
#ifdef USE_WIN32_WINDOWS
|
||||
wchar_t * lpMsgBuf;
|
||||
FormatMessage(
|
||||
FORMAT_MESSAGE_ALLOCATE_BUFFER |
|
||||
FORMAT_MESSAGE_FROM_SYSTEM |
|
||||
FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||
NULL,
|
||||
err,
|
||||
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
||||
(LPTSTR) &lpMsgBuf,
|
||||
0, NULL );
|
||||
LogF(" gl: GetLastError() = %d - %s", err, StdStrBuf(lpMsgBuf).getData());
|
||||
LocalFree(lpMsgBuf);
|
||||
#endif
|
||||
LogF(" gl: %s", glGetString(GL_VENDOR));
|
||||
LogF(" gl: %s", glGetString(GL_RENDERER));
|
||||
LogF(" gl: %s", glGetString(GL_VERSION));
|
||||
LogF(" gl: %s", glGetString(GL_EXTENSIONS));
|
||||
return C4Draw::Error(szMsg);
|
||||
return r;
|
||||
}
|
||||
|
||||
bool CStdGL::CheckGLError(const char *szAtOp)
|
||||
|
|
|
@ -939,7 +939,11 @@ bool C4ScenarioListLoader::SubFolder::LoadCustom(C4Group &rGrp, bool fNameLoaded
|
|||
{
|
||||
// default icon fallback
|
||||
if (!fIconLoaded)
|
||||
fctIcon.Set(C4Startup::Get()->Graphics.fctScenSelIcons.GetSection(C4StartupScenSel_DefaultIcon_Folder));
|
||||
{
|
||||
if(WildcardMatch(C4CFN_Savegames, GetFilename(sFilename.getData()))) iIconIndex = C4StartupScenSel_DefaultIcon_SavegamesFolder;
|
||||
else iIconIndex = C4StartupScenSel_DefaultIcon_Folder;
|
||||
fctIcon.Set(C4Startup::Get()->Graphics.fctScenSelIcons.GetSection(iIconIndex));
|
||||
}
|
||||
// folder index
|
||||
iFolderIndex = C4F.Head.Index;
|
||||
return true;
|
||||
|
|
|
@ -33,14 +33,15 @@
|
|||
class C4StartupScenSelDlg;
|
||||
|
||||
const int32_t C4StartupScenSel_DefaultIcon_Scenario = 14,
|
||||
C4StartupScenSel_DefaultIcon_Folder = 0,
|
||||
C4StartupScenSel_DefaultIcon_WinFolder = 44,
|
||||
C4StartupScenSel_DefaultIcon_OldIconBG = 18,
|
||||
C4StartupScenSel_IconCount = 45,
|
||||
C4StartupScenSel_TitlePictureWdt = 200,
|
||||
C4StartupScenSel_TitlePictureHgt = 150,
|
||||
C4StartupScenSel_TitlePicturePadding = 10,
|
||||
C4StartupScenSel_TitleOverlayMargin = 10; // number of pixels to each side of title overlay picture
|
||||
C4StartupScenSel_DefaultIcon_Folder = 0,
|
||||
C4StartupScenSel_DefaultIcon_SavegamesFolder = 29,
|
||||
C4StartupScenSel_DefaultIcon_WinFolder = 44,
|
||||
C4StartupScenSel_DefaultIcon_OldIconBG = 18,
|
||||
C4StartupScenSel_IconCount = 45,
|
||||
C4StartupScenSel_TitlePictureWdt = 200,
|
||||
C4StartupScenSel_TitlePictureHgt = 150,
|
||||
C4StartupScenSel_TitlePicturePadding = 10,
|
||||
C4StartupScenSel_TitleOverlayMargin = 10; // number of pixels to each side of title overlay picture
|
||||
|
||||
// a list of loaded scenarios
|
||||
class C4ScenarioListLoader
|
||||
|
|
|
@ -547,6 +547,13 @@ GLhandleARB C4LandscapeRenderGL::CreateShader(GLenum iShaderType, const char *sz
|
|||
szCodeRest = szVersion;
|
||||
}
|
||||
|
||||
// Get number of available uniforms from driver
|
||||
GLint max_uniforms = 0;
|
||||
glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_COMPONENTS_ARB, &max_uniforms);
|
||||
Version.AppendFormat("#define MAX_FRAGMENT_UNIFORM_COMPONENTS %d\n", max_uniforms);
|
||||
glGetIntegerv(GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB, &max_uniforms);
|
||||
Version.AppendFormat("#define MAX_VERTEX_UNIFORM_COMPONENTS %d\n", max_uniforms);
|
||||
|
||||
// Build code
|
||||
const char *szCodes[C4LR_ShaderWorkaroundCount + 2];
|
||||
szCodes[0] = Version.getData();
|
||||
|
|
|
@ -428,7 +428,7 @@ bool C4MCOverlay::SetField(C4MCParser *pParser, const char *szField, const char
|
|||
case C4MCV_ScriptFunc:
|
||||
{
|
||||
// get script func of main script
|
||||
C4AulFunc *pSFunc = ::GameScript.ScenPropList->GetFunc(StrPar);
|
||||
C4AulFunc *pSFunc = ::GameScript.ScenPropList._getPropList()->GetFunc(StrPar);
|
||||
if (!pSFunc) throw C4MCParserErr(pParser, C4MCErr_SFuncNotFound, StrPar);
|
||||
// add to main
|
||||
Target.As<C4MCCallbackArray*>() = new C4MCCallbackArray(pSFunc, MapCreator);
|
||||
|
|
|
@ -576,7 +576,7 @@ void SNewSegment(char *szStr, const char *szSepa)
|
|||
int SGetLine(const char *szText, const char *cpPosition)
|
||||
{
|
||||
if (!szText || !cpPosition) return 0;
|
||||
int iLines = 0;
|
||||
int iLines = 1;
|
||||
while (*szText && (szText<cpPosition))
|
||||
{
|
||||
if (*szText == 0x0A) iLines++;
|
||||
|
@ -588,11 +588,16 @@ int SGetLine(const char *szText, const char *cpPosition)
|
|||
int SLineGetCharacters(const char *szText, const char *cpPosition)
|
||||
{
|
||||
if (!szText || !cpPosition) return 0;
|
||||
int iChars = 0;
|
||||
int iChars = 1;
|
||||
while (*szText && (szText<cpPosition))
|
||||
{
|
||||
if (*szText == 0x0A) iChars = 0;
|
||||
iChars++;
|
||||
if (*szText == 0x0A)
|
||||
iChars = 1;
|
||||
else if (*szText == '\t')
|
||||
// assume a tab stop every 8 characters
|
||||
iChars = ((iChars - 1 + 8) & ~7) + 1;
|
||||
else
|
||||
iChars++;
|
||||
szText++;
|
||||
}
|
||||
return iChars;
|
||||
|
|
|
@ -252,7 +252,7 @@ void C4Def::CompileFunc(StdCompiler *pComp)
|
|||
|
||||
//-------------------------------- C4Def -------------------------------------------------------
|
||||
|
||||
C4Def::C4Def(): Script(this), C4PropList(ScriptEngine.GetPropList())
|
||||
C4Def::C4Def(): Script(this), C4PropListStatic(ScriptEngine.GetPropList(), NULL, NULL)
|
||||
{
|
||||
assert(ScriptEngine.GetPropList());
|
||||
Graphics.pDef = this;
|
||||
|
@ -363,6 +363,7 @@ bool C4Def::Load(C4Group &hGroup,
|
|||
|
||||
// Register ID with script engine
|
||||
::ScriptEngine.RegisterGlobalConstant(id.ToString(), C4VPropList(this));
|
||||
ParentKeyName = ::Strings.RegString(id.ToString());
|
||||
|
||||
// Read script
|
||||
if (dwLoadWhat & C4D_Load_Script)
|
||||
|
|
|
@ -102,7 +102,7 @@ C4D_Load_Temporary = 1024;
|
|||
#define C4D_Blit_Additive 1
|
||||
#define C4D_Blit_ModAdd 2
|
||||
|
||||
class C4Def: public C4PropList
|
||||
class C4Def: public C4PropListStatic
|
||||
{
|
||||
public:
|
||||
C4ID id;
|
||||
|
@ -213,7 +213,7 @@ public:
|
|||
void Synchronize();
|
||||
virtual C4Def const * GetDef() const { return this; }
|
||||
virtual C4Def * GetDef() { return this; }
|
||||
virtual bool IsDef() const { return true; }
|
||||
virtual bool Delete() { return false; }
|
||||
protected:
|
||||
bool LoadActMap(C4Group &hGroup);
|
||||
void CrossMapActMap();
|
||||
|
|
|
@ -52,18 +52,18 @@ StdMeshInstance::ValueProvider* CreateValueProviderFromArray(C4Object* pForObj,
|
|||
return new C4ValueProviderConst(itofix(Data[1].getInt(), 1000));
|
||||
case C4AVP_Linear:
|
||||
if (Data[4].getInt() == 0)
|
||||
throw new C4AulExecError(pForObj, "Length cannot be zero");
|
||||
throw new C4AulExecError("Length cannot be zero");
|
||||
return new C4ValueProviderLinear(itofix(Data[1].getInt(), 1000), itofix(Data[2].getInt(), 1000), itofix(Data[3].getInt(), 1000), Data[4].getInt(), static_cast<C4AnimationEnding>(Data[5].getInt()));
|
||||
case C4AVP_X:
|
||||
if (!pForObj) return NULL;
|
||||
if (Data[4].getInt() == 0)
|
||||
throw new C4AulExecError(pForObj, "Length cannot be zero");
|
||||
throw new C4AulExecError("Length cannot be zero");
|
||||
|
||||
return new C4ValueProviderX(pForObj, itofix(Data[1].getInt(), 1000), itofix(Data[2].getInt(), 1000), itofix(Data[3].getInt(), 1000), Data[4].getInt());
|
||||
case C4AVP_Y:
|
||||
if (!pForObj) return NULL;
|
||||
if (Data[4].getInt() == 0)
|
||||
throw new C4AulExecError(pForObj, "Length cannot be zero");
|
||||
throw new C4AulExecError("Length cannot be zero");
|
||||
|
||||
return new C4ValueProviderY(pForObj, itofix(Data[1].getInt(), 1000), itofix(Data[2].getInt(), 1000), itofix(Data[3].getInt(), 1000), Data[4].getInt());
|
||||
case C4AVP_R:
|
||||
|
@ -74,27 +74,27 @@ StdMeshInstance::ValueProvider* CreateValueProviderFromArray(C4Object* pForObj,
|
|||
case C4AVP_AbsX:
|
||||
if (!pForObj) return NULL;
|
||||
if (Data[4].getInt() == 0)
|
||||
throw new C4AulExecError(pForObj, "Length cannot be zero");
|
||||
throw new C4AulExecError("Length cannot be zero");
|
||||
return new C4ValueProviderAbsX(pForObj, itofix(Data[1].getInt(), 1000), itofix(Data[2].getInt(), 1000), itofix(Data[3].getInt(), 1000), Data[4].getInt());
|
||||
case C4AVP_AbsY:
|
||||
if (!pForObj) return NULL;
|
||||
if (Data[4].getInt() == 0)
|
||||
throw new C4AulExecError(pForObj, "Length cannot be zero");
|
||||
throw new C4AulExecError("Length cannot be zero");
|
||||
return new C4ValueProviderAbsY(pForObj, itofix(Data[1].getInt(), 1000), itofix(Data[2].getInt(), 1000), itofix(Data[3].getInt(), 1000), Data[4].getInt());
|
||||
case C4AVP_XDir:
|
||||
if (!pForObj) return NULL;
|
||||
if (Data[3].getInt() == 0)
|
||||
throw new C4AulExecError(pForObj, "MaxXDir cannot be zero");
|
||||
throw new C4AulExecError("MaxXDir cannot be zero");
|
||||
return new C4ValueProviderXDir(pForObj, itofix(Data[1].getInt(), 1000), itofix(Data[2].getInt(), 1000), itofix(Data[3].getInt(),Data[4].getInt()));
|
||||
case C4AVP_YDir:
|
||||
if (!pForObj) return NULL;
|
||||
if (Data[3].getInt() == 0)
|
||||
throw new C4AulExecError(pForObj, "MaxYDir cannot be zero");
|
||||
throw new C4AulExecError("MaxYDir cannot be zero");
|
||||
return new C4ValueProviderYDir(pForObj, itofix(Data[1].getInt(), 1000), itofix(Data[2].getInt(), 1000), itofix(Data[3].getInt(),Data[4].getInt()));
|
||||
case C4AVP_RDir:
|
||||
if (!pForObj) return NULL;
|
||||
if (Data[3].getInt() == 0)
|
||||
throw new C4AulExecError(pForObj, "MaxRDir cannot be zero");
|
||||
throw new C4AulExecError("MaxRDir cannot be zero");
|
||||
return new C4ValueProviderRDir(pForObj, itofix(Data[1].getInt(), 1000), itofix(Data[2].getInt(), 1000), itofix(Data[3].getInt(),Data[4].getInt()));
|
||||
case C4AVP_CosR:
|
||||
if (!pForObj) return NULL;
|
||||
|
|
|
@ -4924,7 +4924,7 @@ void C4Object::SetPropertyByS(C4String * k, const C4Value & to)
|
|||
switch(k - &Strings.P[0])
|
||||
{
|
||||
case P_Plane:
|
||||
if (!to.getInt()) throw new C4AulExecError(this, "invalid Plane 0");
|
||||
if (!to.getInt()) throw new C4AulExecError("invalid Plane 0");
|
||||
SetPlane(to.getInt());
|
||||
return;
|
||||
}
|
||||
|
@ -4957,3 +4957,13 @@ bool C4Object::GetPropertyByS(C4String *k, C4Value *pResult) const
|
|||
}
|
||||
return C4PropListNumbered::GetPropertyByS(k, pResult);
|
||||
}
|
||||
|
||||
C4ValueArray * C4Object::GetProperties() const
|
||||
{
|
||||
C4ValueArray * a = C4PropList::GetProperties();
|
||||
int i;
|
||||
i = a->GetSize();
|
||||
a->SetSize(i + 1);
|
||||
(*a)[i++] = C4VString(&::Strings.P[P_Plane]);
|
||||
return a;
|
||||
}
|
||||
|
|
|
@ -409,6 +409,7 @@ public:
|
|||
virtual void SetPropertyByS(C4String * k, const C4Value & to);
|
||||
virtual void ResetProperty(C4String * k);
|
||||
virtual bool GetPropertyByS(C4String *k, C4Value *pResult) const;
|
||||
virtual C4ValueArray * GetProperties() const;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -84,13 +84,13 @@ static bool FnPunch(C4Object *Obj, C4Object *target, long punch)
|
|||
return !!ObjectComPunch(Obj,target,punch);
|
||||
}
|
||||
|
||||
static bool FnKill(C4AulContext *cthr, C4Object *pObj, bool fForced)
|
||||
static bool FnKill(C4PropList * _this, C4Object *pObj, bool fForced)
|
||||
{
|
||||
if (!pObj) pObj=cthr->Obj; if (!pObj) return false;
|
||||
if (!pObj) pObj=Object(_this); if (!pObj) return false;
|
||||
if (!pObj->GetAlive()) return false;
|
||||
// Trace kills by player-owned objects
|
||||
// Do not trace for NO_OWNER, because that would include e.g. the Suicide-rule
|
||||
if (cthr->Obj && ValidPlr(cthr->Obj->Controller)) pObj->UpdatLastEnergyLossCause(cthr->Obj->Controller);
|
||||
if (Object(_this) && ValidPlr(Object(_this)->Controller)) pObj->UpdatLastEnergyLossCause(Object(_this)->Controller);
|
||||
// Do the kill
|
||||
pObj->AssignDeath(!!fForced);
|
||||
return true;
|
||||
|
@ -174,24 +174,24 @@ static long FnGetCon(C4Object *Obj, long iPrec)
|
|||
return iPrec*Obj->GetCon()/FullCon;
|
||||
}
|
||||
|
||||
static C4String *FnGetName(C4AulContext *cthr)
|
||||
static C4String *FnGetName(C4PropList * _this)
|
||||
{
|
||||
if (!cthr->Def)
|
||||
if (!_this)
|
||||
throw new NeedNonGlobalContext("GetName");
|
||||
else
|
||||
return String(cthr->Def->GetName());
|
||||
return String(_this->GetName());
|
||||
}
|
||||
|
||||
static bool FnSetName(C4AulContext *cthr, C4String *pNewName, bool fSetInInfo, bool fMakeValidIfExists)
|
||||
static bool FnSetName(C4PropList * _this, C4String *pNewName, bool fSetInInfo, bool fMakeValidIfExists)
|
||||
{
|
||||
if (!cthr->Obj)
|
||||
if (!Object(_this))
|
||||
{
|
||||
if (!cthr->Def)
|
||||
if (!_this)
|
||||
throw new NeedNonGlobalContext("SetName");
|
||||
else if (fSetInInfo)
|
||||
return false;
|
||||
// Definition name
|
||||
cthr->Def->SetName(FnStringPar(pNewName));
|
||||
_this->SetName(FnStringPar(pNewName));
|
||||
return true;
|
||||
}
|
||||
else
|
||||
|
@ -200,7 +200,7 @@ static bool FnSetName(C4AulContext *cthr, C4String *pNewName, bool fSetInInfo, b
|
|||
if (fSetInInfo)
|
||||
{
|
||||
// setting name in info
|
||||
C4ObjectInfo *pInfo = cthr->Obj->Info;
|
||||
C4ObjectInfo *pInfo = Object(_this)->Info;
|
||||
if (!pInfo) return false;
|
||||
const char *szName = pNewName->GetCStr();
|
||||
// empty names are bad; e.g., could cause problems in savegames
|
||||
|
@ -213,7 +213,7 @@ static bool FnSetName(C4AulContext *cthr, C4String *pNewName, bool fSetInInfo, b
|
|||
// querying owner info list here isn't 100% accurate, as infos might have been stolen by other players
|
||||
// however, there is no good way to track the original list ATM
|
||||
C4ObjectInfoList *pInfoList = NULL;
|
||||
C4Player *pOwner = ::Players.Get(cthr->Obj->Owner);
|
||||
C4Player *pOwner = ::Players.Get(Object(_this)->Owner);
|
||||
if (pOwner) pInfoList = &pOwner->CrewInfoList;
|
||||
char NameBuf[C4MaxName+1];
|
||||
if (pInfoList) if (pInfoList->NameExists(szName))
|
||||
|
@ -224,14 +224,14 @@ static bool FnSetName(C4AulContext *cthr, C4String *pNewName, bool fSetInInfo, b
|
|||
szName = NameBuf;
|
||||
}
|
||||
SCopy(szName, pInfo->Name, C4MaxName);
|
||||
cthr->Obj->SetName(); // make sure object uses info name
|
||||
cthr->Obj->Call(PSF_NameChange,&C4AulParSet(C4VBool(true)));
|
||||
Object(_this)->SetName(); // make sure object uses info name
|
||||
Object(_this)->Call(PSF_NameChange,&C4AulParSet(C4VBool(true)));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!pNewName) cthr->Obj->SetName();
|
||||
else cthr->Obj->SetName(pNewName->GetCStr());
|
||||
cthr->Obj->Call(PSF_NameChange,&C4AulParSet(C4VBool(false)));
|
||||
if (!pNewName) Object(_this)->SetName();
|
||||
else Object(_this)->SetName(pNewName->GetCStr());
|
||||
Object(_this)->Call(PSF_NameChange,&C4AulParSet(C4VBool(false)));
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
@ -580,15 +580,15 @@ static long FnGetBreath(C4Object *Obj)
|
|||
return Obj->Breath;
|
||||
}
|
||||
|
||||
static long FnGetMass(C4AulContext *cthr)
|
||||
static long FnGetMass(C4PropList * _this)
|
||||
{
|
||||
if (!cthr->Obj)
|
||||
if (!cthr->Def || !cthr->Def->GetDef())
|
||||
if (!Object(_this))
|
||||
if (!_this || !_this->GetDef())
|
||||
throw new NeedNonGlobalContext("GetMass");
|
||||
else
|
||||
return cthr->Def->GetDef()->Mass;
|
||||
return _this->GetDef()->Mass;
|
||||
else
|
||||
return cthr->Obj->Mass;
|
||||
return Object(_this)->Mass;
|
||||
}
|
||||
|
||||
static long FnGetRDir(C4Object *Obj, long iPrec)
|
||||
|
@ -749,15 +749,15 @@ static bool FnSetKiller(C4Object *Obj, long iNewKiller)
|
|||
return true;
|
||||
}
|
||||
|
||||
static long FnGetCategory(C4AulContext *cthr)
|
||||
static long FnGetCategory(C4PropList * _this)
|
||||
{
|
||||
if (!cthr->Obj)
|
||||
if (!cthr->Def || !cthr->Def->GetDef())
|
||||
if (!Object(_this))
|
||||
if (!_this || !_this->GetDef())
|
||||
throw new NeedNonGlobalContext("GetCategory");
|
||||
else
|
||||
return cthr->Def->GetDef()->Category;
|
||||
return _this->GetDef()->Category;
|
||||
else
|
||||
return cthr->Obj->Category;
|
||||
return Object(_this)->Category;
|
||||
}
|
||||
|
||||
static long FnGetOCF(C4Object *Obj)
|
||||
|
@ -770,15 +770,15 @@ static long FnGetDamage(C4Object *Obj)
|
|||
return Obj->Damage;
|
||||
}
|
||||
|
||||
static long FnGetValue(C4AulContext *cthr, C4Object *pInBase, long iForPlayer)
|
||||
static long FnGetValue(C4PropList * _this, C4Object *pInBase, long iForPlayer)
|
||||
{
|
||||
if (!cthr->Obj)
|
||||
if (!cthr->Def || !cthr->Def->GetDef())
|
||||
if (!Object(_this))
|
||||
if (!_this || !_this->GetDef())
|
||||
throw new NeedNonGlobalContext("GetValue");
|
||||
else
|
||||
return cthr->Def->GetDef()->GetValue(pInBase, iForPlayer);
|
||||
return _this->GetDef()->GetValue(pInBase, iForPlayer);
|
||||
else
|
||||
return cthr->Obj->GetValue(pInBase, iForPlayer);
|
||||
return Object(_this)->GetValue(pInBase, iForPlayer);
|
||||
}
|
||||
|
||||
static long FnGetRank(C4Object *Obj)
|
||||
|
@ -895,7 +895,7 @@ static bool FnAddMenuItem(C4Object *Obj, C4String * szCaption, C4String * szComm
|
|||
else if (Parameter.getPropList()->GetDef())
|
||||
sprintf(parameter, "C4Id(\"%s\")", Parameter.getPropList()->GetDef()->id.ToString());
|
||||
else
|
||||
throw new C4AulExecError(Obj, "proplist as parameter to AddMenuItem");
|
||||
throw new C4AulExecError("proplist as parameter to AddMenuItem");
|
||||
break;
|
||||
case C4V_String:
|
||||
// note this breaks if there is '"' in the string.
|
||||
|
@ -908,7 +908,7 @@ static bool FnAddMenuItem(C4Object *Obj, C4String * szCaption, C4String * szComm
|
|||
break;
|
||||
case C4V_Array:
|
||||
// Arrays were never allowed, so tell the scripter
|
||||
throw new C4AulExecError(Obj, "array as parameter to AddMenuItem");
|
||||
throw new C4AulExecError("array as parameter to AddMenuItem");
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
@ -1053,8 +1053,7 @@ static bool FnAddMenuItem(C4Object *Obj, C4String * szCaption, C4String * szComm
|
|||
{
|
||||
// draw object picture
|
||||
if (!XPar.CheckConversion(C4V_Object))
|
||||
throw new C4AulExecError(Obj,
|
||||
FormatString("call to \"%s\" parameter %d: got \"%s\", but expected \"%s\"!",
|
||||
throw new C4AulExecError(FormatString("call to \"%s\" parameter %d: got \"%s\", but expected \"%s\"!",
|
||||
"AddMenuItem", 8, XPar.GetTypeName(), GetC4VName(C4V_Object)
|
||||
).getData());
|
||||
pGfxObj = XPar.getObj();
|
||||
|
@ -1294,9 +1293,9 @@ static long FnSetTransferZone(C4Object *Obj, long iX, long iY, long iWdt, long i
|
|||
return Game.TransferZones.Set(iX,iY,iWdt,iHgt,Obj);
|
||||
}
|
||||
|
||||
static long FnObjectDistance(C4AulContext *cthr, C4Object *pObj2, C4Object *pObj)
|
||||
static long FnObjectDistance(C4PropList * _this, C4Object *pObj2, C4Object *pObj)
|
||||
{
|
||||
if (!pObj) pObj=cthr->Obj; if (!pObj || !pObj2) return 0;
|
||||
if (!pObj) pObj=Object(_this); if (!pObj || !pObj2) return 0;
|
||||
return Distance(pObj->GetX(),pObj->GetY(),pObj2->GetX(),pObj2->GetY());
|
||||
}
|
||||
|
||||
|
@ -1506,13 +1505,13 @@ static bool FnSetGraphics(C4Object *Obj, C4String *pGfxName, C4Def *pSrcDef, lon
|
|||
return Obj->SetGraphics(FnStringPar(pGfxName), pSrcDef);
|
||||
}
|
||||
|
||||
static long FnGetDefBottom(C4AulContext* cthr)
|
||||
static long FnGetDefBottom(C4PropList * _this)
|
||||
{
|
||||
if (!cthr->Def || !cthr->Def->GetDef())
|
||||
if (!_this || !_this->GetDef())
|
||||
throw new NeedNonGlobalContext("GetDefBottom");
|
||||
|
||||
assert(!cthr->Obj || cthr->Obj->Def == cthr->Def->GetDef());
|
||||
return cthr->Def->GetDef()->Shape.y+cthr->Def->GetDef()->Shape.Hgt + (cthr->Obj ? cthr->Obj->GetY() : 0);
|
||||
assert(!Object(_this) || Object(_this)->Def == _this->GetDef());
|
||||
return _this->GetDef()->Shape.y+_this->GetDef()->Shape.Hgt + (Object(_this) ? Object(_this)->GetY() : 0);
|
||||
}
|
||||
|
||||
static bool FnSetMenuSize(C4Object *Obj, long iCols, long iRows)
|
||||
|
@ -2006,7 +2005,7 @@ static Nillable<int> FnAttachMesh(C4Object *Obj, C4PropList* Mesh, C4String * sz
|
|||
StdMeshMatrix trans = StdMeshMatrix::Identity();
|
||||
if (Transformation)
|
||||
if (!C4ValueToMatrix(*Transformation, &trans))
|
||||
throw new C4AulExecError(Obj, "AttachMesh: Transformation is not a valid 3x4 matrix");
|
||||
throw new C4AulExecError("AttachMesh: Transformation is not a valid 3x4 matrix");
|
||||
|
||||
StdMeshInstance::AttachedMesh* attach;
|
||||
C4Object* pObj = Mesh->GetObject();
|
||||
|
@ -2064,7 +2063,7 @@ static bool FnSetAttachTransform(C4Object *Obj, long iAttachNumber, C4ValueArray
|
|||
|
||||
StdMeshMatrix trans;
|
||||
if (!C4ValueToMatrix(*Transformation, &trans))
|
||||
throw new C4AulExecError(Obj, "SetAttachTransform: Transformation is not a valid 3x4 matrix");
|
||||
throw new C4AulExecError("SetAttachTransform: Transformation is not a valid 3x4 matrix");
|
||||
|
||||
attach->SetAttachTransformation(trans);
|
||||
return true;
|
||||
|
@ -2093,23 +2092,6 @@ static bool FnSetMeshMaterial(C4Object *Obj, C4String* Material, int iSubMesh)
|
|||
return true;
|
||||
}
|
||||
|
||||
static C4PropList* FnCreateRope(C4AulContext *cthr, C4Object* First, C4Object* Second, int SegmentLength, C4PropList* Graphics)
|
||||
{
|
||||
try
|
||||
{
|
||||
if(!Graphics) return false;
|
||||
C4Def* Def = Graphics->GetDef();
|
||||
if(!Def) return false;
|
||||
|
||||
return Game.Ropes.CreateRope(First, Second, itofix(SegmentLength), &Def->Graphics);
|
||||
}
|
||||
catch(const C4RopeError& err)
|
||||
{
|
||||
DebugLogF("Failed to create rope: %s", err.what());
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
//=========================== C4Script Function Map ===================================
|
||||
|
||||
C4ScriptConstDef C4ScriptObjectConstMap[]=
|
||||
|
@ -2430,7 +2412,6 @@ void InitObjectFunctionMap(C4AulScriptEngine *pEngine)
|
|||
AddFunc(pEngine, "SetAttachTransform", FnSetAttachTransform);
|
||||
AddFunc(pEngine, "GetMeshMaterial", FnGetMeshMaterial);
|
||||
AddFunc(pEngine, "SetMeshMaterial", FnSetMeshMaterial);
|
||||
AddFunc(pEngine, "CreateRope", FnCreateRope);
|
||||
AddFunc(pEngine, "ChangeDef", FnChangeDef);
|
||||
AddFunc(pEngine, "GrabContents", FnGrabContents);
|
||||
AddFunc(pEngine, "Punch", FnPunch);
|
||||
|
|
|
@ -19,67 +19,67 @@
|
|||
#include <C4Rope.h>
|
||||
#include <C4AulDefFunc.h>
|
||||
|
||||
static C4Void FnRemove(C4AulContext* Context)
|
||||
static C4Void FnRemove(C4PropList* Rope)
|
||||
{
|
||||
Game.Ropes.RemoveRope(static_cast<C4Rope*>(Context->Def));
|
||||
Game.Ropes.RemoveRope(static_cast<C4Rope*>(Rope));
|
||||
return C4Void();
|
||||
}
|
||||
|
||||
static C4Object* FnGetFront(C4AulContext* Context)
|
||||
static C4Object* FnGetFront(C4PropList* Rope)
|
||||
{
|
||||
return static_cast<C4Rope*>(Context->Def)->GetFront()->GetObject();
|
||||
return static_cast<C4Rope*>(Rope)->GetFront()->GetObject();
|
||||
}
|
||||
|
||||
static C4Object* FnGetBack(C4AulContext* Context)
|
||||
static C4Object* FnGetBack(C4PropList* Rope)
|
||||
{
|
||||
return static_cast<C4Rope*>(Context->Def)->GetBack()->GetObject();
|
||||
return static_cast<C4Rope*>(Rope)->GetBack()->GetObject();
|
||||
}
|
||||
|
||||
static C4Void FnSetFront(C4AulContext* Context, C4Object* obj, Nillable<int> x, Nillable<int> y)
|
||||
static C4Void FnSetFront(C4PropList* Rope, C4Object* obj, Nillable<int> x, Nillable<int> y)
|
||||
{
|
||||
static_cast<C4Rope*>(Context->Def)->SetFront(obj, x.IsNil() ? Fix0 : itofix(x), y.IsNil() ? Fix0 : itofix(y));
|
||||
static_cast<C4Rope*>(Rope)->SetFront(obj, x.IsNil() ? Fix0 : itofix(x), y.IsNil() ? Fix0 : itofix(y));
|
||||
return C4Void();
|
||||
}
|
||||
|
||||
static C4Void FnSetBack(C4AulContext* Context, C4Object* obj, Nillable<int> x, Nillable<int> y)
|
||||
static C4Void FnSetBack(C4PropList* Rope, C4Object* obj, Nillable<int> x, Nillable<int> y)
|
||||
{
|
||||
static_cast<C4Rope*>(Context->Def)->SetBack(obj, x.IsNil() ? Fix0 : itofix(x), y.IsNil() ? Fix0 : itofix(y));
|
||||
static_cast<C4Rope*>(Rope)->SetBack(obj, x.IsNil() ? Fix0 : itofix(x), y.IsNil() ? Fix0 : itofix(y));
|
||||
return C4Void();
|
||||
}
|
||||
|
||||
static C4Void FnSetFrontAutoSegmentation(C4AulContext* Context, int max)
|
||||
static C4Void FnSetFrontAutoSegmentation(C4PropList* Rope, int max)
|
||||
{
|
||||
static_cast<C4Rope*>(Context->Def)->SetFrontAutoSegmentation(itofix(max));
|
||||
static_cast<C4Rope*>(Rope)->SetFrontAutoSegmentation(itofix(max));
|
||||
return C4Void();
|
||||
}
|
||||
|
||||
static C4Void FnSetBackAutoSegmentation(C4AulContext* Context, int max)
|
||||
static C4Void FnSetBackAutoSegmentation(C4PropList* Rope, int max)
|
||||
{
|
||||
static_cast<C4Rope*>(Context->Def)->SetBackAutoSegmentation(itofix(max));
|
||||
static_cast<C4Rope*>(Rope)->SetBackAutoSegmentation(itofix(max));
|
||||
return C4Void();
|
||||
}
|
||||
|
||||
static C4Void FnSetFrontFixed(C4AulContext* Context, bool fixed)
|
||||
static C4Void FnSetFrontFixed(C4PropList* Rope, bool fixed)
|
||||
{
|
||||
static_cast<C4Rope*>(Context->Def)->SetFrontFixed(fixed);
|
||||
static_cast<C4Rope*>(Rope)->SetFrontFixed(fixed);
|
||||
return C4Void();
|
||||
}
|
||||
|
||||
static C4Void FnSetBackFixed(C4AulContext* Context, bool fixed)
|
||||
static C4Void FnSetBackFixed(C4PropList* Rope, bool fixed)
|
||||
{
|
||||
static_cast<C4Rope*>(Context->Def)->SetBackFixed(fixed);
|
||||
static_cast<C4Rope*>(Rope)->SetBackFixed(fixed);
|
||||
return C4Void();
|
||||
}
|
||||
|
||||
static C4Void FnPullFront(C4AulContext* Context, int force)
|
||||
static C4Void FnPullFront(C4PropList* Rope, int force)
|
||||
{
|
||||
static_cast<C4Rope*>(Context->Def)->PullFront(itofix(force));
|
||||
static_cast<C4Rope*>(Rope)->PullFront(itofix(force));
|
||||
return C4Void();
|
||||
}
|
||||
|
||||
static C4Void FnPullBack(C4AulContext* Context, int force)
|
||||
static C4Void FnPullBack(C4PropList* Rope, int force)
|
||||
{
|
||||
static_cast<C4Rope*>(Context->Def)->PullBack(itofix(force));
|
||||
static_cast<C4Rope*>(Rope)->PullBack(itofix(force));
|
||||
return C4Void();
|
||||
}
|
||||
|
||||
|
@ -96,8 +96,9 @@ C4RopeAul::~C4RopeAul()
|
|||
void C4RopeAul::InitFunctionMap(C4AulScriptEngine* pEngine)
|
||||
{
|
||||
delete RopeDef;
|
||||
RopeDef = C4PropList::NewScen();
|
||||
RopeDef->SetName("C4Rope");
|
||||
RopeDef = C4PropList::NewAnon(NULL, NULL, ::Strings.RegString("Rope"));
|
||||
RopeDef->SetName("Rope");
|
||||
pEngine->RegisterGlobalConstant("Rope", C4VPropList(RopeDef));
|
||||
|
||||
Reg2List(pEngine);
|
||||
|
||||
|
|
|
@ -240,6 +240,9 @@ LRESULT APIENTRY ViewportWinProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lPa
|
|||
StoreWindowPosition(hwnd, FormatString("Viewport%i",cvp->Player+1).getData(), Config.GetSubkeyPath("Console"));
|
||||
break;
|
||||
//----------------------------------------------------------------------------------------------------------------------------------
|
||||
case WM_CREATE:
|
||||
DragAcceptFiles(hwnd, TRUE);
|
||||
break;
|
||||
case WM_CLOSE:
|
||||
cvp->pWindow->Close();
|
||||
break;
|
||||
|
@ -252,11 +255,11 @@ LRESULT APIENTRY ViewportWinProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lPa
|
|||
|
||||
int32_t iFileNum = DragQueryFile(hDrop,0xFFFFFFFF,NULL,0);
|
||||
POINT pntPoint;
|
||||
DragQueryPoint(hDrop,&pntPoint);
|
||||
wchar_t szFilename[500+1];
|
||||
for (int32_t cnt=0; cnt<iFileNum; cnt++)
|
||||
{
|
||||
DragQueryFileW(hDrop,cnt,szFilename,500);
|
||||
DragQueryPoint(hDrop,&pntPoint);
|
||||
cvp->DropFile(StdStrBuf(szFilename).getData(), (float)pntPoint.x, (float)pntPoint.y);
|
||||
}
|
||||
DragFinish(hDrop);
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
* "Clonk" is a registered trademark of Matthes Bender.
|
||||
* See clonk_trademark_license.txt for full license.
|
||||
*/
|
||||
// C4Aul script engine CP conversion
|
||||
// Miscellaneous script engine bits
|
||||
|
||||
#include <C4Include.h>
|
||||
#include <C4Aul.h>
|
||||
|
@ -44,127 +44,17 @@ void C4AulError::show()
|
|||
DebugLog(sMessage.getData());
|
||||
}
|
||||
|
||||
C4AulFunc::C4AulFunc(C4AulScript *pOwner, const char *pName):
|
||||
iRefCnt(0),
|
||||
Name(pName ? Strings.RegString(pName) : 0),
|
||||
MapNext(NULL),
|
||||
OverloadedBy (NULL)
|
||||
{
|
||||
AppendToScript(pOwner);
|
||||
IncRef(); // see C4AulScript::Clear()
|
||||
}
|
||||
|
||||
void C4AulFunc::AppendToScript(C4AulScript * pOwner)
|
||||
{
|
||||
Owner = pOwner;
|
||||
if ((Prev = Owner->FuncL))
|
||||
{
|
||||
Prev->Next = this;
|
||||
Owner->FuncL = this;
|
||||
}
|
||||
else
|
||||
{
|
||||
Owner->Func0 = this;
|
||||
Owner->FuncL = this;
|
||||
}
|
||||
Next = NULL;
|
||||
assert(GetName() || Owner->Temporary);
|
||||
// add to global lookuptable with this name
|
||||
if (GetName())
|
||||
Owner->Engine->FuncLookUp.Add(this, true);
|
||||
}
|
||||
|
||||
void C4AulFunc::RemoveFromScript()
|
||||
{
|
||||
if (Prev) Prev->Next = Next;
|
||||
if (Next) Next->Prev = Prev;
|
||||
if (Owner->Func0 == this) Owner->Func0 = Next;
|
||||
if (Owner->FuncL == this) Owner->FuncL = Prev;
|
||||
assert(Owner);
|
||||
assert(Owner->Temporary || Name);
|
||||
assert(!Owner->GetPropList() || Owner->GetPropList()->GetFunc(Name) != this);
|
||||
if (GetName())
|
||||
Owner->Engine->FuncLookUp.Remove(this);
|
||||
Prev = 0;
|
||||
Next = 0;
|
||||
Owner = 0;
|
||||
}
|
||||
|
||||
C4AulFunc::~C4AulFunc()
|
||||
{
|
||||
// remove from list
|
||||
if (Prev) Prev->Next = Next;
|
||||
if (Next) Next->Prev = Prev;
|
||||
if (Owner)
|
||||
{
|
||||
if (Owner->Func0 == this) Owner->Func0 = Next;
|
||||
if (Owner->FuncL == this) Owner->FuncL = Prev;
|
||||
if (GetName())
|
||||
Owner->Engine->FuncLookUp.Remove(this);
|
||||
if (Owner->GetPropList() && Name)
|
||||
{
|
||||
C4Value v;
|
||||
Owner->GetPropList()->GetPropertyByS(Name, &v);
|
||||
assert(v.getFunction() != this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
StdStrBuf C4AulFunc::GetFullName()
|
||||
{
|
||||
// "lost" function?
|
||||
StdStrBuf sOwner;
|
||||
if (!Owner)
|
||||
{
|
||||
sOwner.Ref("(unknown) ");
|
||||
}
|
||||
else if (Owner->GetPropList() && Owner->GetPropList()->GetDef())
|
||||
{
|
||||
sOwner.Format("%s.", Owner->GetPropList()->GetDef()->id.ToString());
|
||||
}
|
||||
else if (Owner->Engine == Owner)
|
||||
{
|
||||
sOwner.Ref("global ");
|
||||
}
|
||||
else
|
||||
{
|
||||
sOwner.Ref("game ");
|
||||
}
|
||||
StdStrBuf sResult;
|
||||
sResult.Format("%s%s", sOwner.getData(), GetName());
|
||||
return sResult;
|
||||
}
|
||||
|
||||
C4AulDefFunc::C4AulDefFunc(C4AulScript *pOwner, const char *pName, C4ScriptFnDef* pDef):
|
||||
C4AulFunc(pOwner, pName) // constructor
|
||||
{
|
||||
Def = pDef;
|
||||
Owner->GetPropList()->SetPropertyByS(Name, C4VFunction(this));
|
||||
}
|
||||
|
||||
C4AulDefFunc::~C4AulDefFunc()
|
||||
{
|
||||
assert(!Owner);
|
||||
}
|
||||
|
||||
C4AulScript::C4AulScript()
|
||||
{
|
||||
// not compiled
|
||||
State = ASS_NONE;
|
||||
IncludesResolved = false;
|
||||
|
||||
// defaults
|
||||
Resolving=false;
|
||||
Temporary = false;
|
||||
LocalNamed.Reset();
|
||||
|
||||
// prepare lists
|
||||
Prev = Next = NULL;
|
||||
Engine = NULL;
|
||||
Func0 = FuncL = NULL;
|
||||
// prepare include list
|
||||
Includes.clear();
|
||||
Appends.clear();
|
||||
}
|
||||
|
||||
C4AulScript::~C4AulScript()
|
||||
|
@ -188,15 +78,6 @@ void C4AulScript::Unreg()
|
|||
|
||||
void C4AulScript::Clear()
|
||||
{
|
||||
// remove includes
|
||||
Includes.clear();
|
||||
Appends.clear();
|
||||
while (Func0)
|
||||
{
|
||||
C4AulFunc * f = Func0;
|
||||
f->RemoveFromScript();
|
||||
f->DecRef(); // see C4AulFunc::C4AulFunc
|
||||
}
|
||||
// reset flags
|
||||
State = ASS_NONE;
|
||||
}
|
||||
|
@ -263,13 +144,17 @@ C4AulScriptFunc::C4AulScriptFunc(C4AulScript *pOwner, const C4AulScriptFunc &Fro
|
|||
ParType[i] = FromFunc.ParType[i];
|
||||
}
|
||||
|
||||
|
||||
void C4AulScript::AddFunc(const char *pIdtf, C4ScriptFnDef* Def)
|
||||
C4AulScriptFunc::~C4AulScriptFunc()
|
||||
{
|
||||
// create def func
|
||||
new C4AulDefFunc(this, pIdtf, Def);
|
||||
if (OwnerOverloaded) OwnerOverloaded->DecRef();
|
||||
}
|
||||
|
||||
void C4AulScriptFunc::SetOverloaded(C4AulFunc * f)
|
||||
{
|
||||
if (OwnerOverloaded) OwnerOverloaded->DecRef();
|
||||
OwnerOverloaded = f;
|
||||
if (f) f->IncRef();
|
||||
}
|
||||
|
||||
/*--- C4AulScriptEngine ---*/
|
||||
|
||||
|
@ -293,7 +178,7 @@ C4PropList * C4AulScriptEngine::GetPropList()
|
|||
{
|
||||
if (!GlobalPropList)
|
||||
{
|
||||
GlobalPropList = C4PropList::NewScen();
|
||||
GlobalPropList = C4PropList::NewAnon(NULL, NULL, ::Strings.RegString("Global"));
|
||||
RegisterGlobalConstant("Global", C4VPropList(GlobalPropList));
|
||||
}
|
||||
return GlobalPropList;
|
||||
|
@ -327,21 +212,6 @@ void C4AulScriptEngine::Clear()
|
|||
GlobalNamed.SetNameList(&GlobalNamedNames);
|
||||
}
|
||||
|
||||
|
||||
void C4AulScriptEngine::UnLink()
|
||||
{
|
||||
// unlink scripts
|
||||
for (C4AulScript *s = Child0; s; s = s->Next)
|
||||
s->UnLink();
|
||||
C4AulScript::UnLink();
|
||||
// Do not clear global variables and constants, because they are registered by the
|
||||
// preparser or other parts. Note that keeping those fields means that you cannot delete a global
|
||||
// variable or constant at runtime by removing it from the script.
|
||||
//GlobalNamedNames.Reset();
|
||||
//GlobalConstNames.Reset();
|
||||
}
|
||||
|
||||
|
||||
void C4AulScriptEngine::RegisterGlobalConstant(const char *szName, const C4Value &rValue)
|
||||
{
|
||||
// Register name and set value.
|
||||
|
@ -368,7 +238,7 @@ bool C4AulScriptEngine::Denumerate(C4ValueNumbers * numbers)
|
|||
{
|
||||
GlobalNamed.Denumerate(numbers);
|
||||
// runtime data only: don't denumerate consts
|
||||
GameScript.ScenPropList->Denumerate(numbers);
|
||||
GameScript.ScenPropList.Denumerate(numbers);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -377,54 +247,45 @@ void C4AulScriptEngine::CompileFunc(StdCompiler *pComp, C4ValueNumbers * numbers
|
|||
C4ValueMapData GlobalNamedDefault;
|
||||
GlobalNamedDefault.SetNameList(&GlobalNamedNames);
|
||||
pComp->Value(mkNamingAdapt(mkParAdapt(GlobalNamed, numbers), "StaticVariables", GlobalNamedDefault));
|
||||
pComp->Value(mkNamingAdapt(mkParAdapt(*GameScript.ScenPropList, numbers), "Scenario"));
|
||||
pComp->Value(mkNamingAdapt(mkParAdapt(*GameScript.ScenPropList._getPropList(), numbers), "Scenario"));
|
||||
}
|
||||
|
||||
std::list<const char*> C4AulScriptEngine::GetFunctionNames(C4AulScript * script)
|
||||
std::list<const char*> C4AulScriptEngine::GetFunctionNames(C4PropList * p)
|
||||
{
|
||||
std::list<const char*> functions;
|
||||
for (C4AulFunc *pFn = Func0; pFn; pFn = pFn->Next)
|
||||
std::list<const char*> global_functions;
|
||||
if (!p) p = GetPropList();
|
||||
const C4ValueArray * a = p->GetProperties();
|
||||
for (int i = 0; i < a->GetSize(); ++i)
|
||||
{
|
||||
if (pFn->GetPublic())
|
||||
{
|
||||
functions.push_back(pFn->GetName());
|
||||
}
|
||||
}
|
||||
// Add object or scenario script functions
|
||||
if (script)
|
||||
{
|
||||
bool divider = false;
|
||||
C4AulFunc *f = script->FuncL;
|
||||
C4AulScriptFunc *pRef;
|
||||
// Scan all functions
|
||||
while (f)
|
||||
{
|
||||
if ((pRef = f->SFunc()))
|
||||
{
|
||||
// Insert divider if necessary
|
||||
if (!divider)
|
||||
functions.push_back(0);
|
||||
divider = true;
|
||||
// Add function
|
||||
functions.push_back(pRef->GetName());
|
||||
}
|
||||
f = f->Prev;
|
||||
}
|
||||
C4String * key = (*a)[i].getStr();
|
||||
if (!key) continue;
|
||||
C4AulFunc * f = p->GetFunc(key);
|
||||
if (!f) continue;
|
||||
if (!f->GetPublic()) continue;
|
||||
if (p->HasProperty(key))
|
||||
functions.push_back(key->GetCStr());
|
||||
else
|
||||
global_functions.push_back(key->GetCStr());
|
||||
}
|
||||
delete a;
|
||||
functions.sort();
|
||||
functions.push_back(0);
|
||||
global_functions.sort();
|
||||
functions.splice(functions.end(), global_functions);
|
||||
return functions;
|
||||
}
|
||||
|
||||
/*--- C4AulFuncMap ---*/
|
||||
static const size_t CapacityInc = 1024;
|
||||
|
||||
C4AulFuncMap::C4AulFuncMap(): Funcs(new C4AulFunc*[CapacityInc]), FuncCnt(0), Capacity(CapacityInc)
|
||||
C4AulFuncMap::C4AulFuncMap(): FuncCnt(0)
|
||||
{
|
||||
memset(Funcs, 0, sizeof (C4AulFunc *) * Capacity);
|
||||
memset(Funcs, 0, sizeof (C4AulFunc *) * HashSize);
|
||||
}
|
||||
|
||||
C4AulFuncMap::~C4AulFuncMap()
|
||||
{
|
||||
delete[] Funcs;
|
||||
assert(!FuncCnt);
|
||||
}
|
||||
|
||||
unsigned int C4AulFuncMap::Hash(const char * name)
|
||||
|
@ -436,11 +297,11 @@ unsigned int C4AulFuncMap::Hash(const char * name)
|
|||
return h;
|
||||
}
|
||||
|
||||
C4AulFunc * C4AulFuncMap::GetFirstFunc(const char * Name)
|
||||
C4AulFunc * C4AulFuncMap::GetFirstFunc(C4String * Name)
|
||||
{
|
||||
if (!Name) return NULL;
|
||||
C4AulFunc * Func = Funcs[Hash(Name) % Capacity];
|
||||
while (Func && !SEqual(Name, Func->GetName()))
|
||||
C4AulFunc * Func = Funcs[Hash(Name->GetCStr()) % HashSize];
|
||||
while (Func && Name->GetCStr() != Func->GetName())
|
||||
Func = Func->MapNext;
|
||||
return Func;
|
||||
}
|
||||
|
@ -448,60 +309,25 @@ C4AulFunc * C4AulFuncMap::GetFirstFunc(const char * Name)
|
|||
C4AulFunc * C4AulFuncMap::GetNextSNFunc(const C4AulFunc * After)
|
||||
{
|
||||
C4AulFunc * Func = After->MapNext;
|
||||
while (Func && !SEqual(After->GetName(), Func->GetName()))
|
||||
while (Func && After->GetName() != Func->GetName())
|
||||
Func = Func->MapNext;
|
||||
return Func;
|
||||
}
|
||||
|
||||
void C4AulFuncMap::Add(C4AulFunc * func, bool bAtStart)
|
||||
void C4AulFuncMap::Add(C4AulFunc * func)
|
||||
{
|
||||
if (++FuncCnt > Capacity)
|
||||
{
|
||||
int NCapacity = Capacity + CapacityInc;
|
||||
C4AulFunc ** NFuncs = new C4AulFunc*[NCapacity];
|
||||
memset(NFuncs, 0, sizeof (C4AulFunc *) * NCapacity);
|
||||
for (int i = 0; i < Capacity; ++i)
|
||||
{
|
||||
while (Funcs[i])
|
||||
{
|
||||
// Get a pointer to the bucket
|
||||
C4AulFunc ** pNFunc = &(NFuncs[Hash(Funcs[i]->GetName()) % NCapacity]);
|
||||
// get a pointer to the end of the linked list
|
||||
while (*pNFunc) pNFunc = &((*pNFunc)->MapNext);
|
||||
// Move the func over
|
||||
*pNFunc = Funcs[i];
|
||||
// proceed with the next list member
|
||||
Funcs[i] = Funcs[i]->MapNext;
|
||||
// Terminate the linked list
|
||||
(*pNFunc)->MapNext = 0;
|
||||
}
|
||||
}
|
||||
Capacity = NCapacity;
|
||||
delete [] Funcs;
|
||||
Funcs = NFuncs;
|
||||
}
|
||||
++FuncCnt;
|
||||
// Get a pointer to the bucket
|
||||
C4AulFunc ** pFunc = &(Funcs[Hash(func->GetName()) % Capacity]);
|
||||
if (bAtStart)
|
||||
{
|
||||
// move the current first to the second position
|
||||
func->MapNext = *pFunc;
|
||||
}
|
||||
else
|
||||
{
|
||||
// get a pointer to the end of the linked list
|
||||
while (*pFunc)
|
||||
{
|
||||
pFunc = &((*pFunc)->MapNext);
|
||||
}
|
||||
}
|
||||
C4AulFunc ** pFunc = &(Funcs[Hash(func->GetName()) % HashSize]);
|
||||
// move the current first to the second position
|
||||
func->MapNext = *pFunc;
|
||||
// Add the func
|
||||
*pFunc = func;
|
||||
}
|
||||
|
||||
void C4AulFuncMap::Remove(C4AulFunc * func)
|
||||
{
|
||||
C4AulFunc ** pFunc = &Funcs[Hash(func->GetName()) % Capacity];
|
||||
C4AulFunc ** pFunc = &Funcs[Hash(func->GetName()) % HashSize];
|
||||
while (*pFunc != func)
|
||||
{
|
||||
pFunc = &((*pFunc)->MapNext);
|
||||
|
|
|
@ -62,9 +62,8 @@ public:
|
|||
// execution error
|
||||
class C4AulExecError : public C4AulError
|
||||
{
|
||||
C4Object *cObj;
|
||||
public:
|
||||
C4AulExecError(C4Object *pObj, const char *szError); // constructor
|
||||
C4AulExecError(const char *szError);
|
||||
};
|
||||
|
||||
// function access
|
||||
|
@ -76,25 +75,6 @@ enum C4AulAccess
|
|||
AA_GLOBAL
|
||||
};
|
||||
|
||||
struct C4AulParSet
|
||||
{
|
||||
C4Value Par[C4AUL_MAX_Par];
|
||||
|
||||
C4AulParSet() {} // standard-constructor
|
||||
C4AulParSet(const C4Value &par0, const C4Value &par1 = C4Value(), const C4Value &par2 = C4Value(), const C4Value &par3 = C4Value(), const C4Value &par4 = C4Value(),
|
||||
const C4Value &par5 = C4Value(), const C4Value &par6 = C4Value(), const C4Value &par7 = C4Value(), const C4Value &par8 = C4Value(), const C4Value &par9 = C4Value())
|
||||
{
|
||||
Par[0].Set(par0); Par[1].Set(par1); Par[2].Set(par2); Par[3].Set(par3); Par[4].Set(par4);
|
||||
Par[5].Set(par5); Par[6].Set(par6); Par[7].Set(par7); Par[8].Set(par8); Par[9].Set(par9);
|
||||
}
|
||||
C4Value & operator[](int iIdx) { return Par[iIdx]; }
|
||||
C4AulParSet * operator&() { return this; }
|
||||
};
|
||||
|
||||
#define Copy2ParSet8(Pars, Vars) Pars[0].Set(Vars##0); Pars[1].Set(Vars##1); Pars[2].Set(Vars##2); Pars[3].Set(Vars##3); Pars[4].Set(Vars##4); Pars[5].Set(Vars##5); Pars[6].Set(Vars##6); Pars[7].Set(Vars##7);
|
||||
#define Copy2ParSet9(Pars, Vars) Pars[0].Set(Vars##0); Pars[1].Set(Vars##1); Pars[2].Set(Vars##2); Pars[3].Set(Vars##3); Pars[4].Set(Vars##4); Pars[5].Set(Vars##5); Pars[6].Set(Vars##6); Pars[7].Set(Vars##7); Pars[8].Set(Vars##8);
|
||||
#define Copy2ParSet10(Pars, Vars) Pars[0].Set(Vars##0); Pars[1].Set(Vars##1); Pars[2].Set(Vars##2); Pars[3].Set(Vars##3); Pars[4].Set(Vars##4); Pars[5].Set(Vars##5); Pars[6].Set(Vars##6); Pars[7].Set(Vars##7); Pars[8].Set(Vars##8); Pars[9].Set(Vars##9);
|
||||
|
||||
// byte code chunk type
|
||||
// some special script functions defined hard-coded to reduce the exec context
|
||||
enum C4AulBCCType
|
||||
|
@ -185,16 +165,10 @@ struct C4AulBCC
|
|||
} Par; // extra info
|
||||
};
|
||||
|
||||
// call context
|
||||
struct C4AulContext
|
||||
{
|
||||
C4Object *Obj;
|
||||
C4PropList *Def;
|
||||
};
|
||||
|
||||
// execution context
|
||||
struct C4AulScriptContext : public C4AulContext
|
||||
struct C4AulScriptContext
|
||||
{
|
||||
C4PropList *Obj;
|
||||
C4Value *Return;
|
||||
C4Value *Pars;
|
||||
C4Value *Vars;
|
||||
|
@ -212,6 +186,7 @@ class C4AulScriptFunc : public C4AulFunc
|
|||
{
|
||||
public:
|
||||
C4AulFunc *OwnerOverloaded; // overloaded owner function; if present
|
||||
void SetOverloaded(C4AulFunc *);
|
||||
C4AulScriptFunc *SFunc() { return this; } // type check func...
|
||||
protected:
|
||||
int CodePos; // code pos
|
||||
|
@ -227,18 +202,15 @@ public:
|
|||
|
||||
C4AulScriptFunc(C4AulScript *pOwner, C4ScriptHost *pOrgScript, const char *pName, const char *Script);
|
||||
C4AulScriptFunc(C4AulScript *pOwner, const C4AulScriptFunc &FromFunc); // copy script/code, etc from given func
|
||||
~C4AulScriptFunc();
|
||||
|
||||
void ParseFn(C4AulScriptContext* context = NULL);
|
||||
virtual void UnLink();
|
||||
|
||||
virtual bool GetPublic() { return true; }
|
||||
virtual int GetParCount() { return ParCount; }
|
||||
virtual C4V_Type *GetParType() { return ParType; }
|
||||
virtual C4V_Type GetRetType() { return C4V_Any; }
|
||||
virtual C4Value Exec(C4AulContext *pCallerCtx, C4Value pPars[], bool fPassErrors=false); // execute func (script call, should not happen)
|
||||
virtual C4Value Exec(C4PropList * p = NULL, C4AulParSet *pPars = NULL, bool fPassErrors=false); // execute func (engine call)
|
||||
|
||||
void SetError(C4AulContext *ctx, const char *szMessage); // set error message
|
||||
virtual C4Value Exec(C4PropList * p, C4Value pPars[], bool fPassErrors=false); // execute func
|
||||
|
||||
int GetLineOfCode(C4AulBCC * bcc);
|
||||
C4AulBCC * GetCode();
|
||||
|
@ -250,37 +222,20 @@ public:
|
|||
friend class C4ScriptHost;
|
||||
};
|
||||
|
||||
// defined function class
|
||||
class C4AulDefFunc : C4AulFunc
|
||||
{
|
||||
public:
|
||||
C4ScriptFnDef* Def;
|
||||
|
||||
C4AulDefFunc(C4AulScript *pOwner, const char *pName, C4ScriptFnDef* pDef);
|
||||
~C4AulDefFunc();
|
||||
|
||||
virtual bool GetPublic() { return !!Def->Public; }
|
||||
virtual C4V_Type* GetParType() { return Def->ParType; }
|
||||
virtual C4V_Type GetRetType() { return Def->RetType; }
|
||||
|
||||
using C4AulFunc::Exec;
|
||||
virtual C4Value Exec(C4AulContext *pCallerCtx, C4Value pPars[], bool fPassErrors=false); // execute func (script call)
|
||||
};
|
||||
|
||||
class C4AulFuncMap
|
||||
{
|
||||
public:
|
||||
C4AulFuncMap();
|
||||
~C4AulFuncMap();
|
||||
C4AulFunc * GetFirstFunc(const char * Name);
|
||||
C4AulFunc * GetFirstFunc(C4String * Name);
|
||||
C4AulFunc * GetNextSNFunc(const C4AulFunc * After);
|
||||
private:
|
||||
C4AulFunc ** Funcs;
|
||||
enum { HashSize = 1025 };
|
||||
C4AulFunc * Funcs[HashSize];
|
||||
int FuncCnt;
|
||||
int Capacity;
|
||||
static unsigned int Hash(const char * Name);
|
||||
protected:
|
||||
void Add(C4AulFunc * func, bool bAtEnd = true);
|
||||
void Add(C4AulFunc * func);
|
||||
void Remove(C4AulFunc * func);
|
||||
friend class C4AulFunc;
|
||||
friend class C4ScriptHost;
|
||||
|
@ -336,22 +291,19 @@ public:
|
|||
virtual bool Delete() { return true; } // allow deletion on pure class
|
||||
|
||||
StdCopyStrBuf ScriptName; // script name
|
||||
C4ValueMapNames LocalNamed;
|
||||
bool Temporary; // set for DirectExec-scripts; do not parse those
|
||||
|
||||
virtual C4PropList * GetPropList() { return 0; }
|
||||
virtual C4ScriptHost * GetScriptHost() { return 0; }
|
||||
|
||||
void AddFunc(const char *pIdtf, C4ScriptFnDef* Def); // add def def func to table
|
||||
|
||||
C4Value DirectExec(C4Object *pObj, const char *szScript, const char *szContext, bool fPassErrors = false, C4AulScriptContext* context = NULL); // directly parse uncompiled script (WARG! CYCLES!)
|
||||
void ResetProfilerTimes(); // zero all profiler times of owned functions
|
||||
void CollectProfilerTimes(class C4AulProfiler &rProfiler);
|
||||
virtual void ResetProfilerTimes(); // zero all profiler times of owned functions
|
||||
virtual void CollectProfilerTimes(class C4AulProfiler &rProfiler);
|
||||
|
||||
bool IsReady() { return State == ASS_PARSED; } // whether script calls may be done
|
||||
|
||||
// helper functions
|
||||
void Warn(const char *pMsg, const char *pIdtf);
|
||||
void Warn(const char *pMsg, ...) GNUC_FORMAT_ATTRIBUTE_O;
|
||||
|
||||
friend class C4AulParseError;
|
||||
friend class C4AulFunc;
|
||||
|
@ -367,24 +319,16 @@ public:
|
|||
protected:
|
||||
C4LangStringTable *stringTable;
|
||||
|
||||
C4AulFunc *Func0, *FuncL; // owned functions
|
||||
C4AulScriptEngine *Engine; //owning engine
|
||||
C4AulScript *Prev, *Next; // tree structure
|
||||
|
||||
C4AulScriptState State; // script state
|
||||
bool Resolving; // set while include-resolving, to catch circular includes
|
||||
|
||||
std::list<C4ID> Includes; // include list
|
||||
std::list<C4ID> Appends; // append list
|
||||
|
||||
bool ResolveIncludes(C4DefList *rDefs); // resolve includes
|
||||
bool ResolveAppends(C4DefList *rDefs); // resolve appends
|
||||
void LinkFunctions();
|
||||
bool IncludesResolved;
|
||||
virtual void UnLink(); // reset to unlinked state
|
||||
virtual bool ReloadScript(const char *szPath, const char *szLanguage); // reload given script
|
||||
virtual bool Parse();
|
||||
|
||||
virtual bool ResolveIncludes(C4DefList *rDefs);
|
||||
virtual bool ResolveAppends(C4DefList *rDefs);
|
||||
virtual void UnLink();
|
||||
};
|
||||
|
||||
// holds all C4AulScripts
|
||||
|
@ -417,13 +361,13 @@ public:
|
|||
virtual C4PropList * GetPropList();
|
||||
using C4AulScript::ReloadScript;
|
||||
bool ReloadScript(const char *szScript, C4DefList *pDefs, const char *szLanguage); // search script and reload + relink, if found
|
||||
C4AulFunc * GetFirstFunc(const char * Name)
|
||||
C4AulFunc * GetFirstFunc(C4String * Name)
|
||||
{ return FuncLookUp.GetFirstFunc(Name); }
|
||||
C4AulFunc * GetNextSNFunc(const C4AulFunc * After)
|
||||
{ return FuncLookUp.GetNextSNFunc(After); }
|
||||
|
||||
// For the list of functions in the PropertyDlg
|
||||
std::list<const char*> GetFunctionNames(C4AulScript *);
|
||||
std::list<const char*> GetFunctionNames(C4PropList *);
|
||||
void ResetProfilerTimes(); // zero all profiler times of owned functions
|
||||
void CollectProfilerTimes(class C4AulProfiler &rProfiler);
|
||||
|
||||
|
|
|
@ -229,7 +229,9 @@ void C4AulDebug::ProcessLine(const StdStrBuf &Line)
|
|||
else if (SEqualNoCase(szCmd, "EXC") || SEqualNoCase(szCmd, "E"))
|
||||
{
|
||||
C4AulScriptContext* context = pExec->GetContext(pExec->GetContextDepth()-1);
|
||||
int32_t objectNum = context && context->Obj ? context->Obj->Number : C4ControlScript::SCOPE_Global;
|
||||
int32_t objectNum = C4ControlScript::SCOPE_Global;
|
||||
if (context && context->Obj && context->Obj->GetObject())
|
||||
objectNum = context->Obj->GetObject()->Number;
|
||||
::Control.DoInput(CID_Script, new C4ControlScript(szData, objectNum, true, true), CDT_Decide);
|
||||
}
|
||||
else if (SEqualNoCase(szCmd, "PSE"))
|
||||
|
|
|
@ -26,24 +26,6 @@
|
|||
#include <C4Effect.h>
|
||||
#include <C4DefList.h>
|
||||
|
||||
typedef int32_t t_int;
|
||||
typedef bool t_bool;
|
||||
typedef C4ID t_id;
|
||||
typedef C4Object *t_object;
|
||||
typedef C4String *t_string;
|
||||
typedef C4Value t_any;
|
||||
typedef C4ValueArray *t_array;
|
||||
|
||||
inline t_int getPar_int(C4Value *pVal) { return pVal->getInt(); }
|
||||
inline t_bool getPar_bool(C4Value *pVal) { return pVal->getBool(); }
|
||||
inline t_id getPar_id(C4Value *pVal) { return pVal->getC4ID(); }
|
||||
inline t_object getPar_object(C4Value *pVal) { return pVal->getObj(); }
|
||||
inline t_string getPar_string(C4Value *pVal) { return pVal->getStr(); }
|
||||
inline t_any getPar_any(C4Value *pVal) { return *pVal; }
|
||||
inline t_array getPar_array(C4Value *pVal) { return pVal->getArray(); }
|
||||
|
||||
#define PAR(type, name) t_##type name = getPar_##type(pPars++)
|
||||
|
||||
inline const static char *FnStringPar(C4String *pString)
|
||||
{
|
||||
return pString ? pString->GetCStr() : "";
|
||||
|
@ -52,9 +34,11 @@ inline C4String *String(const char * str)
|
|||
{
|
||||
return str ? ::Strings.RegString(str) : NULL;
|
||||
}
|
||||
StdStrBuf FnStringFormat(C4AulContext *cthr, const char *szFormatPar, C4Value * Par0=0, C4Value * Par1=0, C4Value * Par2=0, C4Value * Par3=0,
|
||||
C4Value * Par4=0, C4Value * Par5=0, C4Value * Par6=0, C4Value * Par7=0, C4Value * Par8=0, C4Value * Par9=0);
|
||||
enum { MaxFnStringParLen=500 };
|
||||
inline C4Object * Object(C4PropList * _this)
|
||||
{
|
||||
return _this ? _this->GetObject() : NULL;
|
||||
}
|
||||
StdStrBuf FnStringFormat(C4PropList * _this, C4String *szFormatPar, C4Value * Pars, int ParCount);
|
||||
|
||||
template <typename T> struct C4ValueConv;
|
||||
// Allow parameters to be nil
|
||||
|
@ -102,7 +86,7 @@ public:
|
|||
class NeedDefinitionContext : public C4AulExecError
|
||||
{
|
||||
public:
|
||||
NeedDefinitionContext(const char *function) : C4AulExecError(NULL, FormatString("%s: must be called from definition context", function).getData()) {}
|
||||
NeedDefinitionContext(const char *function) : C4AulExecError(FormatString("%s: must be called from definition context", function).getData()) {}
|
||||
};
|
||||
|
||||
// Other functions are callable in object context only.
|
||||
|
@ -110,7 +94,7 @@ public:
|
|||
class NeedObjectContext : public C4AulExecError
|
||||
{
|
||||
public:
|
||||
NeedObjectContext(const char *function) : C4AulExecError(NULL, FormatString("%s: must be called from object context", function).getData()) {}
|
||||
NeedObjectContext(const char *function) : C4AulExecError(FormatString("%s: must be called from object context", function).getData()) {}
|
||||
};
|
||||
|
||||
// Then there's functions that don't care, but need either defn or object context.
|
||||
|
@ -118,7 +102,7 @@ public:
|
|||
class NeedNonGlobalContext : public C4AulExecError
|
||||
{
|
||||
public:
|
||||
NeedNonGlobalContext(const char *function) : C4AulExecError(NULL, FormatString("%s: call must not be from global context", function).getData()) {}
|
||||
NeedNonGlobalContext(const char *function) : C4AulExecError(FormatString("%s: call must not be from global context", function).getData()) {}
|
||||
};
|
||||
|
||||
// return type of functions returning nil
|
||||
|
@ -254,7 +238,6 @@ public:
|
|||
}
|
||||
~C4AulDefFuncHelper()
|
||||
{
|
||||
assert(!Owner);
|
||||
}
|
||||
virtual C4V_Type* GetParType() { return ParType; }
|
||||
virtual bool GetPublic() { return Public; }
|
||||
|
@ -294,18 +277,16 @@ class C4AulDefFunc##N: \
|
|||
public C4AulDefFuncHelper { \
|
||||
public: \
|
||||
/* A pointer to the function which this class wraps */ \
|
||||
typedef RType (*Func)(C4AulContext * LIST(N, PARS)); \
|
||||
typedef RType (*Func)(C4PropList * LIST(N, PARS)); \
|
||||
virtual int GetParCount() { return N; } \
|
||||
virtual C4V_Type GetRetType() \
|
||||
{ return C4ValueConv<RType>::Type(); } \
|
||||
/* Constructor, using the base class to create the ParType array */ \
|
||||
C4AulDefFunc##N(C4AulScript *pOwner, const char *pName, Func pFunc, bool Public): \
|
||||
C4AulDefFuncHelper(pOwner, pName, Public LIST(N, CONV_TYPE)), pFunc(pFunc) { } \
|
||||
/* Avoid hiding base class function */ \
|
||||
using C4AulFunc::Exec; \
|
||||
/* Extracts the parameters from C4Values and wraps the return value in a C4Value */ \
|
||||
virtual C4Value Exec(C4AulContext *pContext, C4Value pPars[], bool fPassErrors=false) \
|
||||
{ return C4ValueConv<RType>::ToC4V(pFunc(pContext LIST(N, CONV_FROM_C4V))); } \
|
||||
virtual C4Value Exec(C4PropList * _this, C4Value pPars[], bool fPassErrors) \
|
||||
{ return C4ValueConv<RType>::ToC4V(pFunc(_this LIST(N, CONV_FROM_C4V))); } \
|
||||
protected: \
|
||||
Func pFunc; \
|
||||
}; \
|
||||
|
@ -321,19 +302,17 @@ public C4AulDefFuncHelper { \
|
|||
/* Constructor, using the base class to create the ParType array */ \
|
||||
C4AulDefObjectFunc##N(C4AulScript *pOwner, const char *pName, Func pFunc, bool Public): \
|
||||
C4AulDefFuncHelper(pOwner, pName, Public LIST(N, CONV_TYPE)), pFunc(pFunc) { } \
|
||||
/* Avoid hiding base class function */ \
|
||||
using C4AulFunc::Exec; \
|
||||
/* Extracts the parameters from C4Values and wraps the return value in a C4Value */ \
|
||||
virtual C4Value Exec(C4AulContext *pContext, C4Value pPars[], bool fPassErrors=false) \
|
||||
virtual C4Value Exec(C4PropList * _this, C4Value pPars[], bool fPassErrors) \
|
||||
{ \
|
||||
if (!pContext->Obj) throw new NeedObjectContext(GetName()); \
|
||||
return C4ValueConv<RType>::ToC4V(pFunc(pContext->Obj LIST(N, CONV_FROM_C4V))); \
|
||||
C4Object * Obj; if (!_this || !(Obj = _this->GetObject())) throw new NeedObjectContext(GetName()); \
|
||||
return C4ValueConv<RType>::ToC4V(pFunc(Obj LIST(N, CONV_FROM_C4V))); \
|
||||
} \
|
||||
protected: \
|
||||
Func pFunc; \
|
||||
}; \
|
||||
template <typename RType LIST(N, TYPENAMES)> \
|
||||
inline void AddFunc(C4AulScript * pOwner, const char * Name, RType (*pFunc)(C4AulContext * LIST(N, PARS)), bool Public=true) \
|
||||
template <typename RType LIST(N, TYPENAMES)> \
|
||||
inline void AddFunc(C4AulScript * pOwner, const char * Name, RType (*pFunc)(C4PropList * LIST(N, PARS)), bool Public=true) \
|
||||
{ \
|
||||
new C4AulDefFunc##N<RType LIST(N, PARS)>(pOwner, Name, pFunc, Public); \
|
||||
} \
|
||||
|
@ -375,4 +354,31 @@ TEMPLATE(10)
|
|||
#undef CONV_FROM_C4V
|
||||
#undef TEMPLATE
|
||||
|
||||
|
||||
// a definition of a function exported to script
|
||||
struct C4ScriptFnDef
|
||||
{
|
||||
const char* Identifier; // the name of the func in the script
|
||||
bool Public;
|
||||
C4V_Type RetType; // type returned. ignored when C4V
|
||||
C4V_Type ParType[10];// type of the parameters. error when wrong parameter type.
|
||||
C4Value (*FunctionC4V)(C4PropList * _this, C4Value *);
|
||||
};
|
||||
|
||||
// defined function class
|
||||
class C4AulDefFunc : C4AulFunc
|
||||
{
|
||||
public:
|
||||
C4ScriptFnDef* Def;
|
||||
|
||||
C4AulDefFunc(C4AulScript *pOwner, C4ScriptFnDef* pDef);
|
||||
~C4AulDefFunc();
|
||||
|
||||
virtual bool GetPublic() { return !!Def->Public; }
|
||||
virtual C4V_Type* GetParType() { return Def->ParType; }
|
||||
virtual C4V_Type GetRetType() { return Def->RetType; }
|
||||
|
||||
virtual C4Value Exec(C4PropList * p, C4Value pPars[], bool fPassErrors=false);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -36,7 +36,7 @@
|
|||
|
||||
C4AulExec AulExec;
|
||||
|
||||
C4AulExecError::C4AulExecError(C4Object *pObj, const char *szError) : cObj(pObj)
|
||||
C4AulExecError::C4AulExecError(const char *szError)
|
||||
{
|
||||
// direct error message string
|
||||
sMessage.Format("ERROR: %s.", szError ? szError : "(no error message)");
|
||||
|
@ -46,6 +46,13 @@ StdStrBuf C4AulScriptContext::ReturnDump(StdStrBuf Dump)
|
|||
{
|
||||
if (!Func)
|
||||
return StdStrBuf("");
|
||||
// Context
|
||||
if (Obj && Obj->Status)
|
||||
{
|
||||
C4Value ObjVal(Obj);
|
||||
Dump.Append(ObjVal.GetDataString(0));
|
||||
Dump.Append("->");
|
||||
}
|
||||
bool fDirectExec = !Func->GetName();
|
||||
if (!fDirectExec)
|
||||
{
|
||||
|
@ -77,16 +84,6 @@ StdStrBuf C4AulScriptContext::ReturnDump(StdStrBuf Dump)
|
|||
}
|
||||
else
|
||||
Dump.Append(Func->Owner->ScriptName);
|
||||
// Context
|
||||
if (Obj)
|
||||
{
|
||||
if (Obj->Status == C4OS_NORMAL)
|
||||
Dump.AppendFormat(" (obj #%d)", Obj->Number);
|
||||
else
|
||||
Dump.AppendFormat(" (obj (#%d))", Obj->Number);
|
||||
}
|
||||
else if (Func->Owner->GetPropList())
|
||||
Dump.AppendFormat(" (def %s)", Func->Owner->GetPropList()->GetName());
|
||||
// Script
|
||||
if (!fDirectExec && Func->pOrgScript)
|
||||
Dump.AppendFormat(" (%s:%d)",
|
||||
|
@ -108,13 +105,13 @@ void C4AulExec::LogCallStack()
|
|||
pCtx->dump(StdStrBuf(" by: "));
|
||||
}
|
||||
|
||||
C4String *C4AulExec::FnTranslate(C4AulContext *ctx, C4String *text)
|
||||
C4String *C4AulExec::FnTranslate(C4PropList * _this, C4String *text)
|
||||
{
|
||||
if (!text || text->GetData().isNull()) return NULL;
|
||||
// Find correct script: translations of the context if possible, containing script as fallback
|
||||
C4AulScript *script = NULL;
|
||||
if (ctx->Def && ctx->Def->GetDef())
|
||||
script = &(ctx->Def->GetDef()->Script);
|
||||
if (_this && _this->GetDef())
|
||||
script = &(_this->GetDef()->Script);
|
||||
else
|
||||
script = AulExec.pCurCtx[-1].Func->pOrgScript;
|
||||
assert(script);
|
||||
|
@ -139,8 +136,6 @@ void C4AulExec::ClearPointers(C4Object * obj)
|
|||
{
|
||||
if (pCtx->Obj == obj)
|
||||
pCtx->Obj = NULL;
|
||||
if (pCtx->Def == obj)
|
||||
pCtx->Def = NULL;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
@ -160,8 +155,7 @@ C4Value C4AulExec::Exec(C4AulScriptFunc *pSFunc, C4PropList * p, C4Value *pnPars
|
|||
// Push a new context
|
||||
C4AulScriptContext ctx;
|
||||
ctx.tTime = 0;
|
||||
ctx.Obj = p ? p->GetObject() : NULL;
|
||||
ctx.Def = p;
|
||||
ctx.Obj = p;
|
||||
ctx.Return = NULL;
|
||||
ctx.Pars = pPars;
|
||||
ctx.Vars = pCurVal + 1;
|
||||
|
@ -236,10 +230,10 @@ C4Value C4AulExec::Exec(C4AulBCC *pCPos, bool fPassErrors)
|
|||
break;
|
||||
|
||||
case AB_EOF: case AB_EOFN:
|
||||
throw new C4AulExecError(pCurCtx->Obj, "internal error: function didn't return");
|
||||
throw new C4AulExecError("internal error: function didn't return");
|
||||
|
||||
case AB_ERR:
|
||||
throw new C4AulExecError(pCurCtx->Obj, "syntax error: see above for details");
|
||||
throw new C4AulExecError("syntax error: see above for details");
|
||||
|
||||
case AB_PARN_CONTEXT:
|
||||
PushValue(AulExec.GetContext(AulExec.GetContextDepth()-2)->Pars[pCPos->Par.i]);
|
||||
|
@ -250,24 +244,22 @@ C4Value C4AulExec::Exec(C4AulBCC *pCPos, bool fPassErrors)
|
|||
break;
|
||||
|
||||
case AB_LOCALN:
|
||||
assert(!pCurCtx->Obj || pCurCtx->Def == pCurCtx->Obj);
|
||||
if (!pCurCtx->Def)
|
||||
throw new C4AulExecError(0, "can't access local variables without this");
|
||||
if (!pCurCtx->Obj)
|
||||
throw new C4AulExecError("can't access local variables without this");
|
||||
PushNullVals(1);
|
||||
pCurCtx->Def->GetPropertyByS(pCPos->Par.s, pCurVal);
|
||||
pCurCtx->Obj->GetPropertyByS(pCPos->Par.s, pCurVal);
|
||||
break;
|
||||
case AB_LOCALN_SET:
|
||||
assert(!pCurCtx->Obj || pCurCtx->Def == pCurCtx->Obj);
|
||||
if (!pCurCtx->Def)
|
||||
throw new C4AulExecError(0, "can't access local variables without this");
|
||||
if (pCurCtx->Def->IsFrozen())
|
||||
throw new C4AulExecError(pCurCtx->Obj, "local variable: this is readonly");
|
||||
pCurCtx->Def->SetPropertyByS(pCPos->Par.s, pCurVal[0]);
|
||||
if (!pCurCtx->Obj)
|
||||
throw new C4AulExecError("can't access local variables without this");
|
||||
if (pCurCtx->Obj->IsFrozen())
|
||||
throw new C4AulExecError("local variable: this is readonly");
|
||||
pCurCtx->Obj->SetPropertyByS(pCPos->Par.s, pCurVal[0]);
|
||||
break;
|
||||
|
||||
case AB_PROP:
|
||||
if (!pCurVal->CheckConversion(C4V_PropList))
|
||||
throw new C4AulExecError(pCurCtx->Obj, FormatString("proplist access: proplist expected, got %s", pCurVal->GetTypeName()).getData());
|
||||
throw new C4AulExecError(FormatString("proplist access: proplist expected, got %s", pCurVal->GetTypeName()).getData());
|
||||
if (!pCurVal->_getPropList()->GetPropertyByS(pCPos->Par.s, pCurVal))
|
||||
pCurVal->Set0();
|
||||
break;
|
||||
|
@ -275,9 +267,9 @@ C4Value C4AulExec::Exec(C4AulBCC *pCPos, bool fPassErrors)
|
|||
{
|
||||
C4Value *pPropList = pCurVal - 1;
|
||||
if (!pPropList->CheckConversion(C4V_PropList))
|
||||
throw new C4AulExecError(pCurCtx->Obj, FormatString("proplist write: proplist expected, got %s", pPropList->GetTypeName()).getData());
|
||||
throw new C4AulExecError(FormatString("proplist write: proplist expected, got %s", pPropList->GetTypeName()).getData());
|
||||
if (pPropList->_getPropList()->IsFrozen())
|
||||
throw new C4AulExecError(pCurCtx->Obj, "proplist write: proplist is readonly");
|
||||
throw new C4AulExecError("proplist write: proplist is readonly");
|
||||
pPropList->_getPropList()->SetPropertyByS(pCPos->Par.s, pCurVal[0]);
|
||||
pPropList->Set(pCurVal[0]);
|
||||
PopValue();
|
||||
|
@ -325,7 +317,7 @@ C4Value C4AulExec::Exec(C4AulBCC *pCPos, bool fPassErrors)
|
|||
CheckOpPars(C4V_Int, C4V_Int, "/");
|
||||
C4Value *pPar1 = pCurVal - 1, *pPar2 = pCurVal;
|
||||
if (!pPar2->_getInt())
|
||||
throw new C4AulExecError(pCurCtx->Obj, "division by zero");
|
||||
throw new C4AulExecError("division by zero");
|
||||
pPar1->SetInt(pPar1->_getInt() / pPar2->_getInt());
|
||||
PopValue();
|
||||
break;
|
||||
|
@ -512,7 +504,7 @@ C4Value C4AulExec::Exec(C4AulBCC *pCPos, bool fPassErrors)
|
|||
assert(pStruct->GetType() == C4V_PropList);
|
||||
C4PropList *pPropList = pStruct->_getPropList();
|
||||
if (pPropList->IsFrozen())
|
||||
throw new C4AulExecError(pCurCtx->Obj, "proplist write: proplist is readonly");
|
||||
throw new C4AulExecError("proplist write: proplist is readonly");
|
||||
pPropList->SetPropertyByS(pIndex->_getStr(), *pValue);
|
||||
}
|
||||
// Set result, remove array and index from stack
|
||||
|
@ -528,11 +520,11 @@ C4Value C4AulExec::Exec(C4AulBCC *pCPos, bool fPassErrors)
|
|||
|
||||
// Typcheck
|
||||
if (!Array.CheckConversion(C4V_Array))
|
||||
throw new C4AulExecError(pCurCtx->Obj, FormatString("array slice: can't access %s as an array", Array.GetTypeName()).getData());
|
||||
throw new C4AulExecError(FormatString("array slice: can't access %s as an array", Array.GetTypeName()).getData());
|
||||
if (!StartIndex.CheckConversion(C4V_Int))
|
||||
throw new C4AulExecError(pCurCtx->Obj, FormatString("array slice: start index of type %s, int expected", StartIndex.GetTypeName()).getData());
|
||||
throw new C4AulExecError(FormatString("array slice: start index of type %s, int expected", StartIndex.GetTypeName()).getData());
|
||||
if (!EndIndex.CheckConversion(C4V_Int))
|
||||
throw new C4AulExecError(pCurCtx->Obj, FormatString("array slice: end index of type %s, int expected", EndIndex.GetTypeName()).getData());
|
||||
throw new C4AulExecError(FormatString("array slice: end index of type %s, int expected", EndIndex.GetTypeName()).getData());
|
||||
|
||||
Array.SetArray(Array.GetData().Array->GetSlice(StartIndex._getInt(), EndIndex._getInt()));
|
||||
|
||||
|
@ -550,11 +542,11 @@ C4Value C4AulExec::Exec(C4AulBCC *pCPos, bool fPassErrors)
|
|||
|
||||
// Typcheck
|
||||
if (!Array.CheckConversion(C4V_Array))
|
||||
throw new C4AulExecError(pCurCtx->Obj, FormatString("array slice: can't access %s as an array", Array.GetTypeName()).getData());
|
||||
throw new C4AulExecError(FormatString("array slice: can't access %s as an array", Array.GetTypeName()).getData());
|
||||
if (!StartIndex.CheckConversion(C4V_Int))
|
||||
throw new C4AulExecError(pCurCtx->Obj, FormatString("array slice: start index of type %s, int expected", StartIndex.GetTypeName()).getData());
|
||||
throw new C4AulExecError(FormatString("array slice: start index of type %s, int expected", StartIndex.GetTypeName()).getData());
|
||||
if (!EndIndex.CheckConversion(C4V_Int))
|
||||
throw new C4AulExecError(pCurCtx->Obj, FormatString("array slice: end index of type %s, int expected", EndIndex.GetTypeName()).getData());
|
||||
throw new C4AulExecError(FormatString("array slice: end index of type %s, int expected", EndIndex.GetTypeName()).getData());
|
||||
|
||||
C4ValueArray *pArray = Array._getArray();
|
||||
pArray->SetSlice(StartIndex._getInt(), EndIndex._getInt(), Value);
|
||||
|
@ -697,7 +689,7 @@ C4Value C4AulExec::Exec(C4AulBCC *pCPos, bool fPassErrors)
|
|||
|
||||
case AB_PAR:
|
||||
if (!pCurVal->CheckConversion(C4V_Int))
|
||||
throw new C4AulExecError(pCurCtx->Obj, FormatString("Par: index of type %s, int expected", pCurVal->GetTypeName()).getData());
|
||||
throw new C4AulExecError(FormatString("Par: index of type %s, int expected", pCurVal->GetTypeName()).getData());
|
||||
// Push reference to parameter on the stack
|
||||
if (pCurVal->_getInt() >= 0 && pCurVal->_getInt() < pCurCtx->Func->GetParCount())
|
||||
pCurVal->Set(pCurCtx->Pars[pCurVal->_getInt()]);
|
||||
|
@ -714,7 +706,7 @@ C4Value C4AulExec::Exec(C4AulBCC *pCPos, bool fPassErrors)
|
|||
if (!iItem)
|
||||
{
|
||||
if (!pCurVal[-1].CheckConversion(C4V_Array))
|
||||
throw new C4AulExecError(pCurCtx->Obj, FormatString("for: array expected, but got %s", pCurVal[-1].GetTypeName()).getData());
|
||||
throw new C4AulExecError(FormatString("for: array expected, but got %s", pCurVal[-1].GetTypeName()).getData());
|
||||
}
|
||||
C4ValueArray *pArray = pCurVal[-1]._getArray();
|
||||
// No more entries?
|
||||
|
@ -743,8 +735,7 @@ C4Value C4AulExec::Exec(C4AulBCC *pCPos, bool fPassErrors)
|
|||
pDest = pTargetVal->_getPropList();
|
||||
}
|
||||
else
|
||||
throw new C4AulExecError(pCurCtx->Obj,
|
||||
FormatString("'->': invalid target type %s, expected proplist", pTargetVal->GetTypeName()).getData());
|
||||
throw new C4AulExecError(FormatString("'->': invalid target type %s, expected proplist", pTargetVal->GetTypeName()).getData());
|
||||
|
||||
// Search function for given context
|
||||
C4AulFunc * pFunc = pDest->GetFunc(pCPos->Par.s);
|
||||
|
@ -757,10 +748,7 @@ C4Value C4AulExec::Exec(C4AulBCC *pCPos, bool fPassErrors)
|
|||
|
||||
// Function not found?
|
||||
if (!pFunc)
|
||||
throw new C4AulExecError(pCurCtx->Obj,
|
||||
FormatString("'->': no function \"%s\" in object \"%s\"", pCPos->Par.s->GetCStr(), pTargetVal->GetDataString().getData()).getData());
|
||||
|
||||
assert(!pFunc->OverloadedBy);
|
||||
throw new C4AulExecError(FormatString("'->': no function \"%s\" in object \"%s\"", pCPos->Par.s->GetCStr(), pTargetVal->GetDataString().getData()).getData());
|
||||
|
||||
// Save current position
|
||||
pCurCtx->CPos = pCPos;
|
||||
|
@ -832,15 +820,14 @@ C4AulBCC *C4AulExec::Call(C4AulFunc *pFunc, C4Value *pReturn, C4Value *pPars, C4
|
|||
if (!pContext)
|
||||
{
|
||||
assert(pCurCtx >= Contexts);
|
||||
pContext = pCurCtx->Def;
|
||||
pContext = pCurCtx->Obj;
|
||||
}
|
||||
|
||||
// Convert parameters (typecheck)
|
||||
C4V_Type *pTypes = pFunc->GetParType();
|
||||
for (int i = 0; i < pFunc->GetParCount(); i++)
|
||||
if (!pPars[i].CheckParConversion(pTypes[i]))
|
||||
throw new C4AulExecError(pCurCtx->Obj,
|
||||
FormatString("call to \"%s\" parameter %d: passed %s, but expected %s",
|
||||
throw new C4AulExecError(FormatString("call to \"%s\" parameter %d: passed %s, but expected %s",
|
||||
pFunc->GetName(), i + 1, pPars[i].GetTypeName(), GetC4VName(pTypes[i])
|
||||
).getData());
|
||||
|
||||
|
@ -850,10 +837,9 @@ C4AulBCC *C4AulExec::Call(C4AulFunc *pFunc, C4Value *pReturn, C4Value *pPars, C4
|
|||
{
|
||||
// Push a new context
|
||||
C4AulScriptContext ctx;
|
||||
ctx.Obj = pContext ? pContext->GetObject() : 0;
|
||||
ctx.Obj = pContext;
|
||||
if (ctx.Obj && !ctx.Obj->Status)
|
||||
throw new C4AulExecError(ctx.Obj, "using removed object");
|
||||
ctx.Def = pContext;
|
||||
throw new C4AulExecError("using removed object");
|
||||
ctx.Return = pReturn;
|
||||
ctx.Pars = pPars;
|
||||
ctx.Vars = pCurVal + 1;
|
||||
|
@ -873,13 +859,8 @@ C4AulBCC *C4AulExec::Call(C4AulFunc *pFunc, C4Value *pReturn, C4Value *pPars, C4
|
|||
}
|
||||
else
|
||||
{
|
||||
|
||||
// Create new context
|
||||
C4AulContext ctx;
|
||||
ctx.Obj = pContext ? pContext->GetObject() : 0;
|
||||
if (ctx.Obj && !ctx.Obj->Status)
|
||||
throw new C4AulExecError(ctx.Obj, "using removed object");
|
||||
ctx.Def = pContext;
|
||||
if (pContext && !pContext->Status)
|
||||
throw new C4AulExecError("using removed object");
|
||||
|
||||
#ifdef DEBUGREC_SCRIPT
|
||||
StdStrBuf sCallText;
|
||||
|
@ -916,9 +897,9 @@ C4AulBCC *C4AulExec::Call(C4AulFunc *pFunc, C4Value *pReturn, C4Value *pPars, C4
|
|||
C4AulScriptContext *pCtx = pCurCtx;
|
||||
#endif
|
||||
if (pReturn > pCurVal)
|
||||
PushValue(pFunc->Exec(&ctx, pPars, true));
|
||||
PushValue(pFunc->Exec(pContext, pPars, true));
|
||||
else
|
||||
pReturn->Set(pFunc->Exec(&ctx, pPars, true));
|
||||
pReturn->Set(pFunc->Exec(pContext, pPars, true));
|
||||
#ifdef _DEBUG
|
||||
assert(pCtx == pCurCtx);
|
||||
#endif
|
||||
|
@ -927,16 +908,6 @@ C4AulBCC *C4AulExec::Call(C4AulFunc *pFunc, C4Value *pReturn, C4Value *pPars, C4
|
|||
// Notify debugger
|
||||
if (C4AulDebug *pDebug = C4AulDebug::GetDebugger())
|
||||
{
|
||||
// Make dummy context
|
||||
C4AulScriptContext ctx;
|
||||
ctx.Obj = pContext ? pContext->GetObject() : 0;
|
||||
ctx.Def = pContext;
|
||||
ctx.Return = pReturn;
|
||||
ctx.Pars = pPars;
|
||||
ctx.Vars = pPars + pFunc->GetParCount();
|
||||
ctx.Func = pSFunc;
|
||||
ctx.TemporaryScript = false;
|
||||
ctx.CPos = NULL;
|
||||
pDebug->DebugStepOut(pCurCtx->CPos + 1, pCurCtx, pReturn);
|
||||
}
|
||||
#endif
|
||||
|
@ -991,7 +962,7 @@ void C4AulExec::StopProfiling()
|
|||
void C4AulExec::PushContext(const C4AulScriptContext &rContext)
|
||||
{
|
||||
if (pCurCtx >= Contexts + MAX_CONTEXT_STACK - 1)
|
||||
throw new C4AulExecError(pCurCtx->Obj, "context stack overflow");
|
||||
throw new C4AulExecError("context stack overflow");
|
||||
*++pCurCtx = rContext;
|
||||
// Trace?
|
||||
if (iTraceStart >= 0)
|
||||
|
@ -1007,7 +978,7 @@ void C4AulExec::PushContext(const C4AulScriptContext &rContext)
|
|||
void C4AulExec::PopContext()
|
||||
{
|
||||
if (pCurCtx < Contexts)
|
||||
throw new C4AulExecError(pCurCtx->Obj, "internal error: context stack underflow");
|
||||
throw new C4AulExecError("internal error: context stack underflow");
|
||||
// Profiler adding up times
|
||||
if (fProfiling)
|
||||
{
|
||||
|
@ -1071,57 +1042,15 @@ void C4AulProfiler::Show()
|
|||
// done!
|
||||
}
|
||||
|
||||
|
||||
C4Value C4AulFunc::Exec(C4PropList * p, C4AulParSet* pPars, bool fPassErrors)
|
||||
{
|
||||
// construct a dummy caller context
|
||||
C4AulContext ctx;
|
||||
ctx.Obj = p ? p->GetObject() : NULL;
|
||||
ctx.Def = p;
|
||||
// execute
|
||||
return Exec(&ctx, pPars ? pPars->Par : C4AulParSet().Par, fPassErrors);
|
||||
}
|
||||
|
||||
C4Value C4AulScriptFunc::Exec(C4AulContext *pCtx, C4Value pPars[], bool fPassErrors)
|
||||
C4Value C4AulScriptFunc::Exec(C4PropList * p, C4Value pPars[], bool fPassErrors)
|
||||
{
|
||||
// handle easiest case first
|
||||
if (Owner->State != ASS_PARSED) return C4VNull;
|
||||
if (Owner->State != ASS_PARSED) return C4Value();
|
||||
|
||||
// execute
|
||||
return AulExec.Exec(this, pCtx->Obj ? pCtx->Obj : pCtx->Def, pPars, fPassErrors);
|
||||
return AulExec.Exec(this, p, pPars, fPassErrors);
|
||||
}
|
||||
|
||||
|
||||
C4Value C4AulScriptFunc::Exec(C4PropList * p, C4AulParSet *pPars, bool fPassErrors)
|
||||
{
|
||||
// handle easiest case first
|
||||
if (Owner->State != ASS_PARSED) return C4VNull;
|
||||
|
||||
// execute
|
||||
return AulExec.Exec(this, p, pPars ? pPars->Par : C4AulParSet().Par, fPassErrors);
|
||||
}
|
||||
|
||||
|
||||
C4Value C4AulDefFunc::Exec(C4AulContext *pCallerCtx, C4Value pPars[], bool fPassErrors)
|
||||
{
|
||||
|
||||
// Choose function call format to use
|
||||
if (Def->FunctionC4V2 != 0)
|
||||
|
||||
// C4V function
|
||||
return Def->FunctionC4V2(pCallerCtx, pPars);
|
||||
|
||||
if (Def->FunctionC4V != 0)
|
||||
|
||||
// C4V function
|
||||
return Def->FunctionC4V(pCallerCtx, &pPars[0], &pPars[1], &pPars[2], &pPars[3], &pPars[4], &pPars[5], &pPars[6], &pPars[7], &pPars[8], &pPars[9]);
|
||||
|
||||
// should never happen...
|
||||
return C4VNull;
|
||||
|
||||
}
|
||||
|
||||
|
||||
class C4DirectExecScript: public C4ScriptHost
|
||||
{
|
||||
public:
|
||||
|
@ -1135,8 +1064,6 @@ public:
|
|||
p = pObj->Def;
|
||||
LocalNamed = pObj->Def->Script.LocalNamed;
|
||||
}
|
||||
// FIXME: calls from definitions
|
||||
ClearCode();
|
||||
this->stringTable = stringTable;
|
||||
}
|
||||
bool Delete() { return true; }
|
||||
|
@ -1186,8 +1113,8 @@ void C4AulScript::ResetProfilerTimes()
|
|||
{
|
||||
// zero all profiler times of owned functions
|
||||
C4AulScriptFunc *pSFunc;
|
||||
for (C4AulFunc *pFn = Func0; pFn; pFn = pFn->Next)
|
||||
if ((pSFunc = pFn->SFunc()))
|
||||
for (C4String *pFn = GetPropList()->EnumerateOwnFuncs(); pFn; pFn = GetPropList()->EnumerateOwnFuncs(pFn))
|
||||
if ((pSFunc = GetPropList()->GetFunc(pFn)->SFunc()))
|
||||
pSFunc->tProfileTime = 0;
|
||||
}
|
||||
|
||||
|
@ -1195,8 +1122,8 @@ void C4AulScript::CollectProfilerTimes(C4AulProfiler &rProfiler)
|
|||
{
|
||||
// collect all profiler times of owned functions
|
||||
C4AulScriptFunc *pSFunc;
|
||||
for (C4AulFunc *pFn = Func0; pFn; pFn = pFn->Next)
|
||||
if ((pSFunc = pFn->SFunc()))
|
||||
for (C4String *pFn = GetPropList()->EnumerateOwnFuncs(); pFn; pFn = GetPropList()->EnumerateOwnFuncs(pFn))
|
||||
if ((pSFunc = GetPropList()->GetFunc(pFn)->SFunc()))
|
||||
rProfiler.CollectEntry(pSFunc, pSFunc->tProfileTime);
|
||||
}
|
||||
|
||||
|
|
|
@ -70,7 +70,7 @@ public:
|
|||
int GetContextDepth() const { return pCurCtx - Contexts + 1; }
|
||||
C4AulScriptContext *GetContext(int iLevel) { return iLevel >= 0 && iLevel < GetContextDepth() ? Contexts + iLevel : NULL; }
|
||||
void LogCallStack();
|
||||
static C4String *FnTranslate(C4AulContext *ctx, C4String *text);
|
||||
static C4String *FnTranslate(C4PropList * _this, C4String *text);
|
||||
void ClearPointers(C4Object *);
|
||||
|
||||
private:
|
||||
|
@ -80,7 +80,7 @@ private:
|
|||
void CheckOverflow(int iCnt)
|
||||
{
|
||||
if (pCurVal - Values >= MAX_VALUE_STACK - iCnt)
|
||||
throw new C4AulExecError(pCurCtx->Obj, "value stack overflow, probably due to too deep recursion");
|
||||
throw new C4AulExecError("value stack overflow, probably due to too deep recursion");
|
||||
}
|
||||
|
||||
void PushInt(int32_t i)
|
||||
|
@ -176,20 +176,17 @@ private:
|
|||
|
||||
// Typecheck parameters
|
||||
if (!pPar1->CheckParConversion(Type1))
|
||||
throw new C4AulExecError(pCurCtx->Obj,
|
||||
FormatString("operator \"%s\" left side got %s, but expected %s",
|
||||
throw new C4AulExecError(FormatString("operator \"%s\" left side got %s, but expected %s",
|
||||
opname, pPar1->GetTypeName(), GetC4VName(Type1)).getData());
|
||||
if (!pPar2->CheckParConversion(Type2))
|
||||
throw new C4AulExecError(pCurCtx->Obj,
|
||||
FormatString("operator \"%s\" right side got %s, but expected %s",
|
||||
throw new C4AulExecError(FormatString("operator \"%s\" right side got %s, but expected %s",
|
||||
opname, pPar2->GetTypeName(), GetC4VName(Type2)).getData());
|
||||
}
|
||||
ALWAYS_INLINE void CheckOpPar(C4V_Type Type1, const char * opname)
|
||||
{
|
||||
// Typecheck parameter
|
||||
if (!pCurVal->CheckParConversion(Type1))
|
||||
throw new C4AulExecError(pCurCtx->Obj,
|
||||
FormatString("operator \"%s\": got %s, but expected %s",
|
||||
throw new C4AulExecError(FormatString("operator \"%s\": got %s, but expected %s",
|
||||
opname, pCurVal->GetTypeName(), GetC4VName(Type1)).getData());
|
||||
}
|
||||
|
||||
|
@ -198,17 +195,17 @@ private:
|
|||
if (pStructure->CheckConversion(C4V_Array))
|
||||
{
|
||||
if (!pIndex->CheckConversion(C4V_Int))
|
||||
throw new C4AulExecError(pCurCtx->Obj, FormatString("array access: index of type %s, but expected int", pIndex->GetTypeName()).getData());
|
||||
throw new C4AulExecError(FormatString("array access: index of type %s, but expected int", pIndex->GetTypeName()).getData());
|
||||
return C4V_Array;
|
||||
}
|
||||
else if (pStructure->CheckConversion(C4V_PropList))
|
||||
{
|
||||
if (!pIndex->CheckConversion(C4V_String))
|
||||
throw new C4AulExecError(pCurCtx->Obj, FormatString("proplist access: index of type %s, but expected string", pIndex->GetTypeName()).getData());
|
||||
throw new C4AulExecError(FormatString("proplist access: index of type %s, but expected string", pIndex->GetTypeName()).getData());
|
||||
return C4V_PropList;
|
||||
}
|
||||
else
|
||||
throw new C4AulExecError(pCurCtx->Obj, FormatString("can't access %s as array or proplist", pStructure->GetTypeName()).getData());
|
||||
throw new C4AulExecError(FormatString("can't access %s as array or proplist", pStructure->GetTypeName()).getData());
|
||||
}
|
||||
C4AulBCC *Call(C4AulFunc *pFunc, C4Value *pReturn, C4Value *pPars, C4PropList * pContext = NULL);
|
||||
};
|
||||
|
|
|
@ -0,0 +1,82 @@
|
|||
/*
|
||||
* OpenClonk, http://www.openclonk.org
|
||||
*
|
||||
* Copyright (c) 2001, 2007 Sven Eberhardt
|
||||
* Copyright (c) 2011-2012 Günther Brammer
|
||||
*
|
||||
* Portions might be copyrighted by other authors who have contributed
|
||||
* to OpenClonk.
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
* See isc_license.txt for full license and disclaimer.
|
||||
*
|
||||
* "Clonk" is a registered trademark of Matthes Bender.
|
||||
* See clonk_trademark_license.txt for full license.
|
||||
*/
|
||||
|
||||
#include <C4Include.h>
|
||||
#include <C4Value.h>
|
||||
#include <C4AulFunc.h>
|
||||
#include <C4Aul.h>
|
||||
#include <C4ScriptHost.h>
|
||||
|
||||
C4AulFunc::C4AulFunc(C4AulScript *pOwner, const char *pName):
|
||||
iRefCnt(0),
|
||||
Name(pName ? Strings.RegString(pName) : 0),
|
||||
MapNext(NULL)
|
||||
{
|
||||
Owner = pOwner;
|
||||
assert(GetName() || Owner->Temporary);
|
||||
// add to global lookuptable with this name
|
||||
if (GetName())
|
||||
Owner->Engine->FuncLookUp.Add(this);
|
||||
}
|
||||
|
||||
C4AulFunc::~C4AulFunc()
|
||||
{
|
||||
if (Owner)
|
||||
{
|
||||
C4AulScriptEngine * Engine = Owner->Engine;
|
||||
if (!Engine)
|
||||
Engine = &::ScriptEngine;
|
||||
if (GetName())
|
||||
Engine->FuncLookUp.Remove(this);
|
||||
if (Owner->GetPropList() && Name)
|
||||
{
|
||||
C4Value v;
|
||||
Owner->GetPropList()->GetPropertyByS(Name, &v);
|
||||
assert(v.getFunction() != this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
StdStrBuf C4AulFunc::GetFullName()
|
||||
{
|
||||
StdStrBuf r;
|
||||
// "lost" function?
|
||||
if (!Owner)
|
||||
{
|
||||
r.Ref("(unowned) ");
|
||||
}
|
||||
else if (Owner->GetPropList() && Owner->GetPropList()->IsStatic())
|
||||
{
|
||||
r.Take(Owner->GetPropList()->IsStatic()->GetDataString());
|
||||
r.AppendChar('.');
|
||||
}
|
||||
else if (Owner == &GameScript)
|
||||
{
|
||||
r.Ref("Scenario.");
|
||||
}
|
||||
else if (Owner->Engine == Owner)
|
||||
{
|
||||
r.Ref("Global.");
|
||||
}
|
||||
else
|
||||
{
|
||||
r.Ref("(unknown) ");
|
||||
}
|
||||
r.Append(Name->GetData());
|
||||
return r;
|
||||
}
|
|
@ -25,6 +25,26 @@
|
|||
|
||||
#define C4AUL_MAX_Par 10 // max number of parameters
|
||||
|
||||
struct C4AulParSet
|
||||
{
|
||||
C4Value Par[C4AUL_MAX_Par];
|
||||
|
||||
C4AulParSet() {} // standard-constructor
|
||||
C4AulParSet(const C4Value &par0, const C4Value &par1 = C4Value(), const C4Value &par2 = C4Value(), const C4Value &par3 = C4Value(), const C4Value &par4 = C4Value(),
|
||||
const C4Value &par5 = C4Value(), const C4Value &par6 = C4Value(), const C4Value &par7 = C4Value(), const C4Value &par8 = C4Value(), const C4Value &par9 = C4Value())
|
||||
{
|
||||
Par[0].Set(par0); Par[1].Set(par1); Par[2].Set(par2); Par[3].Set(par3); Par[4].Set(par4);
|
||||
Par[5].Set(par5); Par[6].Set(par6); Par[7].Set(par7); Par[8].Set(par8); Par[9].Set(par9);
|
||||
}
|
||||
C4AulParSet(const C4Value * Pars, int ParCount)
|
||||
{
|
||||
for (int i = 0; i < ParCount; ++i)
|
||||
Par[i].Set(Pars[i]);
|
||||
}
|
||||
C4Value & operator[](int iIdx) { return Par[iIdx]; }
|
||||
C4AulParSet * operator&() { return this; }
|
||||
};
|
||||
|
||||
// base function class
|
||||
class C4AulFunc
|
||||
{
|
||||
|
@ -50,25 +70,22 @@ public:
|
|||
|
||||
protected:
|
||||
C4RefCntPointer<C4String> Name; // function name
|
||||
C4AulFunc *Prev, *Next; // linked list members
|
||||
C4AulFunc *MapNext; // map member
|
||||
void AppendToScript(C4AulScript *);
|
||||
void RemoveFromScript();
|
||||
virtual ~C4AulFunc();
|
||||
|
||||
public:
|
||||
C4AulFunc *OverloadedBy; // function by which this one is overloaded
|
||||
|
||||
virtual C4AulScriptFunc *SFunc() { return NULL; } // type check func...
|
||||
|
||||
// Wether this function should be visible to players
|
||||
virtual bool GetPublic() { return false; }
|
||||
virtual int GetParCount() { return C4AUL_MAX_Par; }
|
||||
virtual C4V_Type* GetParType() { return 0; }
|
||||
virtual C4V_Type GetRetType() { return C4V_Any; }
|
||||
virtual C4Value Exec(C4AulContext *pCallerCtx, C4Value pPars[], bool fPassErrors=false) { return C4Value(); } // execute func (script call)
|
||||
virtual C4Value Exec(C4PropList * p = NULL, C4AulParSet *pPars = NULL, bool fPassErrors=false); // execute func (engine call)
|
||||
virtual void UnLink() { OverloadedBy = NULL; }
|
||||
virtual C4V_Type* GetParType() = 0;
|
||||
virtual C4V_Type GetRetType() = 0;
|
||||
C4Value Exec(C4PropList * p = NULL, C4AulParSet *pPars = NULL, bool fPassErrors=false)
|
||||
{
|
||||
return Exec(p, pPars->Par, fPassErrors);
|
||||
}
|
||||
virtual C4Value Exec(C4PropList * p, C4Value pPars[], bool fPassErrors=false) = 0;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -28,9 +28,19 @@
|
|||
#include <C4Game.h>
|
||||
#include <C4GameObjects.h>
|
||||
|
||||
bool C4AulScript::ResolveIncludes(C4DefList *rDefs)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
bool C4AulScript::ResolveAppends(C4DefList *rDefs)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
// ResolveAppends and ResolveIncludes must be called both
|
||||
// for each script. ResolveAppends has to be called first!
|
||||
bool C4AulScript::ResolveAppends(C4DefList *rDefs)
|
||||
bool C4ScriptHost::ResolveAppends(C4DefList *rDefs)
|
||||
{
|
||||
// resolve local appends
|
||||
if (State != ASS_PREPARSED) return false;
|
||||
|
@ -49,7 +59,7 @@ bool C4AulScript::ResolveAppends(C4DefList *rDefs)
|
|||
// save id in buffer because AulWarn will use the buffer of C4IdText
|
||||
// to get the id of the object in which the error occurs...
|
||||
// (stupid static buffers...)
|
||||
Warn("script to #appendto not found: ", a->ToString());
|
||||
Warn("#appendto %s not found", a->ToString());
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -69,7 +79,7 @@ bool C4AulScript::ResolveAppends(C4DefList *rDefs)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool C4AulScript::ResolveIncludes(C4DefList *rDefs)
|
||||
bool C4ScriptHost::ResolveIncludes(C4DefList *rDefs)
|
||||
{
|
||||
// Had been preparsed?
|
||||
if (State != ASS_PREPARSED) return false;
|
||||
|
@ -91,7 +101,7 @@ bool C4AulScript::ResolveIncludes(C4DefList *rDefs)
|
|||
if (Def)
|
||||
{
|
||||
// resolve #includes in included script first (#include-chains :( )
|
||||
if (!((C4AulScript &)Def->Script).IncludesResolved)
|
||||
if (!Def->Script.IncludesResolved)
|
||||
if (!Def->Script.ResolveIncludes(rDefs))
|
||||
continue; // skip this #include
|
||||
|
||||
|
@ -106,7 +116,7 @@ bool C4AulScript::ResolveIncludes(C4DefList *rDefs)
|
|||
// save id in buffer because AulWarn will use the buffer of C4IdText
|
||||
// to get the id of the object in which the error occurs...
|
||||
// (stupid static buffers...)
|
||||
Warn("script to #include not found: ", i->ToString());
|
||||
Warn("#include %s not found", i->ToString());
|
||||
}
|
||||
}
|
||||
IncludesResolved = true;
|
||||
|
@ -117,30 +127,20 @@ bool C4AulScript::ResolveIncludes(C4DefList *rDefs)
|
|||
}
|
||||
|
||||
void C4AulScript::UnLink()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void C4ScriptHost::UnLink()
|
||||
{
|
||||
// do not unlink temporary (e.g., DirectExec-script in ReloadDef)
|
||||
if (Temporary) return;
|
||||
|
||||
C4PropList * p = GetPropList();
|
||||
if (p) p->C4PropList::Thaw();
|
||||
|
||||
// delete included/appended functions
|
||||
C4AulFunc* pFunc = Func0;
|
||||
while (pFunc)
|
||||
if (p)
|
||||
{
|
||||
C4AulFunc* pNextFunc = pFunc->Next;
|
||||
|
||||
// clear stuff that's set in AfterLink
|
||||
pFunc->UnLink();
|
||||
|
||||
if (pFunc->SFunc())
|
||||
if (pFunc->Owner != pFunc->SFunc()->pOrgScript)
|
||||
{
|
||||
pFunc->RemoveFromScript();
|
||||
pFunc->DecRef();
|
||||
}
|
||||
|
||||
pFunc = pNextFunc;
|
||||
p->C4PropList::Clear();
|
||||
p->SetProperty(P_Prototype, C4VPropList(Engine->GetPropList()));
|
||||
}
|
||||
|
||||
// includes will have to be re-resolved now
|
||||
|
@ -149,11 +149,18 @@ void C4AulScript::UnLink()
|
|||
if (State > ASS_PREPARSED) State = ASS_PREPARSED;
|
||||
}
|
||||
|
||||
void C4AulScriptFunc::UnLink()
|
||||
void C4AulScriptEngine::UnLink()
|
||||
{
|
||||
OwnerOverloaded = NULL;
|
||||
|
||||
C4AulFunc::UnLink();
|
||||
// unlink scripts
|
||||
for (C4AulScript *s = Child0; s; s = s->Next)
|
||||
s->UnLink();
|
||||
GetPropList()->Thaw();
|
||||
if (State > ASS_PREPARSED) State = ASS_PREPARSED;
|
||||
// Do not clear global variables and constants, because they are registered by the
|
||||
// preparser or other parts. Note that keeping those fields means that you cannot delete a global
|
||||
// variable or constant at runtime by removing it from the script.
|
||||
//GlobalNamedNames.Reset();
|
||||
//GlobalConstNames.Reset();
|
||||
}
|
||||
|
||||
bool C4AulScript::ReloadScript(const char *szPath, const char *szLanguage)
|
||||
|
@ -174,9 +181,6 @@ void C4AulScriptEngine::Link(C4DefList *rDefs)
|
|||
for (C4AulScript *s = Child0; s; s = s->Next)
|
||||
s->ResolveIncludes(rDefs);
|
||||
|
||||
// put script functions into the proplist
|
||||
LinkFunctions();
|
||||
|
||||
// parse the scripts to byte code
|
||||
for (C4AulScript *s = Child0; s; s = s->Next)
|
||||
s->Parse();
|
||||
|
|
|
@ -128,7 +128,7 @@ class C4AulParse
|
|||
public:
|
||||
enum Type { PARSER, PREPARSER };
|
||||
C4AulParse(C4ScriptHost * a, enum Type Type):
|
||||
Fn(0), a(a), pOrgScript(a), SPos(a->Script.getData()),
|
||||
Fn(0), a(a), pOrgScript(a), SPos(a->Script.getData()), TokenSPos(SPos),
|
||||
TokenType(ATT_INVALID),
|
||||
Done(false),
|
||||
Type(Type),
|
||||
|
@ -141,6 +141,7 @@ public:
|
|||
{ while (pLoopStack) PopLoop(); ClearToken(); }
|
||||
C4AulScriptFunc *Fn; C4ScriptHost * a; C4ScriptHost * pOrgScript;
|
||||
const char *SPos; // current position in the script
|
||||
const char *TokenSPos; // start of the current token in the script
|
||||
char Idtf[C4AUL_MAX_Identifier]; // current identifier
|
||||
C4AulTokenType TokenType; // current token type
|
||||
int32_t cInt; // current int constant
|
||||
|
@ -166,8 +167,8 @@ public:
|
|||
void Parse_Local();
|
||||
void Parse_Static();
|
||||
void Parse_Const();
|
||||
C4Value Parse_ConstExpression(bool really);
|
||||
C4Value Parse_ConstPropList(bool really);
|
||||
C4Value Parse_ConstExpression(C4PropListStatic * parent, C4String * Name);
|
||||
C4Value Parse_ConstPropList(const C4PropListStatic * parent, C4String * Name);
|
||||
|
||||
bool AdvanceSpaces(); // skip whitespaces; return whether script ended
|
||||
int GetOperator(const char* pScript);
|
||||
|
@ -181,8 +182,8 @@ public:
|
|||
void UnexpectedToken(const char * Expected) NORETURN;
|
||||
static const char * GetTokenName(C4AulTokenType TokenType);
|
||||
|
||||
void Warn(const char *pMsg, const char *pIdtf=0);
|
||||
void Error(const char *pMsg, const char *pIdtf=0);
|
||||
void Warn(const char *pMsg, ...) GNUC_FORMAT_ATTRIBUTE_O;
|
||||
void Error(const char *pMsg, ...) GNUC_FORMAT_ATTRIBUTE_O;
|
||||
|
||||
private:
|
||||
|
||||
|
@ -221,28 +222,26 @@ private:
|
|||
void AddLoopControl(bool fBreak);
|
||||
};
|
||||
|
||||
void C4AulScript::Warn(const char *pMsg, const char *pIdtf)
|
||||
void C4AulScript::Warn(const char *pMsg, ...)
|
||||
{
|
||||
// display error
|
||||
va_list args; va_start(args, pMsg);
|
||||
StdStrBuf Buf;
|
||||
Buf.FormatV(pMsg, args);
|
||||
|
||||
C4AulParseError warning(this, pMsg, pIdtf, true);
|
||||
C4AulParseError warning(this, Buf.getData(), 0, true);
|
||||
// display it
|
||||
warning.show();
|
||||
// count warnings
|
||||
++::ScriptEngine.warnCnt;
|
||||
}
|
||||
|
||||
void C4AulParse::Warn(const char *pMsg, const char *pIdtf)
|
||||
void C4AulParse::Warn(const char *pMsg, ...)
|
||||
{
|
||||
// do not show errors for System.ocg scripts that appear to be pure #appendto scripts
|
||||
if (Fn && !Fn->Owner->GetPropList() && !Fn->Owner->Appends.empty()) return;
|
||||
// script doesn't own function -> skip
|
||||
// (exception: global functions)
|
||||
//if(pFunc) if(pFunc->pOrgScript != pScript && pScript != (C4AulScript *)&::ScriptEngine) return;
|
||||
// display error
|
||||
va_list args; va_start(args, pMsg);
|
||||
StdStrBuf Buf;
|
||||
Buf.FormatV(pMsg, args);
|
||||
|
||||
C4AulParseError warning(this, pMsg, pIdtf, true);
|
||||
// display it
|
||||
C4AulParseError warning(this, Buf.getData(), 0, true);
|
||||
warning.show();
|
||||
if (pOrgScript != a)
|
||||
DebugLogF(" (as #appendto/#include to %s)", a->ScriptName.getData());
|
||||
|
@ -250,9 +249,13 @@ void C4AulParse::Warn(const char *pMsg, const char *pIdtf)
|
|||
++::ScriptEngine.warnCnt;
|
||||
}
|
||||
|
||||
void C4AulParse::Error(const char *pMsg, const char *pIdtf)
|
||||
void C4AulParse::Error(const char *pMsg, ...)
|
||||
{
|
||||
throw new C4AulParseError(this, pMsg, pIdtf);
|
||||
va_list args; va_start(args, pMsg);
|
||||
StdStrBuf Buf;
|
||||
Buf.FormatV(pMsg, args);
|
||||
|
||||
throw new C4AulParseError(this, Buf.getData());
|
||||
}
|
||||
|
||||
C4AulParseError::C4AulParseError(C4AulParse * state, const char *pMsg, const char *pIdtf, bool Warn)
|
||||
|
@ -269,11 +272,11 @@ C4AulParseError::C4AulParseError(C4AulParse * state, const char *pMsg, const cha
|
|||
sMessage.AppendFormat(" (in %s", state->Fn->GetName());
|
||||
|
||||
// Exact position
|
||||
if (state->Fn->pOrgScript && state->SPos)
|
||||
if (state->Fn->pOrgScript && state->TokenSPos)
|
||||
sMessage.AppendFormat(", %s:%d:%d)",
|
||||
state->Fn->pOrgScript->ScriptName.getData(),
|
||||
SGetLine(state->Fn->pOrgScript->GetScript(), state->SPos),
|
||||
SLineGetCharacters(state->Fn->pOrgScript->GetScript(), state->SPos));
|
||||
SGetLine(state->Fn->pOrgScript->GetScript(), state->TokenSPos),
|
||||
SLineGetCharacters(state->Fn->pOrgScript->GetScript(), state->TokenSPos));
|
||||
else
|
||||
sMessage.AppendChar(')');
|
||||
}
|
||||
|
@ -282,8 +285,8 @@ C4AulParseError::C4AulParseError(C4AulParse * state, const char *pMsg, const cha
|
|||
// Script name
|
||||
sMessage.AppendFormat(" (%s:%d:%d)",
|
||||
state->pOrgScript->ScriptName.getData(),
|
||||
SGetLine(state->pOrgScript->GetScript(), state->SPos),
|
||||
SLineGetCharacters(state->pOrgScript->GetScript(), state->SPos));
|
||||
SGetLine(state->pOrgScript->GetScript(), state->TokenSPos),
|
||||
SLineGetCharacters(state->pOrgScript->GetScript(), state->TokenSPos));
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -457,7 +460,7 @@ C4AulTokenType C4AulParse::GetNextToken(OperatorPolicy Operator)
|
|||
// move to start of token
|
||||
if (!AdvanceSpaces()) return ATT_EOF;
|
||||
// store offset
|
||||
const char *SPos0 = SPos;
|
||||
TokenSPos = SPos;
|
||||
|
||||
// get char
|
||||
char C = *(SPos++);
|
||||
|
@ -476,7 +479,7 @@ C4AulTokenType C4AulParse::GetNextToken(OperatorPolicy Operator)
|
|||
}
|
||||
|
||||
Len = Min(Len, C4AUL_MAX_Identifier);
|
||||
SCopy(SPos0, Idtf, Len);
|
||||
SCopy(TokenSPos, Idtf, Len);
|
||||
return dir ? ATT_DIR : ATT_IDTF;
|
||||
}
|
||||
else if (C == '(') return ATT_BOPEN; // "("
|
||||
|
@ -495,7 +498,7 @@ C4AulTokenType C4AulParse::GetNextToken(OperatorPolicy Operator)
|
|||
else
|
||||
{
|
||||
// decimal
|
||||
cInt = StrToI32(SPos0, 10, &SPos);
|
||||
cInt = StrToI32(TokenSPos, 10, &SPos);
|
||||
return ATT_INT;
|
||||
}
|
||||
}
|
||||
|
@ -575,8 +578,7 @@ C4AulTokenType C4AulParse::GetNextToken(OperatorPolicy Operator)
|
|||
// just insert "\"
|
||||
strbuf.push_back('\\');
|
||||
// show warning
|
||||
char strEscape[2] = { *(SPos + 1), 0 };
|
||||
Warn("unknown escape: ", strEscape);
|
||||
Warn("unknown escape \"%c\"", *(SPos + 1));
|
||||
}
|
||||
}
|
||||
else if (C == 0 || C == 10 || C == 13) // line break / feed
|
||||
|
@ -730,11 +732,26 @@ void C4ScriptHost::ClearCode()
|
|||
// add one empty chunk to init CPos and for functions without code.
|
||||
// For example, leftovers from a previous version of a reloaded script
|
||||
AddBCC(AB_ERR);
|
||||
C4AulFunc * f = Func0;
|
||||
while (f)
|
||||
if (Engine) for (C4String *pFn = Engine->GetPropList()->EnumerateOwnFuncs(); pFn; pFn = Engine->GetPropList()->EnumerateOwnFuncs(pFn))
|
||||
{
|
||||
f->SFunc()->CodePos = 0;
|
||||
f = f->Next;
|
||||
C4AulScriptFunc *pSFunc = Engine->GetPropList()->GetFunc(pFn)->SFunc();
|
||||
while (pSFunc)
|
||||
{
|
||||
if (pSFunc->pOrgScript == this)
|
||||
pSFunc->CodePos = 0;
|
||||
pSFunc = pSFunc->OwnerOverloaded ? pSFunc->OwnerOverloaded->SFunc() : 0;
|
||||
}
|
||||
}
|
||||
if (!GetPropList()) return;
|
||||
for (C4String *pFn = GetPropList()->EnumerateOwnFuncs(); pFn; pFn = GetPropList()->EnumerateOwnFuncs(pFn))
|
||||
{
|
||||
C4AulScriptFunc *pSFunc = GetPropList()->GetFunc(pFn)->SFunc();
|
||||
while (pSFunc)
|
||||
{
|
||||
assert(pSFunc->Owner == this);
|
||||
pSFunc->CodePos = 0;
|
||||
pSFunc = pSFunc->OwnerOverloaded ? pSFunc->OwnerOverloaded->SFunc() : 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -768,11 +785,9 @@ bool C4ScriptHost::Preparse()
|
|||
// clear stuff
|
||||
Includes.clear(); Appends.clear();
|
||||
|
||||
if (GetPropList())
|
||||
{
|
||||
GetPropList()->C4PropList::Clear();
|
||||
GetPropList()->SetProperty(P_Prototype, C4VPropList(Engine->GetPropList()));
|
||||
}
|
||||
GetPropList()->C4PropList::Clear();
|
||||
GetPropList()->SetProperty(P_Prototype, C4VPropList(Engine->GetPropList()));
|
||||
LocalValues.Clear();
|
||||
|
||||
// reset code
|
||||
ClearCode();
|
||||
|
@ -783,6 +798,9 @@ bool C4ScriptHost::Preparse()
|
|||
// #include will have to be resolved now...
|
||||
IncludesResolved = false;
|
||||
|
||||
// Parse will write the properties back after the ones from included scripts
|
||||
GetPropList()->Properties.Swap(&LocalValues);
|
||||
|
||||
// return success
|
||||
C4AulScript::State = ASS_PREPARSED;
|
||||
return true;
|
||||
|
@ -971,7 +989,7 @@ int C4AulParse::AddBCC(C4AulBCCType eType, intptr_t X)
|
|||
}
|
||||
|
||||
// Add
|
||||
a->AddBCC(eType, X, SPos);
|
||||
a->AddBCC(eType, X, TokenSPos);
|
||||
|
||||
// Reset jump flag
|
||||
fJump = false;
|
||||
|
@ -1006,7 +1024,7 @@ C4V_Type C4AulParse::GetLastRetType(C4V_Type to)
|
|||
case AB_CALL: case AB_CALLFS:
|
||||
{
|
||||
C4String * pName = a->GetLastCode()->Par.s;
|
||||
C4AulFunc * pFunc2 = a->Engine->GetFirstFunc(pName->GetCStr());
|
||||
C4AulFunc * pFunc2 = a->Engine->GetFirstFunc(pName);
|
||||
bool allwarn = true;
|
||||
from = C4V_Any;
|
||||
while (pFunc2 && allwarn)
|
||||
|
@ -1213,7 +1231,8 @@ void C4AulScriptFunc::ParseFn(C4AulScriptContext* context)
|
|||
state.Shift();
|
||||
state.Fn = this;
|
||||
state.Parse_Expression();
|
||||
GetCodeOwner()->AddBCC(AB_RETURN, 0, state.SPos);
|
||||
state.Match(ATT_EOF);
|
||||
GetCodeOwner()->AddBCC(AB_RETURN, 0, state.TokenSPos);
|
||||
}
|
||||
|
||||
void C4AulParse::Parse_Script()
|
||||
|
@ -1377,7 +1396,7 @@ void C4AulParse::Parse_Function()
|
|||
if (a->Engine->GlobalNamedNames.GetItemNr(Idtf) != -1)
|
||||
throw new C4AulParseError(this, "function definition: name already in use (global variable)");
|
||||
if (a->Engine->GlobalConstNames.GetItemNr(Idtf) != -1)
|
||||
Error("function definition: name already in use (global constant)", 0);
|
||||
Error("function definition: name already in use (global constant)");
|
||||
}
|
||||
// get script fn
|
||||
C4AulScript * owner;
|
||||
|
@ -1386,22 +1405,24 @@ void C4AulParse::Parse_Function()
|
|||
else
|
||||
owner = a;
|
||||
Fn = 0;
|
||||
C4AulFunc * f = owner->Func0;
|
||||
C4AulFunc * f = owner->GetPropList()->GetFunc(Idtf);
|
||||
while (f)
|
||||
{
|
||||
if (SEqual(f->GetName(), Idtf) && f->SFunc() && f->SFunc()->pOrgScript == pOrgScript)
|
||||
if (f->SFunc() && f->SFunc()->pOrgScript == pOrgScript && f->Owner == owner)
|
||||
{
|
||||
if (Fn)
|
||||
//throw new C4AulParseError(this, "Duplicate function ", Idtf);
|
||||
Warn("Duplicate function ", Idtf);
|
||||
Warn("Duplicate function %s", Idtf);
|
||||
Fn = f->SFunc();
|
||||
}
|
||||
f = f->Next;
|
||||
f = f->SFunc() ? f->SFunc()->OwnerOverloaded : 0;
|
||||
}
|
||||
// first preparser run or a new func in a reloaded script
|
||||
if (!Fn && Type == PREPARSER)
|
||||
{
|
||||
Fn = new C4AulScriptFunc(owner, pOrgScript, Idtf, SPos);
|
||||
Fn->SetOverloaded(owner->GetPropList()->GetFunc(Fn->Name));
|
||||
owner->GetPropList()->SetPropertyByS(Fn->Name, C4VFunction(Fn));
|
||||
}
|
||||
assert(Fn);
|
||||
if (Type == PARSER)
|
||||
|
@ -1489,6 +1510,52 @@ void C4AulParse::Parse_Function()
|
|||
}
|
||||
// add separator
|
||||
AddBCC(AB_EOFN);
|
||||
|
||||
// dump bytecode
|
||||
if (DEBUG_BYTECODE_DUMP && Type == PARSER)
|
||||
{
|
||||
fprintf(stderr, "%s:\n", Fn->GetName());
|
||||
std::map<C4AulBCC *, int> labels;
|
||||
int labeln = 0;
|
||||
for (C4AulBCC *pBCC = Fn->GetCode(); pBCC->bccType != AB_EOFN; pBCC++)
|
||||
{
|
||||
switch (pBCC->bccType)
|
||||
{
|
||||
case AB_JUMP: case AB_JUMPAND: case AB_JUMPOR: case AB_JUMPNNIL: case AB_CONDN: case AB_COND:
|
||||
labels[pBCC + pBCC->Par.i] = ++labeln; break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
for (C4AulBCC *pBCC = Fn->GetCode();; pBCC++)
|
||||
{
|
||||
C4AulBCCType eType = pBCC->bccType;
|
||||
if (labels.find(pBCC) != labels.end())
|
||||
fprintf(stderr, "%d:\n", labels[pBCC]);
|
||||
fprintf(stderr, "\t%d\t%s", Fn->GetLineOfCode(pBCC), GetTTName(eType));
|
||||
switch (eType)
|
||||
{
|
||||
case AB_FUNC:
|
||||
fprintf(stderr, "\t%s\n", pBCC->Par.f->GetName()); break;
|
||||
case AB_CALL: case AB_CALLFS: case AB_LOCALN: case AB_LOCALN_SET: case AB_PROP: case AB_PROP_SET:
|
||||
fprintf(stderr, "\t%s\n", pBCC->Par.s->GetCStr()); break;
|
||||
case AB_STRING:
|
||||
fprintf(stderr, "\t\"%s\"\n", pBCC->Par.s->GetCStr()); break;
|
||||
case AB_DEBUG: case AB_NIL: case AB_RETURN:
|
||||
case AB_PAR:
|
||||
case AB_ARRAYA: case AB_ARRAYA_SET: case AB_ARRAY_SLICE: case AB_ARRAY_SLICE_SET:
|
||||
case AB_ERR: case AB_EOFN: case AB_EOF:
|
||||
assert(!pBCC->Par.X); fprintf(stderr, "\n"); break;
|
||||
case AB_CARRAY: case AB_CPROPLIST:
|
||||
fprintf(stderr, "\t%p\n", reinterpret_cast<void *>(pBCC->Par.X)); break;
|
||||
case AB_JUMP: case AB_JUMPAND: case AB_JUMPOR: case AB_JUMPNNIL: case AB_CONDN: case AB_COND:
|
||||
fprintf(stderr, "\t%d\n", labels[pBCC + pBCC->Par.i]); break;
|
||||
default:
|
||||
fprintf(stderr, "\t%d\n", pBCC->Par.i); break;
|
||||
}
|
||||
if (eType == AB_EOFN) break;
|
||||
}
|
||||
}
|
||||
|
||||
// Do not blame this function for script errors between functions
|
||||
Fn = 0;
|
||||
Shift();
|
||||
|
@ -1757,7 +1824,7 @@ int C4AulParse::Parse_Params(int iMaxCnt, const char * sWarn, C4AulFunc * pFunc)
|
|||
// too many parameters?
|
||||
if (sWarn && size > iMaxCnt && Type == PARSER)
|
||||
Warn(FormatString("call to %s gives %d parameters, but only %d are used", sWarn, size, iMaxCnt).getData(), NULL);
|
||||
// Balance stack
|
||||
// Balance stack// FIXME: not for CALL/FUNC
|
||||
if (size != iMaxCnt)
|
||||
AddBCC(AB_STACK, iMaxCnt - size);
|
||||
return size;
|
||||
|
@ -1867,19 +1934,50 @@ void C4AulParse::Parse_PropList()
|
|||
Shift();
|
||||
}
|
||||
|
||||
C4Value C4AulParse::Parse_ConstPropList(bool really)
|
||||
C4Value C4AulParse::Parse_ConstPropList(const C4PropListStatic * parent, C4String * Name)
|
||||
{
|
||||
C4Value r;
|
||||
if (!Name)
|
||||
throw new C4AulParseError(this, "a static proplist is not allowed to be anonymous");
|
||||
C4PropListStatic * p;
|
||||
if (Type == PREPARSER)
|
||||
{
|
||||
p = C4PropList::NewAnon(NULL, parent, Name);
|
||||
}
|
||||
else
|
||||
{
|
||||
C4Value v;
|
||||
bool r;
|
||||
if (parent)
|
||||
r = parent->GetPropertyByS(Name, &v);
|
||||
else
|
||||
r = a->Engine->GetGlobalConstant(Name->GetCStr(), &v);
|
||||
if (!r || !v.getPropList())
|
||||
{
|
||||
// the proplist couldn't be parsed or was overwritten by a later constant.
|
||||
// create a temporary replacement
|
||||
v.SetPropList(C4PropList::NewAnon(NULL, parent, Name));
|
||||
}
|
||||
p = v.getPropList()->IsStatic();
|
||||
if (!p)
|
||||
throw new C4AulParseError(this, "internal error: constant proplist is not static");
|
||||
if (p->GetParent() != parent || p->GetParentKeyName() != Name)
|
||||
{
|
||||
// the proplist is from another definition, so don't change it
|
||||
// create a replacement for this defnition
|
||||
// FIXME: shouldn't the copy be made in parse, like functions are handled?
|
||||
v.SetPropList(C4PropList::NewAnon(NULL, parent, Name));
|
||||
p = v.getPropList()->IsStatic();
|
||||
}
|
||||
// In case of script reloads
|
||||
p->Thaw();
|
||||
}
|
||||
Shift();
|
||||
if (really)
|
||||
r.SetPropList(C4PropList::NewAnon());
|
||||
while (TokenType != ATT_BLCLOSE)
|
||||
{
|
||||
C4String * pKey;
|
||||
if (TokenType == ATT_IDTF)
|
||||
{
|
||||
if (really)
|
||||
pKey = Strings.RegString(Idtf);
|
||||
pKey = Strings.RegString(Idtf);
|
||||
Shift();
|
||||
}
|
||||
else if (TokenType == ATT_STRING)
|
||||
|
@ -1891,18 +1989,15 @@ C4Value C4AulParse::Parse_ConstPropList(bool really)
|
|||
if (TokenType != ATT_COLON && TokenType != ATT_SET)
|
||||
UnexpectedToken("':' or '='");
|
||||
Shift();
|
||||
if (really)
|
||||
r._getPropList()->SetPropertyByS(pKey, Parse_ConstExpression(really));
|
||||
else
|
||||
Parse_ConstExpression(really);
|
||||
Parse_ConstExpression(p, pKey);
|
||||
if (TokenType == ATT_COMMA)
|
||||
Shift();
|
||||
else if (TokenType != ATT_BLCLOSE)
|
||||
UnexpectedToken("'}' or ','");
|
||||
}
|
||||
if (really)
|
||||
r._getPropList()->Freeze();
|
||||
return r;
|
||||
if (Type == PARSER)
|
||||
p->Freeze();
|
||||
return C4VPropList(p);
|
||||
}
|
||||
|
||||
void C4AulParse::Parse_DoWhile()
|
||||
|
@ -2195,7 +2290,7 @@ void C4AulParse::Parse_Expression(int iParentPrio)
|
|||
throw new C4AulParseError(this, "'for' may not be used as a parameter");
|
||||
else if (SEqual(Idtf, C4AUL_Return))
|
||||
{
|
||||
Error("return may not be used as a parameter", 0);
|
||||
Error("return may not be used as a parameter");
|
||||
}
|
||||
else if (SEqual(Idtf, C4AUL_Par))
|
||||
{
|
||||
|
@ -2203,7 +2298,7 @@ void C4AulParse::Parse_Expression(int iParentPrio)
|
|||
Fn->ParCount = C4AUL_MAX_Par;
|
||||
// and for Par
|
||||
Shift();
|
||||
Parse_Params(1, C4AUL_Par);
|
||||
Parse_Params(1, C4AUL_Par);//FIXME: don't use Parse_Params
|
||||
AddBCC(AB_PAR);
|
||||
}
|
||||
else if (SEqual(Idtf, C4AUL_Inherited) || SEqual(Idtf, C4AUL_SafeInherited))
|
||||
|
@ -2250,7 +2345,7 @@ void C4AulParse::Parse_Expression(int iParentPrio)
|
|||
else if (FoundFn)
|
||||
{
|
||||
if (Config.Developer.ExtraWarnings && !FoundFn->GetPublic())
|
||||
Warn("using deprecated function ", Idtf);
|
||||
Warn("using deprecated function %s", Idtf);
|
||||
Shift();
|
||||
// Function parameters for all functions except "this", which can be used without
|
||||
if (!SEqual(FoundFn->GetName(), C4AUL_this) || TokenType == ATT_BOPEN)
|
||||
|
@ -2534,9 +2629,11 @@ void C4AulParse::Parse_Expression2(int iParentPrio)
|
|||
Shift();
|
||||
// expect identifier of called function now
|
||||
if (TokenType != ATT_IDTF) throw new C4AulParseError(this, "expecting func name after '->'");
|
||||
pFunc = a->Engine->GetFirstFunc(Idtf);
|
||||
if (Type == PARSER)
|
||||
{
|
||||
pName = ::Strings.RegString(Idtf);
|
||||
pFunc = a->Engine->GetFirstFunc(pName);
|
||||
}
|
||||
Shift();
|
||||
Parse_Params(C4AUL_MAX_Par, pName ? pName->GetCStr() : Idtf, pFunc);
|
||||
AddBCC(eCallType, reinterpret_cast<intptr_t>(pName));
|
||||
|
@ -2611,11 +2708,9 @@ void C4AulParse::Parse_Local()
|
|||
if (!a->GetPropList())
|
||||
throw new C4AulParseError(this, "local variables can only be initialized on proplists");
|
||||
Shift();
|
||||
// register as constant
|
||||
if (Type == PARSER)
|
||||
a->GetPropList()->SetPropertyByS(Strings.RegString(Name), Parse_ConstExpression(true));
|
||||
else
|
||||
Parse_ConstExpression(false);
|
||||
C4RefCntPointer<C4String> key = ::Strings.RegString(Name);
|
||||
assert(a->GetPropList()->IsStatic());
|
||||
Parse_ConstExpression(a->GetPropList()->IsStatic(), key);
|
||||
}
|
||||
switch (TokenType)
|
||||
{
|
||||
|
@ -2654,8 +2749,8 @@ void C4AulParse::Parse_Static()
|
|||
UnexpectedToken("variable name");
|
||||
// global variable definition
|
||||
// check: symbol already in use?
|
||||
if (a->Engine->GetPropList()->GetFunc(Idtf)) Error("function and variable with name ", Idtf);
|
||||
if (a->Engine->GetGlobalConstant(Idtf, NULL)) Error("constant and variable with name ", Idtf);
|
||||
if (a->Engine->GetPropList()->GetFunc(Idtf)) Error("function and variable with name %s", Idtf);
|
||||
if (a->Engine->GetGlobalConstant(Idtf, NULL)) Error("constant and variable with name %s", Idtf);
|
||||
// insert variable if not defined already
|
||||
if (a->Engine->GlobalNamedNames.GetItemNr(Idtf) == -1)
|
||||
{
|
||||
|
@ -2682,7 +2777,7 @@ void C4AulParse::Parse_Static()
|
|||
}
|
||||
}
|
||||
|
||||
C4Value C4AulParse::Parse_ConstExpression(bool really)
|
||||
C4Value C4AulParse::Parse_ConstExpression(C4PropListStatic * parent, C4String * Name)
|
||||
{
|
||||
C4Value r;
|
||||
switch (TokenType)
|
||||
|
@ -2698,15 +2793,18 @@ C4Value C4AulParse::Parse_ConstExpression(bool really)
|
|||
else if (SEqual(Idtf, C4AUL_Nil))
|
||||
r.Set0();
|
||||
else if (SEqual(Idtf, C4AUL_New))
|
||||
r = Parse_ConstPropList(really);
|
||||
r = Parse_ConstPropList(parent, Name);
|
||||
else if (a->LocalNamed.GetItemNr(Idtf) != -1)
|
||||
a->GetPropList()->GetPropertyByS(::Strings.FindString(Idtf), &r);
|
||||
else if (!a->Engine->GetGlobalConstant(Idtf, &r))
|
||||
UnexpectedToken("constant value");
|
||||
if (Type == PARSER)
|
||||
UnexpectedToken("constant value");
|
||||
break;
|
||||
case ATT_BOPEN2:
|
||||
{
|
||||
Shift();
|
||||
// Create an array
|
||||
if (really)
|
||||
if (Type == PARSER)
|
||||
r.SetArray(new C4ValueArray());
|
||||
int size = 0;
|
||||
bool fDone = false;
|
||||
|
@ -2718,7 +2816,7 @@ C4Value C4AulParse::Parse_ConstExpression(bool really)
|
|||
// [] -> size 0, [*,] -> size 2, [*,*,] -> size 3
|
||||
if (size > 0)
|
||||
{
|
||||
if (really)
|
||||
if (Type == PARSER)
|
||||
r._getArray()->SetItem(size, C4VNull);
|
||||
++size;
|
||||
}
|
||||
|
@ -2728,7 +2826,7 @@ C4Value C4AulParse::Parse_ConstExpression(bool really)
|
|||
case ATT_COMMA:
|
||||
{
|
||||
// got no parameter before a ","? then push nil
|
||||
if (really)
|
||||
if (Type == PARSER)
|
||||
r._getArray()->SetItem(size, C4VNull);
|
||||
Shift();
|
||||
++size;
|
||||
|
@ -2736,10 +2834,10 @@ C4Value C4AulParse::Parse_ConstExpression(bool really)
|
|||
}
|
||||
default:
|
||||
{
|
||||
if (really)
|
||||
r._getArray()->SetItem(size, Parse_ConstExpression(really));
|
||||
if (Type == PARSER)
|
||||
r._getArray()->SetItem(size, Parse_ConstExpression(NULL, NULL));
|
||||
else
|
||||
Parse_ConstExpression(really);
|
||||
Parse_ConstExpression(NULL, NULL);
|
||||
++size;
|
||||
if (TokenType == ATT_COMMA)
|
||||
Shift();
|
||||
|
@ -2757,7 +2855,7 @@ C4Value C4AulParse::Parse_ConstExpression(bool really)
|
|||
}
|
||||
case ATT_BLOPEN:
|
||||
{
|
||||
r = Parse_ConstPropList(really);
|
||||
r = Parse_ConstPropList(parent, Name);
|
||||
break;
|
||||
}
|
||||
case ATT_OPERATOR:
|
||||
|
@ -2794,10 +2892,18 @@ C4Value C4AulParse::Parse_ConstExpression(bool really)
|
|||
if (C4ScriptOpMap[OpID].Code == AB_BitOr)
|
||||
{
|
||||
Shift();
|
||||
C4Value r2 = Parse_ConstExpression(really);
|
||||
C4Value r2 = Parse_ConstExpression(NULL, NULL);
|
||||
r.SetInt(r.getInt() | r2.getInt());
|
||||
}
|
||||
}
|
||||
// store as constant or property
|
||||
if (Name)
|
||||
{
|
||||
if (parent)
|
||||
parent->SetPropertyByS(Name, r);
|
||||
else
|
||||
a->Engine->RegisterGlobalConstant(Name->GetCStr(), r);
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
|
@ -2814,9 +2920,9 @@ void C4AulParse::Parse_Const()
|
|||
SCopy(Idtf, Name);
|
||||
// check func lists - functions of same name are not allowed
|
||||
if (a->Engine->GetPropList()->GetFunc(Idtf))
|
||||
Error("definition of constant hidden by function ", Idtf);
|
||||
Error("definition of constant hidden by function %s", Idtf);
|
||||
if (a->Engine->GlobalNamedNames.GetItemNr(Idtf) != -1)
|
||||
Error("constant and variable with name ", Idtf);
|
||||
Error("constant and variable with name %s", Idtf);
|
||||
Match(ATT_IDTF);
|
||||
// expect '='
|
||||
if (TokenType != ATT_SET)
|
||||
|
@ -2828,11 +2934,8 @@ void C4AulParse::Parse_Const()
|
|||
// So allow only simple constants for now.
|
||||
Shift();
|
||||
|
||||
// register as constant
|
||||
if (Type == PREPARSER)
|
||||
a->Engine->RegisterGlobalConstant(Name, Parse_ConstExpression(true));
|
||||
else
|
||||
Parse_ConstExpression(false);
|
||||
C4RefCntPointer<C4String> key = ::Strings.RegString(Name);
|
||||
Parse_ConstExpression(NULL, key);
|
||||
|
||||
switch (TokenType)
|
||||
{
|
||||
|
@ -2858,25 +2961,8 @@ bool C4AulScript::Parse()
|
|||
return true;
|
||||
}
|
||||
|
||||
void C4AulScript::LinkFunctions()
|
||||
{
|
||||
for (C4AulFunc *f = Func0; f; f = f->Next)
|
||||
{
|
||||
C4AulScriptFunc *sf = f->SFunc();
|
||||
if (!sf) continue;
|
||||
sf->OwnerOverloaded = GetPropList()->GetFunc(sf->Name);
|
||||
if (sf->OwnerOverloaded && sf->OwnerOverloaded->Owner == this)
|
||||
sf->OwnerOverloaded->OverloadedBy = sf;
|
||||
GetPropList()->SetPropertyByS(sf->Name, C4VFunction(sf));
|
||||
}
|
||||
}
|
||||
|
||||
bool C4ScriptHost::Parse()
|
||||
{
|
||||
if (DEBUG_BYTECODE_DUMP)
|
||||
{
|
||||
fprintf(stderr, "parsing %s...\n", ScriptName.getData());
|
||||
}
|
||||
// check state
|
||||
if (State != ASS_LINKED) return false;
|
||||
|
||||
|
@ -2890,120 +2976,63 @@ bool C4ScriptHost::Parse()
|
|||
return true;
|
||||
}
|
||||
|
||||
C4AulFunc * thisfuncs = Func0;
|
||||
for (C4AulFunc *f = thisfuncs; f; f = f->Next)
|
||||
if (f->GetName() && f->SFunc())
|
||||
{
|
||||
Engine->FuncLookUp.Remove(f);
|
||||
}
|
||||
Func0 = FuncL = 0;
|
||||
C4PropList * p = GetPropList();
|
||||
|
||||
for (std::list<C4ScriptHost *>::iterator s = SourceScripts.begin(); s != SourceScripts.end(); ++s)
|
||||
{
|
||||
if (*s == this)
|
||||
// append all funcs and local variable initializations
|
||||
const C4Property * prop = (*s)->LocalValues.First();
|
||||
while (prop)
|
||||
{
|
||||
C4AulFunc *f = thisfuncs, *n;
|
||||
while (f)
|
||||
switch(prop->Value.GetType())
|
||||
{
|
||||
n = f->Next;
|
||||
f->AppendToScript(this);
|
||||
f = n;
|
||||
case C4V_Function:
|
||||
{
|
||||
C4AulScriptFunc * sf = prop->Value.getFunction()->SFunc();
|
||||
assert(sf->pOrgScript == *s);
|
||||
C4AulScriptFunc *sfc;
|
||||
if (sf->pOrgScript != this)
|
||||
sfc = new C4AulScriptFunc(this, *sf);
|
||||
else
|
||||
sfc = sf;
|
||||
sfc->SetOverloaded(p->GetFunc(sf->Name));
|
||||
p->SetPropertyByS(prop->Key, C4VFunction(sfc));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
p->SetPropertyByS(prop->Key, prop->Value);
|
||||
}
|
||||
continue;
|
||||
prop = (*s)->LocalValues.Next(prop);
|
||||
}
|
||||
if (*s == this)
|
||||
continue;
|
||||
// definition appends
|
||||
if (GetPropList() && GetPropList()->GetDef() && (*s)->GetPropList() && (*s)->GetPropList()->GetDef())
|
||||
GetPropList()->GetDef()->IncludeDefinition((*s)->GetPropList()->GetDef());
|
||||
// append all funcs
|
||||
C4AulScriptFunc *sf;
|
||||
for (C4AulFunc *f = (*s)->Func0; f; f = f->Next)
|
||||
// funcs from other scripts get appended directly from their script
|
||||
if ((sf = f->SFunc()) && sf->pOrgScript == *s)
|
||||
{
|
||||
// append: create copy
|
||||
C4AulScriptFunc *sfc = new C4AulScriptFunc(this, *sf);
|
||||
}
|
||||
// copy local var definitions
|
||||
for (int ivar = 0; ivar < (*s)->LocalNamed.iSize; ivar ++)
|
||||
LocalNamed.AddName((*s)->LocalNamed.pNames[ivar]);
|
||||
}
|
||||
|
||||
LinkFunctions();
|
||||
|
||||
// parse
|
||||
C4AulParse state(this, C4AulParse::PARSER);
|
||||
for (std::list<C4ScriptHost *>::iterator s = SourceScripts.begin(); s != SourceScripts.end(); ++s)
|
||||
{
|
||||
state.SPos = (*s)->Script.getData();
|
||||
state.pOrgScript = *s;
|
||||
if (DEBUG_BYTECODE_DUMP)
|
||||
{
|
||||
fprintf(stderr, "parsing %s...\n", state.pOrgScript->ScriptName.getData());
|
||||
}
|
||||
state.Parse_Script();
|
||||
}
|
||||
|
||||
// add eof chunk
|
||||
AddBCC(AB_EOF);
|
||||
|
||||
// calc absolute code addresses for script funcs
|
||||
for (C4AulFunc * f = Func0; f; f = f->Next)
|
||||
{
|
||||
C4AulScriptFunc * Fn = f->SFunc();
|
||||
assert(Fn);
|
||||
if (Fn)
|
||||
assert(Fn->GetCodeOwner() == this);
|
||||
}
|
||||
|
||||
// save line count
|
||||
Engine->lineCnt += SGetLine(Script.getData(), Script.getPtr(Script.getLength()));
|
||||
|
||||
// dump bytecode
|
||||
if (DEBUG_BYTECODE_DUMP)
|
||||
for (C4AulFunc * f = Func0; f; f = f->Next)
|
||||
{
|
||||
C4AulScriptFunc *Fn = f->SFunc();
|
||||
assert(Fn);
|
||||
if (!Fn)
|
||||
continue;
|
||||
fprintf(stderr, "%s:\n", Fn->GetName());
|
||||
std::map<C4AulBCC *, int> labels;
|
||||
int labeln = 0;
|
||||
for (C4AulBCC *pBCC = Fn->GetCode(); pBCC->bccType != AB_EOFN; pBCC++)
|
||||
{
|
||||
switch (pBCC->bccType)
|
||||
{
|
||||
case AB_JUMP: case AB_JUMPAND: case AB_JUMPOR: case AB_JUMPNNIL: case AB_CONDN: case AB_COND:
|
||||
labels[pBCC + pBCC->Par.i] = ++labeln; break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
for (C4AulBCC *pBCC = Fn->GetCode();; pBCC++)
|
||||
{
|
||||
C4AulBCCType eType = pBCC->bccType;
|
||||
if (labels.find(pBCC) != labels.end())
|
||||
fprintf(stderr, "%d:\n", labels[pBCC]);
|
||||
fprintf(stderr, "\t%d\t%s", Fn->GetLineOfCode(pBCC), GetTTName(eType));
|
||||
switch (eType)
|
||||
{
|
||||
case AB_FUNC:
|
||||
fprintf(stderr, "\t%s\n", pBCC->Par.f->GetName()); break;
|
||||
case AB_CALL: case AB_CALLFS: case AB_LOCALN: case AB_LOCALN_SET: case AB_PROP: case AB_PROP_SET:
|
||||
fprintf(stderr, "\t%s\n", pBCC->Par.s->GetCStr()); break;
|
||||
case AB_STRING:
|
||||
fprintf(stderr, "\t\"%s\"\n", pBCC->Par.s->GetCStr()); break;
|
||||
case AB_DEBUG: case AB_NIL: case AB_RETURN:
|
||||
case AB_PAR:
|
||||
case AB_ARRAYA: case AB_ARRAYA_SET: case AB_ARRAY_SLICE: case AB_ARRAY_SLICE_SET:
|
||||
case AB_ERR: case AB_EOFN: case AB_EOF:
|
||||
assert(!pBCC->Par.X); fprintf(stderr, "\n"); break;
|
||||
case AB_CARRAY: case AB_CPROPLIST:
|
||||
fprintf(stderr, "\t%p\n", reinterpret_cast<void *>(pBCC->Par.X)); break;
|
||||
case AB_JUMP: case AB_JUMPAND: case AB_JUMPOR: case AB_JUMPNNIL: case AB_CONDN: case AB_COND:
|
||||
fprintf(stderr, "\t%d\n", labels[pBCC + pBCC->Par.i]); break;
|
||||
default:
|
||||
fprintf(stderr, "\t%d\n", pBCC->Par.i); break;
|
||||
}
|
||||
if (eType == AB_EOFN) break;
|
||||
}
|
||||
}
|
||||
|
||||
// finished
|
||||
State = ASS_PARSED;
|
||||
|
||||
|
|
|
@ -62,7 +62,7 @@ void C4PropList::DelRef(const C4Value * pRef, C4Value * pNextRef)
|
|||
}
|
||||
// Only pure script proplists are garbage collected here, host proplists
|
||||
// like definitions and effects have their own memory management.
|
||||
if (IsScriptPropList()) delete this;
|
||||
if (Delete()) delete this;
|
||||
}
|
||||
|
||||
C4PropList * C4PropList::New(C4PropList * prototype)
|
||||
|
@ -71,15 +71,9 @@ C4PropList * C4PropList::New(C4PropList * prototype)
|
|||
return r;
|
||||
}
|
||||
|
||||
C4PropList * C4PropList::NewAnon(C4PropList * prototype)
|
||||
C4PropListStatic * C4PropList::NewAnon(C4PropList * prototype, const C4PropListStatic * parent, C4String * key)
|
||||
{
|
||||
C4PropList * r = new C4PropListScript(prototype);
|
||||
return r;
|
||||
}
|
||||
|
||||
C4PropList * C4PropList::NewScen(C4PropList * prototype)
|
||||
{
|
||||
return new C4PropList(prototype);
|
||||
return new C4PropListStatic(prototype, parent, key);
|
||||
}
|
||||
|
||||
C4Set<C4PropListNumbered *> C4PropListNumbered::PropLists;
|
||||
|
@ -157,6 +151,33 @@ C4PropListNumbered::~C4PropListNumbered()
|
|||
Log("removing numbered proplist without number");
|
||||
}
|
||||
|
||||
void C4PropListStatic::RefCompileFunc(StdCompiler *pComp, C4ValueNumbers * numbers) const
|
||||
{
|
||||
assert(!pComp->isCompiler());
|
||||
if (Parent)
|
||||
{
|
||||
Parent->RefCompileFunc(pComp, numbers);
|
||||
pComp->Separator(StdCompiler::SEP_PART);
|
||||
}
|
||||
if (!ParentKeyName)
|
||||
pComp->excCorrupt("C4PropListStatic::RefCompileFunc without ParentKeyName");
|
||||
pComp->Value(mkParAdapt(ParentKeyName->GetData(), StdCompiler::RCT_ID));
|
||||
}
|
||||
|
||||
StdStrBuf C4PropListStatic::GetDataString() const
|
||||
{
|
||||
StdStrBuf r;
|
||||
if (Parent)
|
||||
{
|
||||
r.Take(Parent->GetDataString());
|
||||
r.AppendChar('.');
|
||||
}
|
||||
assert(ParentKeyName);
|
||||
if (ParentKeyName)
|
||||
r.Append(ParentKeyName->GetData());
|
||||
return r;
|
||||
}
|
||||
|
||||
#ifdef _DEBUG
|
||||
C4Set<C4PropList *> C4PropList::PropLists;
|
||||
#endif
|
||||
|
@ -204,13 +225,18 @@ C4PropList::~C4PropList()
|
|||
|
||||
bool C4PropList::operator==(const C4PropList &b) const
|
||||
{
|
||||
// every numbered proplist has a unique number and is only identical to itself
|
||||
if (this == &b) return true;
|
||||
if (IsNumbered() || b.IsNumbered()) return false;
|
||||
if (Properties.GetSize() != b.Properties.GetSize()) return false;
|
||||
if (GetDef() != b.GetDef()) return false;
|
||||
//if (GetObject() != b.GetObject()) return false;
|
||||
const C4Property * p = Properties.First();
|
||||
while (p)
|
||||
{
|
||||
if (*p != b.Properties.Get(p->Key)) return false;
|
||||
const C4Property & bp = b.Properties.Get(p->Key);
|
||||
if (!bp) return false;
|
||||
if (p->Value != bp.Value) return false;
|
||||
p = Properties.Next(p);
|
||||
}
|
||||
return true;
|
||||
|
@ -476,8 +502,7 @@ C4Value C4PropList::CallOrThrow(const char * s, C4AulParSet *Pars)
|
|||
{
|
||||
if (s[0] == '~')
|
||||
return C4Value();
|
||||
throw new C4AulExecError(this->GetObject(),
|
||||
FormatString("Call: no function \"%s\"", s).getData());
|
||||
throw new C4AulExecError(FormatString("Call: no function \"%s\"", s).getData());
|
||||
}
|
||||
return pFn->Exec(this, Pars);
|
||||
}
|
||||
|
@ -513,6 +538,42 @@ int32_t C4PropList::GetPropertyInt(C4PropertyName n) const
|
|||
return 0;
|
||||
}
|
||||
|
||||
C4ValueArray * C4PropList::GetProperties() const
|
||||
{
|
||||
C4ValueArray * a;
|
||||
int i;
|
||||
if (prototype)
|
||||
{
|
||||
a = prototype->GetProperties();
|
||||
i = a->GetSize();
|
||||
a->SetSize(i + Properties.GetSize());
|
||||
}
|
||||
else
|
||||
{
|
||||
a = new C4ValueArray(Properties.GetSize());
|
||||
i = 0;
|
||||
}
|
||||
const C4Property * p = Properties.First();
|
||||
while (p)
|
||||
{
|
||||
(*a)[i++] = C4VString(p->Key);
|
||||
p = Properties.Next(p);
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
C4String * C4PropList::EnumerateOwnFuncs(C4String * prev) const
|
||||
{
|
||||
const C4Property * p = prev ? Properties.Next(&Properties.Get(prev)) : Properties.First();
|
||||
while (p)
|
||||
{
|
||||
if (p->Value.getFunction())
|
||||
return p->Key;
|
||||
p = Properties.Next(p);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void C4PropList::SetPropertyByS(C4String * k, const C4Value & to)
|
||||
{
|
||||
assert(!constant);
|
||||
|
@ -522,7 +583,7 @@ void C4PropList::SetPropertyByS(C4String * k, const C4Value & to)
|
|||
C4PropList * newpt = to.GetData().PropList;
|
||||
for(C4PropList * it = newpt; it; it = it->prototype)
|
||||
if(it == this)
|
||||
throw new C4AulExecError(NULL, "Trying to create cyclic prototype structure");
|
||||
throw new C4AulExecError("Trying to create cyclic prototype structure");
|
||||
prototype = newpt;
|
||||
//return;
|
||||
}
|
||||
|
|
|
@ -63,15 +63,17 @@ public:
|
|||
virtual C4PropListNumbered * GetPropListNumbered();
|
||||
C4PropList * GetPrototype() const { return prototype; }
|
||||
|
||||
// Whether this proplist should be saved as a reference to a C4Def/C4Object
|
||||
virtual bool IsDef() const { return false; }
|
||||
// saved as a reference to a global constant?
|
||||
virtual class C4PropListStatic * IsStatic() { return NULL; }
|
||||
// saved as a reference to separately saved objects?
|
||||
virtual bool IsNumbered() const { return false; }
|
||||
// Whether this proplist is a pure script proplist, not a host object
|
||||
virtual bool IsScriptPropList() { return false; }
|
||||
// some proplists have references that are not reference-counted
|
||||
virtual bool Delete() { return false; }
|
||||
|
||||
// These three operate on properties as seen by script, which can be dynamic
|
||||
// These four operate on properties as seen by script, which can be dynamic
|
||||
// or reflect C++ variables
|
||||
virtual bool GetPropertyByS(C4String *k, C4Value *pResult) const;
|
||||
virtual C4ValueArray * GetProperties() const;
|
||||
// not allowed on frozen proplists
|
||||
virtual void SetPropertyByS(C4String * k, const C4Value & to);
|
||||
virtual void ResetProperty(C4String * k);
|
||||
|
@ -84,6 +86,7 @@ public:
|
|||
{ return GetFunc(&Strings.P[k]); }
|
||||
C4AulFunc * GetFunc(C4String * k) const;
|
||||
C4AulFunc * GetFunc(const char * k) const;
|
||||
C4String * EnumerateOwnFuncs(C4String * prev = 0) const;
|
||||
C4Value Call(C4PropertyName k, C4AulParSet *pPars=0)
|
||||
{ return Call(&Strings.P[k], pPars); }
|
||||
C4Value Call(C4String * k, C4AulParSet *pPars=0);
|
||||
|
@ -97,10 +100,10 @@ public:
|
|||
{ SetPropertyByS(&Strings.P[k], to); }
|
||||
|
||||
static C4PropList * New(C4PropList * prototype = 0);
|
||||
static C4PropList * NewAnon(C4PropList * prototype = 0);
|
||||
static C4PropList * NewScen(C4PropList * prototype = 0);
|
||||
static C4PropListStatic * NewAnon(C4PropList * prototype, const C4PropListStatic * parent, C4String * key);
|
||||
|
||||
// only freeze proplists which are not going to be modified
|
||||
// FIXME: Only C4PropListStatic get frozen. Optimize accordingly.
|
||||
void Freeze() { constant = true; }
|
||||
void Thaw() { constant = false; }
|
||||
bool IsFrozen() const { return constant; }
|
||||
|
@ -108,7 +111,6 @@ public:
|
|||
virtual void Denumerate(C4ValueNumbers *);
|
||||
virtual ~C4PropList();
|
||||
|
||||
// Every proplist has to be initialized by either Init or CompileFunc.
|
||||
void CompileFunc(StdCompiler *pComp, C4ValueNumbers *);
|
||||
void AppendDataString(StdStrBuf * out, const char * delim, int depth = 3);
|
||||
|
||||
|
@ -125,6 +127,7 @@ private:
|
|||
C4Set<C4Property> Properties;
|
||||
C4PropList * prototype;
|
||||
bool constant; // if true, this proplist is not changeable
|
||||
friend class C4ScriptHost;
|
||||
public:
|
||||
int32_t Status;
|
||||
};
|
||||
|
@ -132,7 +135,7 @@ public:
|
|||
void CompileNewFunc(C4PropList *&pStruct, StdCompiler *pComp, C4ValueNumbers * const & rPar);
|
||||
|
||||
// Proplists that are created during a game and get saved in a savegame
|
||||
// Examples: Objects, Effects, scriptcreated proplists
|
||||
// Examples: Objects, Effects
|
||||
class C4PropListNumbered: public C4PropList
|
||||
{
|
||||
public:
|
||||
|
@ -162,8 +165,26 @@ class C4PropListScript: public C4PropList
|
|||
{
|
||||
public:
|
||||
C4PropListScript(C4PropList * prototype = 0): C4PropList(prototype) { }
|
||||
bool IsScriptPropList() { return true; }
|
||||
bool Delete() { return true; }
|
||||
};
|
||||
|
||||
// PropLists declared in the game data
|
||||
// examples: Definitions, local variable initializers
|
||||
class C4PropListStatic: public C4PropList
|
||||
{
|
||||
public:
|
||||
C4PropListStatic(C4PropList * prototype, const C4PropListStatic * parent, C4String * key):
|
||||
C4PropList(prototype), Parent(parent), ParentKeyName(key) { }
|
||||
virtual ~C4PropListStatic() { }
|
||||
bool Delete() { return true; }
|
||||
virtual C4PropListStatic * IsStatic() { return this; }
|
||||
void RefCompileFunc(StdCompiler *pComp, C4ValueNumbers * numbers) const;
|
||||
StdStrBuf GetDataString() const;
|
||||
const C4PropListStatic * GetParent() { return Parent; }
|
||||
const C4String * GetParentKeyName() { return ParentKeyName; }
|
||||
protected:
|
||||
const C4PropListStatic * Parent;
|
||||
C4RefCntPointer<C4String> ParentKeyName; // property in parent this proplist was created in
|
||||
};
|
||||
|
||||
#endif // C4PROPLIST_H
|
||||
|
|
|
@ -33,19 +33,14 @@
|
|||
|
||||
//========================== Some Support Functions =======================================
|
||||
|
||||
StdStrBuf FnStringFormat(C4AulContext *cthr, const char *szFormatPar, C4Value * Par0, C4Value * Par1, C4Value * Par2, C4Value * Par3,
|
||||
C4Value * Par4, C4Value * Par5, C4Value * Par6, C4Value * Par7, C4Value * Par8, C4Value * Par9)
|
||||
StdStrBuf FnStringFormat(C4PropList * _this, C4String *szFormatPar, C4Value * Pars, int ParCount)
|
||||
{
|
||||
C4Value * Par[11];
|
||||
Par[0]=Par0; Par[1]=Par1; Par[2]=Par2; Par[3]=Par3; Par[4]=Par4;
|
||||
Par[5]=Par5; Par[6]=Par6; Par[7]=Par7; Par[8]=Par8; Par[9]=Par9;
|
||||
Par[10] = 0;
|
||||
int cPar=0;
|
||||
|
||||
StdStrBuf StringBuf("", false);
|
||||
const char * cpFormat = szFormatPar;
|
||||
const char * cpFormat = FnStringPar(szFormatPar);
|
||||
const char * cpType;
|
||||
char szField[MaxFnStringParLen+1];
|
||||
char szField[20];
|
||||
while (*cpFormat)
|
||||
{
|
||||
// Copy normal stuff
|
||||
|
@ -57,31 +52,31 @@ StdStrBuf FnStringFormat(C4AulContext *cthr, const char *szFormatPar, C4Value *
|
|||
// Scan field type
|
||||
for (cpType=cpFormat+1; *cpType && (*cpType=='.' || Inside(*cpType,'0','9')); cpType++) {}
|
||||
// Copy field
|
||||
SCopy(cpFormat,szField,cpType-cpFormat+1);
|
||||
SCopy(cpFormat,szField,Min<unsigned int>(sizeof szField - 1, cpType - cpFormat + 1));
|
||||
// Insert field by type
|
||||
switch (*cpType)
|
||||
{
|
||||
// number
|
||||
case 'd': case 'x': case 'X':
|
||||
{
|
||||
if (!Par[cPar]) throw new C4AulExecError(cthr->Obj, "format placeholder without parameter");
|
||||
StringBuf.AppendFormat(szField, Par[cPar++]->getInt());
|
||||
if (cPar >= ParCount) throw new C4AulExecError("format placeholder without parameter");
|
||||
StringBuf.AppendFormat(szField, Pars[cPar++].getInt());
|
||||
cpFormat+=SLen(szField);
|
||||
break;
|
||||
}
|
||||
// character
|
||||
case 'c':
|
||||
{
|
||||
if (!Par[cPar]) throw new C4AulExecError(cthr->Obj, "format placeholder without parameter");
|
||||
StringBuf.AppendCharacter(Par[cPar++]->getInt());
|
||||
if (cPar >= ParCount) throw new C4AulExecError("format placeholder without parameter");
|
||||
StringBuf.AppendCharacter(Pars[cPar++].getInt());
|
||||
cpFormat+=SLen(szField);
|
||||
break;
|
||||
}
|
||||
// C4ID
|
||||
case 'i':
|
||||
{
|
||||
if (!Par[cPar]) throw new C4AulExecError(cthr->Obj, "format placeholder without parameter");
|
||||
C4ID id = Par[cPar++]->getC4ID();
|
||||
if (cPar >= ParCount) throw new C4AulExecError("format placeholder without parameter");
|
||||
C4ID id = Pars[cPar++].getC4ID();
|
||||
StringBuf.Append(id.ToString());
|
||||
cpFormat+=SLen(szField);
|
||||
break;
|
||||
|
@ -89,8 +84,8 @@ StdStrBuf FnStringFormat(C4AulContext *cthr, const char *szFormatPar, C4Value *
|
|||
// C4Value
|
||||
case 'v':
|
||||
{
|
||||
if (!Par[cPar]) throw new C4AulExecError(cthr->Obj, "format placeholder without parameter");
|
||||
StringBuf.Append(static_cast<const StdStrBuf&>(Par[cPar++]->GetDataString(10)));
|
||||
if (cPar >= ParCount) throw new C4AulExecError("format placeholder without parameter");
|
||||
StringBuf.Append(static_cast<const StdStrBuf&>(Pars[cPar++].GetDataString(10)));
|
||||
cpFormat+=SLen(szField);
|
||||
break;
|
||||
}
|
||||
|
@ -98,14 +93,15 @@ StdStrBuf FnStringFormat(C4AulContext *cthr, const char *szFormatPar, C4Value *
|
|||
case 's':
|
||||
{
|
||||
// get string
|
||||
if (!Par[cPar]) throw new C4AulExecError(cthr->Obj, "format placeholder without parameter");
|
||||
if (cPar >= ParCount) throw new C4AulExecError("format placeholder without parameter");
|
||||
const char *szStr = "(null)";
|
||||
if (Par[cPar]->GetData())
|
||||
if (Pars[cPar].GetData())
|
||||
{
|
||||
C4String * pStr = Par[cPar++]->getStr();
|
||||
if (!pStr) throw new C4AulExecError(cthr->Obj, "string format placeholder without string");
|
||||
C4String * pStr = Pars[cPar].getStr();
|
||||
if (!pStr) throw new C4AulExecError("string format placeholder without string");
|
||||
szStr = pStr->GetCStr();
|
||||
}
|
||||
++cPar;
|
||||
StringBuf.AppendFormat(szField, szStr);
|
||||
cpFormat+=SLen(szField);
|
||||
break;
|
||||
|
@ -154,88 +150,104 @@ bool C4ValueToMatrix(const C4ValueArray& array, StdMeshMatrix* matrix)
|
|||
return true;
|
||||
}
|
||||
|
||||
//=============================== C4Script Functions ====================================
|
||||
|
||||
static C4PropList *Fn_this(C4AulContext *cthr)
|
||||
C4AulDefFunc::C4AulDefFunc(C4AulScript *pOwner, C4ScriptFnDef* pDef):
|
||||
C4AulFunc(pOwner, pDef->Identifier), Def(pDef)
|
||||
{
|
||||
return cthr->Def;
|
||||
Owner->GetPropList()->SetPropertyByS(Name, C4VFunction(this));
|
||||
}
|
||||
|
||||
static C4PropList * FnCreatePropList(C4AulContext *cthr, C4PropList * prototype)
|
||||
C4AulDefFunc::~C4AulDefFunc()
|
||||
{
|
||||
}
|
||||
|
||||
C4Value C4AulDefFunc::Exec(C4PropList * p, C4Value pPars[], bool fPassErrors)
|
||||
{
|
||||
assert(Def->FunctionC4V);
|
||||
return Def->FunctionC4V(p, pPars);
|
||||
}
|
||||
|
||||
//=============================== C4Script Functions ====================================
|
||||
|
||||
static C4PropList *Fnthis(C4PropList * _this)
|
||||
{
|
||||
return _this;
|
||||
}
|
||||
|
||||
static C4PropList * FnCreatePropList(C4PropList * _this, C4PropList * prototype)
|
||||
{
|
||||
return C4PropList::New(prototype);
|
||||
}
|
||||
|
||||
static C4Value FnGetProperty_C4V(C4AulContext *cthr, C4Value * key_C4V, C4Value * pObj_C4V)
|
||||
static C4Value FnGetProperty(C4PropList * _this, C4String * key, C4PropList * pObj)
|
||||
{
|
||||
C4PropList * pObj = pObj_C4V->_getPropList();
|
||||
if (!pObj) pObj=cthr->Obj;
|
||||
if (!pObj) pObj=cthr->Def;
|
||||
if (!pObj) pObj = _this;
|
||||
if (!pObj) return C4VNull;
|
||||
C4String * key = key_C4V->_getStr();
|
||||
if (!key) return C4VNull;
|
||||
C4Value r;
|
||||
pObj->GetPropertyByS(key, &r);
|
||||
return r;
|
||||
}
|
||||
|
||||
static C4Value FnSetProperty_C4V(C4AulContext *cthr, C4Value * key_C4V, C4Value * to, C4Value * pObj_C4V)
|
||||
static bool FnSetProperty(C4PropList * _this, C4String * key, const C4Value & to, C4PropList * pObj)
|
||||
{
|
||||
C4PropList * pObj = pObj_C4V->_getPropList();
|
||||
if (!pObj) pObj=cthr->Obj;
|
||||
if (!pObj) pObj=cthr->Def;
|
||||
if (!pObj) return C4VFalse;
|
||||
C4String * key = key_C4V->_getStr();
|
||||
if (!key) return C4VFalse;
|
||||
if (!pObj) pObj = _this;
|
||||
if (!pObj) return false;
|
||||
if (!key) return false;
|
||||
if (pObj->IsFrozen())
|
||||
throw new C4AulExecError(cthr->Obj, "proplist write: proplist is readonly");
|
||||
pObj->SetPropertyByS(key, *to);
|
||||
return C4VTrue;
|
||||
throw new C4AulExecError("proplist write: proplist is readonly");
|
||||
pObj->SetPropertyByS(key, to);
|
||||
return true;
|
||||
}
|
||||
|
||||
static C4Value FnResetProperty_C4V(C4AulContext *cthr, C4Value * key_C4V, C4Value * pObj_C4V)
|
||||
static bool FnResetProperty(C4PropList * _this, C4String * key, C4PropList * pObj)
|
||||
{
|
||||
C4PropList * pObj = pObj_C4V->_getPropList();
|
||||
if (!pObj) pObj=cthr->Obj;
|
||||
if (!pObj) pObj=cthr->Def;
|
||||
if (!pObj) return C4VFalse;
|
||||
C4String * key = key_C4V->_getStr();
|
||||
if (!key) return C4VFalse;
|
||||
if (!pObj->HasProperty(key)) return C4VFalse;
|
||||
if (!pObj) pObj = _this;
|
||||
if (!pObj) return false;
|
||||
if (!key) return false;
|
||||
if (!pObj->HasProperty(key)) return false;
|
||||
if (pObj->IsFrozen())
|
||||
throw new C4AulExecError(cthr->Obj, "proplist write: proplist is readonly");
|
||||
throw new C4AulExecError("proplist write: proplist is readonly");
|
||||
pObj->ResetProperty(key);
|
||||
return C4VTrue;
|
||||
return true;
|
||||
}
|
||||
|
||||
static C4Value FnLog_C4V(C4AulContext *cthr, C4Value *szMessage, C4Value * iPar0, C4Value * iPar1, C4Value * iPar2, C4Value * iPar3, C4Value * iPar4, C4Value * iPar5, C4Value * iPar6, C4Value * iPar7, C4Value * iPar8)
|
||||
static C4ValueArray * FnGetProperties(C4PropList * _this, C4PropList * p)
|
||||
{
|
||||
Log(FnStringFormat(cthr, FnStringPar(szMessage->getStr()),iPar0,iPar1,iPar2,iPar3,iPar4,iPar5,iPar6,iPar7,iPar8).getData());
|
||||
if (!p) p = _this;
|
||||
if (!p) throw new NeedNonGlobalContext("GetProperties");
|
||||
C4ValueArray * r = p->GetProperties();
|
||||
r->SortStrings();
|
||||
return r;
|
||||
}
|
||||
|
||||
static C4Value FnLog(C4PropList * _this, C4Value * Pars)
|
||||
{
|
||||
Log(FnStringFormat(_this, Pars[0].getStr(), &Pars[1], 9).getData());
|
||||
return C4VBool(true);
|
||||
}
|
||||
|
||||
static C4Value FnDebugLog_C4V(C4AulContext *cthr, C4Value *szMessage, C4Value * iPar0, C4Value * iPar1, C4Value * iPar2, C4Value * iPar3, C4Value * iPar4, C4Value * iPar5, C4Value * iPar6, C4Value * iPar7, C4Value * iPar8)
|
||||
static C4Value FnDebugLog(C4PropList * _this, C4Value * Pars)
|
||||
{
|
||||
DebugLog(FnStringFormat(cthr, FnStringPar(szMessage->getStr()),iPar0,iPar1,iPar2,iPar3,iPar4,iPar5,iPar6,iPar7,iPar8).getData());
|
||||
DebugLog(FnStringFormat(_this, Pars[0].getStr(), &Pars[1], 9).getData());
|
||||
return C4VBool(true);
|
||||
}
|
||||
|
||||
static C4Value FnFormat_C4V(C4AulContext *cthr, C4Value *szFormat, C4Value * iPar0, C4Value * iPar1, C4Value * iPar2, C4Value * iPar3, C4Value * iPar4, C4Value * iPar5, C4Value * iPar6, C4Value * iPar7, C4Value * iPar8)
|
||||
static C4Value FnFormat(C4PropList * _this, C4Value * Pars)
|
||||
{
|
||||
return C4VString(FnStringFormat(cthr, FnStringPar(szFormat->getStr()),iPar0,iPar1,iPar2,iPar3,iPar4,iPar5,iPar6,iPar7,iPar8));
|
||||
return C4VString(FnStringFormat(_this, Pars[0].getStr(), &Pars[1], 9));
|
||||
}
|
||||
|
||||
static C4ID FnC4Id(C4AulContext *cthr, C4String *szID)
|
||||
static C4ID FnC4Id(C4PropList * _this, C4String *szID)
|
||||
{
|
||||
return(C4ID(FnStringPar(szID)));
|
||||
}
|
||||
|
||||
static long FnAbs(C4AulContext *cthr, long iVal)
|
||||
static long FnAbs(C4PropList * _this, long iVal)
|
||||
{
|
||||
return Abs(iVal);
|
||||
}
|
||||
|
||||
static long FnSin(C4AulContext *cthr, long iAngle, long iRadius, long iPrec)
|
||||
static long FnSin(C4PropList * _this, long iAngle, long iRadius, long iPrec)
|
||||
{
|
||||
if (!iPrec) iPrec = 1;
|
||||
// Precalculate the modulo operation so the C4Fixed argument to Sin does not overflow
|
||||
|
@ -244,14 +256,14 @@ static long FnSin(C4AulContext *cthr, long iAngle, long iRadius, long iPrec)
|
|||
return fixtoi(Sin(itofix(iAngle, iPrec)), iRadius);
|
||||
}
|
||||
|
||||
static long FnCos(C4AulContext *cthr, long iAngle, long iRadius, long iPrec)
|
||||
static long FnCos(C4PropList * _this, long iAngle, long iRadius, long iPrec)
|
||||
{
|
||||
if (!iPrec) iPrec = 1;
|
||||
iAngle %= 360 * iPrec;
|
||||
return fixtoi(Cos(itofix(iAngle, iPrec)), iRadius);
|
||||
}
|
||||
|
||||
static long FnSqrt(C4AulContext *cthr, long iValue)
|
||||
static long FnSqrt(C4PropList * _this, long iValue)
|
||||
{
|
||||
if (iValue<0) return 0;
|
||||
long iSqrt = long(sqrt(double(iValue)));
|
||||
|
@ -260,7 +272,7 @@ static long FnSqrt(C4AulContext *cthr, long iValue)
|
|||
return iSqrt;
|
||||
}
|
||||
|
||||
static long FnAngle(C4AulContext *cthr, long iX1, long iY1, long iX2, long iY2, long iPrec)
|
||||
static long FnAngle(C4PropList * _this, long iX1, long iY1, long iX2, long iY2, long iPrec)
|
||||
{
|
||||
long iAngle;
|
||||
|
||||
|
@ -295,7 +307,7 @@ static long FnAngle(C4AulContext *cthr, long iX1, long iY1, long iX2, long iY2,
|
|||
return iAngle;
|
||||
}
|
||||
|
||||
static long FnArcSin(C4AulContext *cthr, long iVal, long iRadius)
|
||||
static long FnArcSin(C4PropList * _this, long iVal, long iRadius)
|
||||
{
|
||||
// safety
|
||||
if (!iRadius) return 0;
|
||||
|
@ -307,7 +319,7 @@ static long FnArcSin(C4AulContext *cthr, long iVal, long iRadius)
|
|||
return (long) floor(f1+0.5);
|
||||
}
|
||||
|
||||
static long FnArcCos(C4AulContext *cthr, long iVal, long iRadius)
|
||||
static long FnArcCos(C4PropList * _this, long iVal, long iRadius)
|
||||
{
|
||||
// safety
|
||||
if (!iRadius) return 0;
|
||||
|
@ -319,42 +331,42 @@ static long FnArcCos(C4AulContext *cthr, long iVal, long iRadius)
|
|||
return (long) floor(f1+0.5);
|
||||
}
|
||||
|
||||
static long FnMin(C4AulContext *cthr, long iVal1, long iVal2)
|
||||
static long FnMin(C4PropList * _this, long iVal1, long iVal2)
|
||||
{
|
||||
return Min(iVal1,iVal2);
|
||||
}
|
||||
|
||||
static long FnMax(C4AulContext *cthr, long iVal1, long iVal2)
|
||||
static long FnMax(C4PropList * _this, long iVal1, long iVal2)
|
||||
{
|
||||
return Max(iVal1,iVal2);
|
||||
}
|
||||
|
||||
static long FnDistance(C4AulContext *cthr, long iX1, long iY1, long iX2, long iY2)
|
||||
static long FnDistance(C4PropList * _this, long iX1, long iY1, long iX2, long iY2)
|
||||
{
|
||||
return Distance(iX1,iY1,iX2,iY2);
|
||||
}
|
||||
|
||||
static long FnBoundBy(C4AulContext *cthr, long iVal, long iRange1, long iRange2)
|
||||
static long FnBoundBy(C4PropList * _this, long iVal, long iRange1, long iRange2)
|
||||
{
|
||||
return BoundBy(iVal,iRange1,iRange2);
|
||||
}
|
||||
|
||||
static bool FnInside(C4AulContext *cthr, long iVal, long iRange1, long iRange2)
|
||||
static bool FnInside(C4PropList * _this, long iVal, long iRange1, long iRange2)
|
||||
{
|
||||
return Inside(iVal,iRange1,iRange2);
|
||||
}
|
||||
|
||||
static long FnRandom(C4AulContext *cthr, long iRange)
|
||||
static long FnRandom(C4PropList * _this, long iRange)
|
||||
{
|
||||
return Random(iRange);
|
||||
}
|
||||
|
||||
static long FnAsyncRandom(C4AulContext *cthr, long iRange)
|
||||
static long FnAsyncRandom(C4PropList * _this, long iRange)
|
||||
{
|
||||
return SafeRandom(iRange);
|
||||
}
|
||||
|
||||
static int FnGetType(C4AulContext *cthr, const C4Value & Value)
|
||||
static int FnGetType(C4PropList * _this, const C4Value & Value)
|
||||
{
|
||||
// dynamic types
|
||||
if (Value.CheckConversion(C4V_Object)) return C4V_Object;
|
||||
|
@ -364,54 +376,49 @@ static int FnGetType(C4AulContext *cthr, const C4Value & Value)
|
|||
return Value.GetType();
|
||||
}
|
||||
|
||||
static C4ValueArray * FnCreateArray(C4AulContext *cthr, int iSize)
|
||||
static C4ValueArray * FnCreateArray(C4PropList * _this, int iSize)
|
||||
{
|
||||
return new C4ValueArray(iSize);
|
||||
}
|
||||
|
||||
static C4Value FnGetLength(C4AulContext *cthr, C4Value *pPars)
|
||||
static int FnGetLength(C4PropList * _this, const C4Value & Par)
|
||||
{
|
||||
// support GetLength() etc.
|
||||
if (!pPars[0]) return C4VNull;
|
||||
C4ValueArray * pArray = pPars->getArray();
|
||||
C4ValueArray * pArray = Par.getArray();
|
||||
if (pArray)
|
||||
return C4VInt(pArray->GetSize());
|
||||
C4String * pStr = pPars->getStr();
|
||||
return pArray->GetSize();
|
||||
C4String * pStr = Par.getStr();
|
||||
if (pStr)
|
||||
return C4VInt(GetCharacterCount(pStr->GetData().getData()));
|
||||
throw new C4AulExecError(cthr->Obj, "func \"GetLength\" par 0 cannot be converted to string or array");
|
||||
return GetCharacterCount(pStr->GetData().getData());
|
||||
throw new C4AulExecError("GetLength: parameter 0 cannot be converted to string or array");
|
||||
}
|
||||
|
||||
static C4Value FnGetIndexOf(C4AulContext *cthr, C4Value *pPars)
|
||||
static int FnGetIndexOf(C4PropList * _this, C4ValueArray * pArray, const C4Value & Needle)
|
||||
{
|
||||
// find first occurance of first parameter in array
|
||||
// support GetIndexOf(0, x)
|
||||
if (!pPars[0]) return C4VInt(-1);
|
||||
// if the first param is nonzero, it must be an array
|
||||
const C4ValueArray * pArray = pPars[0].getArray();
|
||||
if (!pArray)
|
||||
throw new C4AulExecError(cthr->Obj, "func \"GetIndexOf\" par 0 cannot be converted to array");
|
||||
if (!pArray) return -1;
|
||||
int32_t iSize = pArray->GetSize();
|
||||
for (int32_t i = 0; i<iSize; ++i)
|
||||
if (pPars[1] == pArray->GetItem(i))
|
||||
for (int32_t i = 0; i < iSize; ++i)
|
||||
if (Needle == pArray->GetItem(i))
|
||||
// element found
|
||||
return C4VInt(i);
|
||||
return i;
|
||||
// element not found
|
||||
return C4VInt(-1);
|
||||
return -1;
|
||||
}
|
||||
|
||||
static C4Void FnSetLength(C4AulContext *cthr, C4ValueArray *pArray, int iNewSize)
|
||||
static C4Void FnSetLength(C4PropList * _this, C4ValueArray *pArray, int iNewSize)
|
||||
{
|
||||
// safety
|
||||
if (iNewSize<0 || iNewSize > C4ValueArray::MaxSize)
|
||||
throw new C4AulExecError(cthr->Obj, FormatString("SetLength: invalid array size (%d)", iNewSize).getData());
|
||||
throw new C4AulExecError(FormatString("SetLength: invalid array size (%d)", iNewSize).getData());
|
||||
|
||||
// set new size
|
||||
pArray->SetSize(iNewSize);
|
||||
return C4Void();
|
||||
}
|
||||
|
||||
static Nillable<long> FnGetChar(C4AulContext* cthr, C4String *pString, long iIndex)
|
||||
static Nillable<long> FnGetChar(C4PropList * _this, C4String *pString, long iIndex)
|
||||
{
|
||||
const char *szText = FnStringPar(pString);
|
||||
if (!szText) return C4Void();
|
||||
|
@ -425,18 +432,18 @@ static Nillable<long> FnGetChar(C4AulContext* cthr, C4String *pString, long iInd
|
|||
return c;
|
||||
}
|
||||
|
||||
static C4Value FnEval(C4AulContext *cthr, C4Value *strScript_C4V)
|
||||
static C4Value Fneval(C4PropList * _this, C4String *strScript)
|
||||
{
|
||||
// execute script in the same object
|
||||
if (cthr->Obj)
|
||||
return cthr->Obj->Def->Script.DirectExec(cthr->Obj, FnStringPar(strScript_C4V->getStr()), "eval", true);
|
||||
else if (cthr->Def && cthr->Def->GetDef())
|
||||
return cthr->Def->GetDef()->Script.DirectExec(0, FnStringPar(strScript_C4V->getStr()), "eval", true);
|
||||
if (Object(_this))
|
||||
return Object(_this)->Def->Script.DirectExec(Object(_this), FnStringPar(strScript), "eval", true);
|
||||
else if (_this && _this->GetDef())
|
||||
return _this->GetDef()->Script.DirectExec(0, FnStringPar(strScript), "eval", true);
|
||||
else
|
||||
return ::GameScript.DirectExec(0, FnStringPar(strScript_C4V->getStr()), "eval", true);
|
||||
return ::GameScript.DirectExec(0, FnStringPar(strScript), "eval", true);
|
||||
}
|
||||
|
||||
static bool FnLocateFunc(C4AulContext *cthr, C4String *funcname, C4PropList * p)
|
||||
static bool FnLocateFunc(C4PropList * _this, C4String *funcname, C4PropList * p)
|
||||
{
|
||||
// safety
|
||||
if (!funcname || !funcname->GetCStr())
|
||||
|
@ -444,7 +451,7 @@ static bool FnLocateFunc(C4AulContext *cthr, C4String *funcname, C4PropList * p)
|
|||
Log("No func name");
|
||||
return false;
|
||||
}
|
||||
if (!p) p = cthr->Def;
|
||||
if (!p) p = _this;
|
||||
// get function by name
|
||||
C4AulFunc *pFunc = p->GetFunc(funcname);
|
||||
if (!pFunc)
|
||||
|
@ -478,7 +485,7 @@ static bool FnLocateFunc(C4AulContext *cthr, C4String *funcname, C4PropList * p)
|
|||
return true;
|
||||
}
|
||||
|
||||
static long FnModulateColor(C4AulContext *cthr, long iClr1, long iClr2)
|
||||
static long FnModulateColor(C4PropList * _this, long iClr1, long iClr2)
|
||||
{
|
||||
DWORD dwClr1 = iClr1;
|
||||
DWORD dwClr2 = iClr2;
|
||||
|
@ -494,24 +501,24 @@ static long FnModulateColor(C4AulContext *cthr, long iClr1, long iClr2)
|
|||
return r;
|
||||
}
|
||||
|
||||
static long FnWildcardMatch(C4AulContext *ctx, C4String *psString, C4String *psWildcard)
|
||||
static long FnWildcardMatch(C4PropList * _this, C4String *psString, C4String *psWildcard)
|
||||
{
|
||||
return SWildcardMatchEx(FnStringPar(psString), FnStringPar(psWildcard));
|
||||
}
|
||||
|
||||
static bool FnFatalError(C4AulContext *ctx, C4String *pErrorMsg)
|
||||
static bool FnFatalError(C4PropList * _this, C4String *pErrorMsg)
|
||||
{
|
||||
throw new C4AulExecError(ctx->Obj, FormatString("script: %s", pErrorMsg ? pErrorMsg->GetCStr() : "(no error)").getData());
|
||||
throw new C4AulExecError(FormatString("script: %s", pErrorMsg ? pErrorMsg->GetCStr() : "(no error)").getData());
|
||||
}
|
||||
|
||||
static bool FnStartCallTrace(C4AulContext *ctx)
|
||||
static bool FnStartCallTrace(C4PropList * _this)
|
||||
{
|
||||
extern void C4AulStartTrace();
|
||||
C4AulStartTrace();
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool FnStartScriptProfiler(C4AulContext *ctx, C4ID idScript)
|
||||
static bool FnStartScriptProfiler(C4PropList * _this, C4ID idScript)
|
||||
{
|
||||
// get script to profile
|
||||
C4AulScript *pScript;
|
||||
|
@ -528,13 +535,13 @@ static bool FnStartScriptProfiler(C4AulContext *ctx, C4ID idScript)
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool FnStopScriptProfiler(C4AulContext *ctx)
|
||||
static bool FnStopScriptProfiler(C4PropList * _this)
|
||||
{
|
||||
C4AulProfiler::StopProfiling();
|
||||
return true;
|
||||
}
|
||||
|
||||
static Nillable<C4String *> FnGetConstantNameByValue(C4AulContext *ctx, int value, Nillable<C4String *> name_prefix, int idx)
|
||||
static Nillable<C4String *> FnGetConstantNameByValue(C4PropList * _this, int value, Nillable<C4String *> name_prefix, int idx)
|
||||
{
|
||||
C4String *name_prefix_s = name_prefix;
|
||||
// find a constant that has the specified value and prefix
|
||||
|
@ -576,26 +583,13 @@ C4ScriptConstDef C4ScriptConstMap[]=
|
|||
{ NULL, C4V_Nil, 0}
|
||||
};
|
||||
|
||||
#define MkFnC4V (C4Value (*)(C4AulContext *cthr, C4Value*, C4Value*, C4Value*, C4Value*, C4Value*,\
|
||||
C4Value*, C4Value*, C4Value*, C4Value*, C4Value*))
|
||||
|
||||
C4ScriptFnDef C4ScriptFnMap[]=
|
||||
{
|
||||
{ "Log", 1, C4V_Bool, { C4V_String ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any}, FnLog },
|
||||
{ "DebugLog", 1, C4V_Bool, { C4V_String ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any}, FnDebugLog },
|
||||
{ "Format", 1, C4V_String, { C4V_String ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any}, FnFormat },
|
||||
|
||||
{ "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 },
|
||||
{ "ResetProperty", 1 ,C4V_Any ,{ C4V_String ,C4V_PropList,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any} ,MkFnC4V FnResetProperty_C4V , 0 },
|
||||
{ "Log", 1 ,C4V_Bool ,{ C4V_String ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any} ,MkFnC4V &FnLog_C4V, 0 },
|
||||
{ "DebugLog", 1 ,C4V_Bool ,{ C4V_String ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any} ,MkFnC4V &FnDebugLog_C4V, 0 },
|
||||
{ "Format", 1 ,C4V_String ,{ C4V_String ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any} ,MkFnC4V &FnFormat_C4V, 0 },
|
||||
|
||||
{ "GetLength", 1 ,C4V_Int ,{ C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any} ,0, FnGetLength },
|
||||
{ "GetIndexOf", 1 ,C4V_Int ,{ C4V_Array ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any} ,0, FnGetIndexOf },
|
||||
|
||||
{ "eval", 1 ,C4V_Any ,{ C4V_String ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any} ,MkFnC4V FnEval, 0 },
|
||||
|
||||
{ NULL, 0 ,C4V_Nil ,{ C4V_Nil ,C4V_Nil ,C4V_Nil ,C4V_Nil ,C4V_Nil ,C4V_Nil ,C4V_Nil ,C4V_Nil ,C4V_Nil ,C4V_Nil} ,0, 0 }
|
||||
|
||||
{ NULL, 0, C4V_Nil, { C4V_Nil ,C4V_Nil ,C4V_Nil ,C4V_Nil ,C4V_Nil ,C4V_Nil ,C4V_Nil ,C4V_Nil ,C4V_Nil ,C4V_Nil}, 0 }
|
||||
};
|
||||
|
||||
void InitCoreFunctionMap(C4AulScriptEngine *pEngine)
|
||||
|
@ -609,39 +603,48 @@ void InitCoreFunctionMap(C4AulScriptEngine *pEngine)
|
|||
|
||||
// add all def script funcs
|
||||
for (C4ScriptFnDef *pDef = &C4ScriptFnMap[0]; pDef->Identifier; pDef++)
|
||||
pEngine->AddFunc(pDef->Identifier, pDef);
|
||||
AddFunc(pEngine, "Abs", FnAbs);
|
||||
AddFunc(pEngine, "Min", FnMin);
|
||||
AddFunc(pEngine, "Max", FnMax);
|
||||
AddFunc(pEngine, "Sin", FnSin);
|
||||
AddFunc(pEngine, "Cos", FnCos);
|
||||
AddFunc(pEngine, "Sqrt", FnSqrt);
|
||||
AddFunc(pEngine, "ArcSin", FnArcSin);
|
||||
AddFunc(pEngine, "ArcCos", FnArcCos);
|
||||
AddFunc(pEngine, "BoundBy", FnBoundBy);
|
||||
AddFunc(pEngine, "Inside", FnInside);
|
||||
AddFunc(pEngine, "Random", FnRandom);
|
||||
AddFunc(pEngine, "AsyncRandom", FnAsyncRandom);
|
||||
new C4AulDefFunc(pEngine, pDef);
|
||||
#define F(f) AddFunc(pEngine, #f, Fn##f)
|
||||
F(Abs);
|
||||
F(Min);
|
||||
F(Max);
|
||||
F(Sin);
|
||||
F(Cos);
|
||||
F(Sqrt);
|
||||
F(ArcSin);
|
||||
F(ArcCos);
|
||||
F(BoundBy);
|
||||
F(Inside);
|
||||
F(Random);
|
||||
F(AsyncRandom);
|
||||
|
||||
AddFunc(pEngine, "CreateArray", FnCreateArray);
|
||||
AddFunc(pEngine, "CreatePropList", FnCreatePropList);
|
||||
AddFunc(pEngine, "C4Id", FnC4Id, false);
|
||||
AddFunc(pEngine, "Distance", FnDistance);
|
||||
AddFunc(pEngine, "Angle", FnAngle);
|
||||
AddFunc(pEngine, "GetChar", FnGetChar);
|
||||
AddFunc(pEngine, "GetType", FnGetType);
|
||||
AddFunc(pEngine, "ModulateColor", FnModulateColor);
|
||||
AddFunc(pEngine, "WildcardMatch", FnWildcardMatch);
|
||||
AddFunc(pEngine, "FatalError", FnFatalError);
|
||||
AddFunc(pEngine, "StartCallTrace", FnStartCallTrace);
|
||||
AddFunc(pEngine, "StartScriptProfiler", FnStartScriptProfiler);
|
||||
AddFunc(pEngine, "StopScriptProfiler", FnStopScriptProfiler);
|
||||
AddFunc(pEngine, "LocateFunc", FnLocateFunc);
|
||||
F(CreateArray);
|
||||
F(CreatePropList);
|
||||
F(GetProperties);
|
||||
F(GetProperty);
|
||||
F(SetProperty);
|
||||
F(ResetProperty);
|
||||
F(C4Id);
|
||||
F(Distance);
|
||||
F(Angle);
|
||||
F(GetChar);
|
||||
F(GetType);
|
||||
F(ModulateColor);
|
||||
F(WildcardMatch);
|
||||
F(GetLength);
|
||||
F(SetLength);
|
||||
F(GetIndexOf);
|
||||
F(FatalError);
|
||||
F(StartCallTrace);
|
||||
F(StartScriptProfiler);
|
||||
F(StopScriptProfiler);
|
||||
F(LocateFunc);
|
||||
|
||||
AddFunc(pEngine, "SetLength", FnSetLength);
|
||||
F(eval);
|
||||
|
||||
AddFunc(pEngine, "this", Fn_this);
|
||||
AddFunc(pEngine, "GetConstantNameByValue", FnGetConstantNameByValue, false);
|
||||
F(this);
|
||||
F(GetConstantNameByValue);
|
||||
|
||||
AddFunc(pEngine, "Translate", C4AulExec::FnTranslate);
|
||||
#undef F
|
||||
}
|
||||
|
|
|
@ -38,8 +38,17 @@ C4ScriptHost::C4ScriptHost()
|
|||
LastCode = NULL;
|
||||
stringTable = 0;
|
||||
SourceScripts.push_back(this);
|
||||
LocalNamed.Reset();
|
||||
// prepare include list
|
||||
IncludesResolved = false;
|
||||
Resolving=false;
|
||||
Includes.clear();
|
||||
Appends.clear();
|
||||
}
|
||||
C4ScriptHost::~C4ScriptHost()
|
||||
{
|
||||
Clear();
|
||||
}
|
||||
C4ScriptHost::~C4ScriptHost() { Clear(); }
|
||||
|
||||
void C4ScriptHost::Clear()
|
||||
{
|
||||
|
@ -49,6 +58,9 @@ void C4ScriptHost::Clear()
|
|||
ClearCode();
|
||||
SourceScripts.clear();
|
||||
SourceScripts.push_back(this);
|
||||
// remove includes
|
||||
Includes.clear();
|
||||
Appends.clear();
|
||||
}
|
||||
|
||||
bool C4ScriptHost::Load(C4Group &hGroup, const char *szFilename,
|
||||
|
@ -109,7 +121,7 @@ void C4ScriptHost::SetError(const char *szMessage)
|
|||
/*--- C4ExtraScriptHost ---*/
|
||||
|
||||
C4ExtraScriptHost::C4ExtraScriptHost():
|
||||
ParserPropList(C4PropList::NewAnon())
|
||||
ParserPropList(C4PropList::NewAnon(NULL, NULL, NULL))
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -125,9 +137,9 @@ C4PropList * C4ExtraScriptHost::GetPropList()
|
|||
|
||||
/*--- C4DefScriptHost ---*/
|
||||
|
||||
bool C4DefScriptHost::Load(C4Group & g, const char * f, const char * l, C4LangStringTable * t)
|
||||
bool C4DefScriptHost::Parse()
|
||||
{
|
||||
bool r = C4ScriptHost::Load(g, f, l, t);
|
||||
bool r = C4ScriptHost::Parse();
|
||||
assert(Def);
|
||||
|
||||
// Check category
|
||||
|
@ -152,7 +164,7 @@ bool C4DefScriptHost::Load(C4Group & g, const char * f, const char * l, C4LangSt
|
|||
case C4D_Living | C4D_Foreground: Plane = 1400; break;
|
||||
case C4D_Object | C4D_Foreground: Plane = 1500; break;
|
||||
default:
|
||||
DebugLogF("WARNING: Def %s (%s) at %s has invalid category!", Def->GetName(), Def->id.ToString(), g.GetFullName().getData());
|
||||
Warn("Def %s (%s) has invalid category", Def->GetName(), Def->id.ToString());
|
||||
gotplane = false;
|
||||
break;
|
||||
}
|
||||
|
@ -160,7 +172,7 @@ bool C4DefScriptHost::Load(C4Group & g, const char * f, const char * l, C4LangSt
|
|||
}
|
||||
if (!Def->GetPlane())
|
||||
{
|
||||
DebugLogF("WARNING: Def %s (%s) at %s has invalid Plane!", Def->GetName(), Def->id.ToString(), g.GetFullName().getData());
|
||||
Warn("Def %s (%s) has invalid Plane", Def->GetName(), Def->id.ToString());
|
||||
Def->SetProperty(P_Plane, C4VInt(1));
|
||||
}
|
||||
return r;
|
||||
|
@ -176,24 +188,26 @@ C4GameScriptHost::~C4GameScriptHost() { }
|
|||
bool C4GameScriptHost::Load(C4Group & g, const char * f, const char * l, C4LangStringTable * t)
|
||||
{
|
||||
assert(ScriptEngine.GetPropList());
|
||||
ScenPrototype = C4PropList::NewScen(ScriptEngine.GetPropList());
|
||||
ScenPropList = C4PropList::NewScen(ScenPrototype);
|
||||
::ScriptEngine.RegisterGlobalConstant("Scenario", C4VPropList(ScenPropList));
|
||||
C4PropListStatic * pScen = C4PropList::NewAnon(NULL/*ScenPrototype*/, NULL, ::Strings.RegString("Scenario"));
|
||||
ScenPropList.SetPropList(pScen);
|
||||
::ScriptEngine.RegisterGlobalConstant("Scenario", ScenPropList);
|
||||
ScenPrototype.SetPropList(C4PropList::NewAnon(ScriptEngine.GetPropList(), pScen, &::Strings.P[P_Prototype]));
|
||||
ScenPropList._getPropList()->SetProperty(P_Prototype, ScenPrototype);
|
||||
Reg2List(&ScriptEngine);
|
||||
return C4ScriptHost::Load(g, f, l, t);
|
||||
}
|
||||
|
||||
void C4GameScriptHost::Clear()
|
||||
{
|
||||
delete ScenPropList; ScenPropList = 0;
|
||||
delete ScenPrototype; ScenPrototype = 0;
|
||||
ScenPropList.Set0();
|
||||
ScenPrototype.Set0();
|
||||
C4ScriptHost::Clear();
|
||||
}
|
||||
|
||||
C4Value C4GameScriptHost::Call(const char *szFunction, C4AulParSet *Pars, bool fPassError)
|
||||
{
|
||||
// FIXME: Does fPassError make sense?
|
||||
return ScenPropList->Call(szFunction, Pars);
|
||||
return ScenPropList._getPropList()->Call(szFunction, Pars);
|
||||
}
|
||||
|
||||
C4Value C4GameScriptHost::GRBroadcast(const char *szFunction, C4AulParSet *pPars, bool fPassError, bool fRejectTest)
|
||||
|
|
|
@ -33,7 +33,7 @@ class C4ScriptHost : public C4AulScript
|
|||
public:
|
||||
~C4ScriptHost();
|
||||
bool Delete() { return false; } // do NOT delete this - it's just a class member!
|
||||
public:
|
||||
|
||||
void Clear();
|
||||
virtual bool Load(C4Group &hGroup, const char *szFilename,
|
||||
const char *szLanguage, C4LangStringTable *pLocalTable);
|
||||
|
@ -52,18 +52,31 @@ protected:
|
|||
void RemoveLastBCC();
|
||||
void ClearCode();
|
||||
bool Preparse(); // preparse script; return if successfull
|
||||
bool Parse(); // parse preparsed script; return if successfull
|
||||
virtual bool Parse(); // parse preparsed script; return if successfull
|
||||
virtual void UnLink(); // reset to unlinked state
|
||||
int GetCodePos() const { return Code.size(); }
|
||||
C4AulBCC *GetCodeByPos(int iPos) { return &Code[iPos]; }
|
||||
C4AulBCC *GetLastCode() { return LastCode; }
|
||||
|
||||
|
||||
std::list<C4ID> Includes; // include list
|
||||
std::list<C4ID> Appends; // append list
|
||||
|
||||
bool ResolveIncludes(C4DefList *rDefs); // resolve includes
|
||||
bool ResolveAppends(C4DefList *rDefs); // resolve appends
|
||||
bool Resolving; // set while include-resolving, to catch circular includes
|
||||
bool IncludesResolved;
|
||||
|
||||
StdStrBuf Script; // script
|
||||
std::vector<C4AulBCC> Code;
|
||||
std::vector<const char *> PosForCode;
|
||||
C4AulBCC * LastCode;
|
||||
C4ValueMapNames LocalNamed;
|
||||
C4Set<C4Property> LocalValues;
|
||||
friend class C4AulParse;
|
||||
friend class C4AulScriptFunc;
|
||||
friend class C4AulDebug;
|
||||
friend class C4DirectExecScript;
|
||||
};
|
||||
|
||||
// script host for System.ocg scripts
|
||||
|
@ -84,7 +97,7 @@ class C4DefScriptHost: public C4ScriptHost
|
|||
public:
|
||||
C4DefScriptHost(C4Def * Def) : C4ScriptHost(), Def(Def) { }
|
||||
|
||||
virtual bool Load(C4Group &, const char *, const char *, C4LangStringTable *);
|
||||
virtual bool Parse();
|
||||
virtual C4PropList * GetPropList();
|
||||
protected:
|
||||
C4Def *Def; // owning def file
|
||||
|
@ -99,11 +112,11 @@ public:
|
|||
~C4GameScriptHost();
|
||||
virtual bool Load(C4Group &, const char *, const char *, C4LangStringTable *);
|
||||
void Clear();
|
||||
virtual C4PropList * GetPropList() { return ScenPrototype; }
|
||||
virtual C4PropList * GetPropList() { return ScenPrototype._getPropList(); }
|
||||
C4Value Call(const char *szFunction, C4AulParSet *pPars=0, bool fPassError=false);
|
||||
C4Value GRBroadcast(const char *szFunction, C4AulParSet *pPars = 0, bool fPassError=false, bool fRejectTest=false); // call function in scenario script and all goals/rules/environment objects
|
||||
C4PropList * ScenPropList;
|
||||
C4PropList * ScenPrototype;
|
||||
C4Value ScenPropList;
|
||||
C4Value ScenPrototype;
|
||||
};
|
||||
|
||||
extern C4GameScriptHost GameScript;
|
||||
|
|
|
@ -59,7 +59,7 @@ public:
|
|||
template <class U> C4RefCntPointer(const C4RefCntPointer<U> & r): p(r.p) { IncRef(); }
|
||||
#ifdef HAVE_RVALUE_REF
|
||||
// Move constructor
|
||||
template <class U> C4RefCntPointer(const C4RefCntPointer<U> RREF r): p(r.p) { r.p = 0; }
|
||||
template <class U> C4RefCntPointer(C4RefCntPointer<U> RREF r): p(r.p) { r.p = 0; }
|
||||
// Move assignment
|
||||
template <class U> C4RefCntPointer& operator = (C4RefCntPointer<U> RREF r)
|
||||
{
|
||||
|
@ -215,6 +215,18 @@ public:
|
|||
}
|
||||
return 0;
|
||||
}
|
||||
void Swap(C4Set<T> * S2)
|
||||
{
|
||||
unsigned int Capacity2 = S2->Capacity;
|
||||
unsigned int Size2 = S2->Size;
|
||||
T * Table2 = S2->Table;
|
||||
S2->Capacity = Capacity;
|
||||
S2->Size = Size;
|
||||
S2->Table = Table;
|
||||
Capacity = Capacity2;
|
||||
Size = Size2;
|
||||
Table = Table2;
|
||||
}
|
||||
};
|
||||
|
||||
template<> template<>
|
||||
|
|
|
@ -136,17 +136,14 @@ StdStrBuf C4Value::GetDataString(int depth) const
|
|||
{
|
||||
if (Data.PropList == ScriptEngine.GetPropList())
|
||||
return StdStrBuf("Global");
|
||||
C4Object * Obj = Data.PropList->GetObject();
|
||||
if (Obj == Data.PropList)
|
||||
return FormatString("Object(%d)", Obj->Number);
|
||||
const C4PropListStatic * Def = Data.PropList->IsStatic();
|
||||
if (Def)
|
||||
return Def->GetDataString();
|
||||
StdStrBuf DataString;
|
||||
DataString = "{";
|
||||
if (Data.PropList->GetObject())
|
||||
{
|
||||
if (Data.PropList->GetObject()->Status == C4OS_NORMAL)
|
||||
DataString.AppendFormat("#%d, ", Data.PropList->GetObject()->Number);
|
||||
else
|
||||
DataString.AppendFormat("(#%d), ", Data.PropList->GetObject()->Number);
|
||||
}
|
||||
else if (Data.PropList->GetDef())
|
||||
DataString.AppendFormat("%s, ", Data.PropList->GetDef()->id.ToString());
|
||||
Data.PropList->AppendDataString(&DataString, ", ", depth);
|
||||
DataString.AppendChar('}');
|
||||
return DataString;
|
||||
|
@ -210,7 +207,7 @@ void C4Value::Denumerate(class C4ValueNumbers * numbers)
|
|||
Data.Array->Denumerate(numbers); break;
|
||||
case C4V_PropList:
|
||||
// objects and effects are denumerated via the main object list
|
||||
if (!Data.PropList->IsNumbered() && !Data.PropList->IsDef())
|
||||
if (!Data.PropList->IsNumbered() && !Data.PropList->IsStatic())
|
||||
Data.PropList->Denumerate(numbers);
|
||||
break;
|
||||
case C4V_C4ObjectEnum:
|
||||
|
@ -266,23 +263,17 @@ void C4Value::CompileFunc(StdCompiler *pComp, C4ValueNumbers * numbers)
|
|||
case C4V_Bool:
|
||||
cC4VID = 'b'; break;
|
||||
case C4V_PropList:
|
||||
if (getPropList()->IsDef())
|
||||
if (getPropList()->IsStatic())
|
||||
cC4VID = 'D';
|
||||
else if (getPropList()->IsNumbered())
|
||||
cC4VID = 'O';
|
||||
else if (getPropList() == GameScript.ScenPropList)
|
||||
cC4VID = 'c';
|
||||
else if (getPropList() == GameScript.ScenPrototype)
|
||||
cC4VID = 't';
|
||||
else if (getPropList() == ScriptEngine.GetPropList())
|
||||
cC4VID = 'g';
|
||||
else
|
||||
cC4VID = 'E';
|
||||
break;
|
||||
case C4V_Array:
|
||||
cC4VID = 'E'; break;
|
||||
case C4V_Function:
|
||||
cC4VID = 'f'; break;
|
||||
cC4VID = 'D'; break;
|
||||
case C4V_String:
|
||||
cC4VID = 's'; break;
|
||||
default:
|
||||
|
@ -330,21 +321,38 @@ void C4Value::CompileFunc(StdCompiler *pComp, C4ValueNumbers * numbers)
|
|||
|
||||
case 'D':
|
||||
{
|
||||
C4ID id;
|
||||
if (!fCompiler)
|
||||
id = getPropList()->GetDef()->id;
|
||||
pComp->Value(id);
|
||||
if (fCompiler)
|
||||
if (!pComp->isCompiler())
|
||||
{
|
||||
C4PropList * p = Definitions.ID2Def(id);
|
||||
if (!p)
|
||||
C4PropList * p = getPropList();
|
||||
if (getFunction())
|
||||
{
|
||||
Set0();
|
||||
pComp->Warn("ERROR: Definition %s is missing.", id.ToString());
|
||||
p = Data.Fn->Owner->GetPropList();
|
||||
assert(p);
|
||||
assert(p->GetFunc(Data.Fn->GetName()) == Data.Fn);
|
||||
assert(p->IsStatic());
|
||||
}
|
||||
else
|
||||
p->IsStatic()->RefCompileFunc(pComp, numbers);
|
||||
if (getFunction())
|
||||
{
|
||||
SetPropList(p);
|
||||
pComp->Separator(StdCompiler::SEP_PART);
|
||||
StdStrBuf s; s.Ref(Data.Fn->GetName());
|
||||
pComp->Value(mkParAdapt(s, StdCompiler::RCT_ID));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
StdStrBuf s;
|
||||
pComp->Value(mkParAdapt(s, StdCompiler::RCT_ID));
|
||||
if (!::ScriptEngine.GetGlobalConstant(s.getData(), this))
|
||||
pComp->excNotFound("static proplist %s", s.getData());
|
||||
while(pComp->Separator(StdCompiler::SEP_PART))
|
||||
{
|
||||
C4PropList * p = getPropList();
|
||||
if (!p)
|
||||
pComp->excNotFound("static proplist is not a proplist anymore", s.getData());
|
||||
pComp->Value(mkParAdapt(s, StdCompiler::RCT_ID));
|
||||
if (!p->GetPropertyByS(::Strings.RegString(s), this))
|
||||
pComp->excNotFound("static proplist %s", s.getData());
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -361,14 +369,15 @@ void C4Value::CompileFunc(StdCompiler *pComp, C4ValueNumbers * numbers)
|
|||
break;
|
||||
}
|
||||
|
||||
// FIXME: remove these three once Game.txt were re-saved with current version
|
||||
case 'c':
|
||||
if (fCompiler)
|
||||
SetPropList(GameScript.ScenPropList);
|
||||
Set(GameScript.ScenPropList);
|
||||
break;
|
||||
|
||||
case 't':
|
||||
if (fCompiler)
|
||||
SetPropList(GameScript.ScenPrototype);
|
||||
Set(GameScript.ScenPrototype);
|
||||
break;
|
||||
|
||||
case 'g':
|
||||
|
@ -383,34 +392,6 @@ void C4Value::CompileFunc(StdCompiler *pComp, C4ValueNumbers * numbers)
|
|||
// doesn't have a value, so nothing to store
|
||||
break;
|
||||
|
||||
case 'f':
|
||||
{
|
||||
C4Value Owner;
|
||||
if (!fCompiler)
|
||||
{
|
||||
Owner.SetPropList(Data.Fn->Owner->GetPropList());
|
||||
assert(Owner._getPropList() && Owner._getPropList()->GetFunc(Data.Fn->GetName()) == Data.Fn);
|
||||
}
|
||||
pComp->Value(mkParAdapt(Owner, numbers));
|
||||
pComp->Separator(StdCompiler::SEP_PART);
|
||||
StdStrBuf s;
|
||||
if (!fCompiler)
|
||||
s = Data.Fn->GetName();
|
||||
pComp->Value(s);
|
||||
if (fCompiler)
|
||||
{
|
||||
// Owner was a definition or singleton, so shouldn't have to be denumerated
|
||||
if (!Owner.getPropList())
|
||||
{
|
||||
Set0();
|
||||
pComp->Warn("ERROR: Owner of function %s is missing.", s.getData());
|
||||
}
|
||||
else
|
||||
SetFunction(Owner._getPropList()->GetFunc(s.getData()));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
// shouldn't happen
|
||||
pComp->excCorrupt("unknown C4Value type tag '%c'", cC4VID);
|
||||
|
@ -508,30 +489,20 @@ bool C4Value::operator == (const C4Value& Value2) const
|
|||
{
|
||||
case C4V_Nil:
|
||||
assert(!Data);
|
||||
return Value2.Type == Type;
|
||||
return Type == Value2.Type;
|
||||
case C4V_Int:
|
||||
case C4V_Bool:
|
||||
return (Value2.Type == C4V_Int || Value2.Type == C4V_Bool) &&
|
||||
Data == Value2.Data;
|
||||
Data.Int == Value2.Data.Int;
|
||||
case C4V_PropList:
|
||||
if (Value2.Type == C4V_PropList)
|
||||
{
|
||||
// Compare as equal if and only if the proplists are indistinguishable
|
||||
// If one or both are mutable, they have to be the same
|
||||
// otherwise, they have to have the same contents
|
||||
if (Data.PropList == Value2.Data.PropList) return true;
|
||||
if (!Data.PropList->IsFrozen() || !Value2.Data.PropList->IsFrozen()) return false;
|
||||
return (*Data.PropList == *Value2.Data.PropList);
|
||||
}
|
||||
return false;
|
||||
return Type == Value2.Type && *Data.PropList == *Value2.Data.PropList;
|
||||
case C4V_String:
|
||||
return Type == Value2.Type && Data.Str == Value2.Data.Str;
|
||||
case C4V_Array:
|
||||
return Type == Value2.Type &&
|
||||
(Data.Array == Value2.Data.Array || *(Data.Array) == *(Value2.Data.Array));
|
||||
case C4V_Function:
|
||||
return Type == Value2.Type &&
|
||||
Data == Value2.Data;
|
||||
return Type == Value2.Type && Data.Fn == Value2.Data.Fn;
|
||||
default:
|
||||
assert(!"Unexpected C4Value type (denumeration missing?)");
|
||||
return Data == Value2.Data;
|
||||
|
|
|
@ -208,8 +208,6 @@ protected:
|
|||
// data type
|
||||
C4V_Type Type;
|
||||
|
||||
C4Value(C4V_Data nData, C4V_Type nType): Data(nData), NextRef(NULL)
|
||||
{ Type = (nData || IsNullableType(nType) ? nType : C4V_Nil); AddDataRef(); }
|
||||
|
||||
void Set(C4V_Data nData, C4V_Type nType);
|
||||
|
||||
|
|