Split C4Script.cpp into game functions and C4Script support functions

floating-point
Günther Brammer 2011-03-04 13:49:41 +01:00
parent d82815087e
commit 111df0392c
7 changed files with 736 additions and 671 deletions

View File

@ -272,7 +272,7 @@ set(OC_CLONK_SOURCES
src/game/script/C4Effects.h
src/game/script/C4FindObject.cpp
src/game/script/C4FindObject.h
src/game/script/C4Script.cpp
src/game/script/C4GameScript.cpp
src/game/script/C4Script.h
src/game/script/C4TransferZone.cpp
src/game/script/C4TransferZone.h
@ -501,6 +501,7 @@ set(OC_CLONK_SOURCES
src/script/C4AulParse.cpp
src/script/C4PropList.cpp
src/script/C4PropList.h
src/script/C4Script.cpp
src/script/C4ScriptHost.cpp
src/script/C4ScriptHost.h
src/script/C4StringTable.cpp

View File

@ -290,7 +290,7 @@ src/game/script/C4Effect.cpp \
src/game/script/C4Effects.h \
src/game/script/C4FindObject.cpp \
src/game/script/C4FindObject.h \
src/game/script/C4Script.cpp \
src/game/script/C4GameScript.cpp \
src/game/script/C4Script.h \
src/game/script/C4TransferZone.cpp \
src/game/script/C4TransferZone.h \
@ -513,6 +513,7 @@ src/script/C4AulLink.cpp \
src/script/C4AulParse.cpp \
src/script/C4PropList.cpp \
src/script/C4PropList.h \
src/script/C4Script.cpp \
src/script/C4ScriptHost.cpp \
src/script/C4ScriptHost.h \
src/script/C4StringTable.cpp \

View File

@ -2249,7 +2249,9 @@ bool C4Game::InitGameFinal()
bool C4Game::InitScriptEngine()
{
// engine functions
InitFunctionMap(&ScriptEngine);
InitCoreFunctionMap(&ScriptEngine);
InitObjectFunctionMap(&ScriptEngine);
InitGameFunctionMap(&ScriptEngine);
// system functions: check if system group is open
if (!Application.OpenSystemGroup())

View File

@ -1,6 +1,6 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: t; c-basic-offset: 2 -*- */
/*
* OpenClonk, http://www.openclonk.org
*
* Copyright (c) 1998-2000, 2004, 2008 Matthes Bender
* Copyright (c) 2001-2008, 2010 Peter Wortmann
* Copyright (c) 2001-2010 Sven Eberhardt
@ -11,7 +11,6 @@
* Copyright (c) 2009-2010 Randrian
* Copyright (c) 2009-2010 Nicolas Hake
* Copyright (c) 2010 Benjamin Herr
*
* Copyright (c) 2001-2009, RedWolf Design GmbH, http://www.clonk.de
*
* Portions might be copyrighted by other authors who have contributed
@ -33,7 +32,6 @@
#include <C4Application.h>
#include <C4AulDefFunc.h>
#include <C4AulExec.h>
#include <C4Command.h>
#include <C4DefList.h>
#include <C4Console.h>
@ -48,135 +46,10 @@
#include <C4Player.h>
#include <C4PlayerList.h>
#include <C4PXS.h>
#include <C4Random.h>
#include <C4Texture.h>
#include <C4Weather.h>
#include <C4Version.h>
#include <C4Viewport.h>
//========================== Some Support Functions =======================================
const long MaxFnStringParLen=500;
static 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)
{
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 * cpType;
char szField[MaxFnStringParLen+1];
while (*cpFormat)
{
// Copy normal stuff
while (*cpFormat && (*cpFormat!='%'))
StringBuf.AppendChar(*cpFormat++);
// Field
if (*cpFormat=='%')
{
// Scan field type
for (cpType=cpFormat+1; *cpType && (*cpType=='.' || Inside(*cpType,'0','9')); cpType++) {}
// Copy field
SCopy(cpFormat,szField,cpType-cpFormat+1);
// Insert field by type
switch (*cpType)
{
// number
case 'd': case 'x': case 'X': case 'c':
{
if (!Par[cPar]) throw new C4AulExecError(cthr->Obj, "format placeholder without parameter");
StringBuf.AppendFormat(szField, Par[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();
StringBuf.Append(id.ToString());
cpFormat+=SLen(szField);
break;
}
// C4Value
case 'v':
{
if (!Par[cPar]) throw new C4AulExecError(cthr->Obj, "format placeholder without parameter");
StringBuf.Append(static_cast<const StdStrBuf&>(Par[cPar++]->GetDataString()));
cpFormat+=SLen(szField);
break;
}
// String
case 's':
{
// get string
if (!Par[cPar]) throw new C4AulExecError(cthr->Obj, "format placeholder without parameter");
const char *szStr = "(null)";
if (Par[cPar]->GetData())
{
C4String * pStr = Par[cPar++]->getStr();
if (!pStr) throw new C4AulExecError(cthr->Obj, "string format placeholder without string");
szStr = pStr->GetCStr();
}
StringBuf.AppendFormat(szField, szStr);
cpFormat+=SLen(szField);
break;
}
case '%':
StringBuf.AppendChar('%');
cpFormat+=SLen(szField);
break;
// Undefined / Empty
default:
StringBuf.AppendChar('%');
cpFormat++;
break;
}
}
}
return StringBuf;
}
bool C4ValueToMatrix(C4Value& value, StdMeshMatrix* matrix)
{
//if(value.GetType() != C4V_Array) return false;
const C4ValueArray* array = value.getArray();
if (!array) return false;
return C4ValueToMatrix(*array, matrix);
}
bool C4ValueToMatrix(const C4ValueArray& array, StdMeshMatrix* matrix)
{
if (array.GetSize() != 12) return false;
StdMeshMatrix& trans = *matrix;
trans(0,0) = array[0].getInt()/1000.0f;
trans(0,1) = array[1].getInt()/1000.0f;
trans(0,2) = array[2].getInt()/1000.0f;
trans(0,3) = array[3].getInt()/1000.0f;
trans(1,0) = array[4].getInt()/1000.0f;
trans(1,1) = array[5].getInt()/1000.0f;
trans(1,2) = array[6].getInt()/1000.0f;
trans(1,3) = array[7].getInt()/1000.0f;
trans(2,0) = array[8].getInt()/1000.0f;
trans(2,1) = array[9].getInt()/1000.0f;
trans(2,2) = array[10].getInt()/1000.0f;
trans(2,3) = array[11].getInt()/1000.0f;
return true;
}
//=============================== C4Script Functions ====================================
static C4Object *Fn_this(C4AulContext *cthr)
{
return cthr->Obj;
}
static C4Void Fn_goto(C4AulContext *cthr, long iCounter)
{
@ -228,53 +101,6 @@ static C4Value FnPlayerObjectCommand(C4AulContext *cthr, C4Value *pPars)
return C4VTrue;
}
static C4PropList * FnCreatePropList(C4AulContext *cthr, C4PropList * prototype)
{
return C4PropList::New(prototype);
}
static C4Value FnGetProperty_C4V(C4AulContext *cthr, C4Value * key_C4V, C4Value * pObj_C4V)
{
C4PropList * pObj = pObj_C4V->_getPropList();
if (!pObj) pObj=cthr->Obj;
if (!pObj) pObj=cthr->Def;
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)
{
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->IsFrozen())
throw new C4AulExecError(cthr->Obj, "proplist write: proplist is readonly");
pObj->SetPropertyByS(key, *to);
return C4VTrue;
}
static C4Value FnResetProperty_C4V(C4AulContext *cthr, C4Value * key_C4V, C4Value * pObj_C4V)
{
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->IsFrozen())
throw new C4AulExecError(cthr->Obj, "proplist write: proplist is readonly");
pObj->ResetProperty(key);
return C4VTrue;
}
static C4String *FnGetPlayerName(C4AulContext *cthr, long iPlayer)
{
if (!ValidPlr(iPlayer)) return NULL;
@ -670,28 +496,6 @@ static bool FnGainMissionAccess(C4AulContext *cthr, C4String *szPassword)
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)
{
Log(FnStringFormat(cthr, FnStringPar(szMessage->getStr()),iPar0,iPar1,iPar2,iPar3,iPar4,iPar5,iPar6,iPar7,iPar8).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)
{
DebugLog(FnStringFormat(cthr, FnStringPar(szMessage->getStr()),iPar0,iPar1,iPar2,iPar3,iPar4,iPar5,iPar6,iPar7,iPar8).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)
{
return C4VString(FnStringFormat(cthr, FnStringPar(szFormat->getStr()),iPar0,iPar1,iPar2,iPar3,iPar4,iPar5,iPar6,iPar7,iPar8));
}
static C4ID FnC4Id(C4AulContext *cthr, C4String *szID)
{
return(C4ID(FnStringPar(szID)));
}
static C4Value FnPlayerMessage_C4V(C4AulContext *cthr, C4Value * iPlayer, C4Value *c4vMessage, C4Value * iPar0, C4Value * iPar1, C4Value * iPar2, C4Value * iPar3, C4Value * iPar4, C4Value * iPar5, C4Value * iPar6, C4Value * iPar7)
{
if (!cthr->Obj) throw new NeedObjectContext("PlayerMessage");
@ -1277,136 +1081,12 @@ static C4ValueArray* FnPathFree2(C4AulContext *cthr, int32_t x1, int32_t y1, int
return 0;
}
static long FnAbs(C4AulContext *cthr, long iVal)
{
return Abs(iVal);
}
static long FnSin(C4AulContext *cthr, long iAngle, long iRadius, long iPrec)
{
if (!iPrec) iPrec = 1;
// Precalculate the modulo operation so the C4Fixed argument to Sin does not overflow
iAngle %= 360 * iPrec;
// Let itofix and fixtoi handle the division and multiplication because that can handle higher ranges
return fixtoi(Sin(itofix(iAngle, iPrec)), iRadius);
}
static long FnCos(C4AulContext *cthr, 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)
{
if (iValue<0) return 0;
long iSqrt = long(sqrt(double(iValue)));
if (iSqrt * iSqrt < iValue) iSqrt++;
if (iSqrt * iSqrt > iValue) iSqrt--;
return iSqrt;
}
static long FnAngle(C4AulContext *cthr, long iX1, long iY1, long iX2, long iY2, long iPrec)
{
long iAngle;
// Standard prec
if (!iPrec) iPrec = 1;
long dx=iX2-iX1,dy=iY2-iY1;
if (!dx)
{
if (dy>0) return 180 * iPrec;
else return 0;
}
if (!dy)
{
if (dx>0) return 90 * iPrec;
else return 270 * iPrec;
}
iAngle = static_cast<long>(180.0 * iPrec * atan2(static_cast<double>(Abs(dy)), static_cast<double>(Abs(dx))) / M_PI);
if (iX2>iX1 )
{
if (iY2<iY1) iAngle = (90 * iPrec) - iAngle;
else iAngle = (90 * iPrec) + iAngle;
}
else
{
if (iY2<iY1) iAngle = (270 * iPrec) + iAngle;
else iAngle = (270 * iPrec) - iAngle;
}
return iAngle;
}
static long FnArcSin(C4AulContext *cthr, long iVal, long iRadius)
{
// safety
if (!iRadius) return 0;
if (iVal > iRadius) return 0;
// calc arcsin
double f1 = iVal;
f1 = asin(f1/iRadius)*180.0/M_PI;
// return rounded angle
return (long) floor(f1+0.5);
}
static long FnArcCos(C4AulContext *cthr, long iVal, long iRadius)
{
// safety
if (!iRadius) return 0;
if (iVal > iRadius) return 0;
// calc arccos
double f1 = iVal;
f1 = acos(f1/iRadius)*180.0/M_PI;
// return rounded angle
return (long) floor(f1+0.5);
}
static long FnMin(C4AulContext *cthr, long iVal1, long iVal2)
{
return Min(iVal1,iVal2);
}
static long FnMax(C4AulContext *cthr, long iVal1, long iVal2)
{
return Max(iVal1,iVal2);
}
static long FnDistance(C4AulContext *cthr, long iX1, long iY1, long iX2, long iY2)
{
return Distance(iX1,iY1,iX2,iY2);
}
C4Object* FnObject(C4AulContext *cthr, long iNumber)
{
return ::Objects.SafeObjectPointer(iNumber);
// See FnObjectNumber
}
static long FnBoundBy(C4AulContext *cthr, long iVal, long iRange1, long iRange2)
{
return BoundBy(iVal,iRange1,iRange2);
}
static bool FnInside(C4AulContext *cthr, long iVal, long iRange1, long iRange2)
{
return Inside(iVal,iRange1,iRange2);
}
static long FnRandom(C4AulContext *cthr, long iRange)
{
return Random(iRange);
}
static long FnAsyncRandom(C4AulContext *cthr, long iRange)
{
return SafeRandom(iRange);
}
static C4Value FnCall_C4V(C4AulContext *cthr, C4Value* szFunction_C4V,
C4Value* par0, C4Value* par1, C4Value* par2, C4Value* par3, C4Value* par4,
C4Value* par5, C4Value* par6, C4Value* par7, C4Value* par8/*, C4Value* par9*/)
@ -1609,61 +1289,6 @@ static long FnSetMaxPlayer(C4AulContext *cthr, long iTo)
return true;
}
static C4Value FnGetType(C4AulContext *cthr, C4Value* Value)
{
return C4VInt(Value->GetType());
}
static C4ValueArray * FnCreateArray(C4AulContext *cthr, int iSize)
{
return new C4ValueArray(iSize);
}
static C4Value FnGetLength(C4AulContext *cthr, C4Value *pPars)
{
// support GetLength() etc.
if (!pPars[0]) return C4VNull;
C4ValueArray * pArray = pPars->getArray();
if (pArray)
return C4VInt(pArray->GetSize());
C4String * pStr = pPars->getStr();
if (pStr)
return C4VInt(pStr->GetData().getLength());
throw new C4AulExecError(cthr->Obj, "func \"GetLength\" par 0 cannot be converted to string or array");
}
static C4Value FnGetIndexOf(C4AulContext *cthr, C4Value *pPars)
{
// find first occurance of first parameter in array
// support GetIndexOf(x, 0)
if (!pPars[1]) return C4VInt(-1);
// if the second param is nonzero, it must be an array
const C4ValueArray * pArray = pPars[1].getArray();
if (!pArray)
throw new C4AulExecError(cthr->Obj, "func \"GetIndexOf\" par 1 cannot be converted to array");
// find the element by comparing data only - this may result in bogus results if an object ptr array is searched for an int
// however, that's rather unlikely and strange scripting style
int32_t iSize = pArray->GetSize();
long cmp = pPars[0].GetData().Int;
for (int32_t i = 0; i<iSize; ++i)
if (cmp == pArray->GetItem(i).GetData().Int)
// element found
return C4VInt(i);
// element not found
return C4VInt(-1);
}
static C4Void FnSetLength(C4AulContext *cthr, C4ValueArray *pArray, int iNewSize)
{
// safety
if (iNewSize<0 || iNewSize > C4ValueArray::MaxSize)
throw new C4AulExecError(cthr->Obj, FormatString("SetLength: invalid array size (%d)", iNewSize).getData());
// set new size
pArray->SetSize(iNewSize);
return C4Void();
}
static bool FnGetMissionAccess(C4AulContext *cthr, C4String *strMissionAccess)
{
// safety
@ -1948,17 +1573,6 @@ static C4Value FnGetMaterialVal(C4AulContext* cthr, C4Value* strEntry_C4V, C4Val
return GetValByStdCompiler(strEntry, NULL, iEntryNr, *pMaterialCore);
}
static long FnGetChar(C4AulContext* cthr, C4String *pString, long iIndex)
{
const char *szText = FnStringPar(pString);
if (!szText) return 0;
// loop and check for end of string
for (int i=0; i<iIndex; i++, szText++)
if (!*szText) return 0;
// return indiced character value
return (unsigned char) *szText;
}
static C4String *FnMaterialName(C4AulContext* cthr, long iMat)
{
// mat valid?
@ -1976,80 +1590,6 @@ static C4String *FnGetNeededMatStr(C4AulContext* cthr, C4Object *pObj)
return String(pObj->GetNeededMatStr(cthr->Obj).getData());
}
static C4Value FnEval(C4AulContext *cthr, C4Value *strScript_C4V)
{
// execute script in the same object
enum C4AulScript::Strict Strict = C4AulScript::MAXSTRICT;
if (cthr->Obj)
return cthr->Obj->Def->Script.DirectExec(cthr->Obj, FnStringPar(strScript_C4V->getStr()), "eval", true, Strict);
else if (cthr->Def)
return cthr->Def->Script.DirectExec(0, FnStringPar(strScript_C4V->getStr()), "eval", true, Strict);
else
return ::GameScript.DirectExec(0, FnStringPar(strScript_C4V->getStr()), "eval", true, Strict);
}
static bool FnLocateFunc(C4AulContext *cthr, C4String *funcname, C4Object *pObj, C4ID idDef)
{
// safety
if (!funcname || !funcname->GetCStr())
{
Log("No func name");
return false;
}
// determine script context
C4AulScript *pCheckScript;
if (pObj)
{
pCheckScript = &pObj->Def->Script;
}
else if (idDef)
{
C4Def *pDef = C4Id2Def(idDef);
if (!pDef) { Log("Invalid or unloaded def"); return false; }
pCheckScript = &pDef->Script;
}
else
{
if (!cthr || !cthr->Caller || !cthr->Caller->Func || !cthr->Caller->Func->Owner)
{
Log("No valid script context");
return false;
}
pCheckScript = cthr->Caller->Func->Owner;
}
// get function by name
C4AulFunc *pFunc = pCheckScript->GetFuncRecursive(funcname->GetCStr());
if (!pFunc)
{
LogF("Func %s not found", funcname->GetCStr());
}
else
{
const char *szPrefix = "";
while (pFunc)
{
C4AulScriptFunc *pSFunc = pFunc->SFunc();
if (!pSFunc)
{
LogF("%s%s (engine)", szPrefix, pFunc->Name);
}
else if (!pSFunc->pOrgScript)
{
LogF("%s%s (no owner)", szPrefix, pSFunc->Name);
}
else
{
int32_t iLine = SGetLine(pSFunc->pOrgScript->GetScript(), pSFunc->Script);
LogF("%s%s (%s:%d)", szPrefix, pFunc->Name, pSFunc->pOrgScript->ScriptName.getData(), (int)iLine);
}
// next func in overload chain
pFunc = pSFunc ? pSFunc->OwnerOverloaded : NULL;
szPrefix = "overloads ";
}
}
return true;
}
static bool FnSetSkyAdjust(C4AulContext* cthr, long dwAdjust, long dwBackClr)
{
// set adjust
@ -2085,22 +1625,6 @@ static long FnGetTime(C4AulContext *)
return timeGetTime();
}
static long FnGetSystemTime(C4AulContext *cthr, long iWhat)
{
#ifdef _WIN32
// check network, record, etc
if (::Control.SyncMode()) return 0;
// check bounds
if (!Inside<long>(iWhat, 0, 7)) return 0;
SYSTEMTIME time;
GetLocalTime(&time);
// return queried value
return *(((WORD *) &time) + iWhat);
#else
return 0;
#endif
}
static C4Value FnSetPlrExtraData(C4AulContext *cthr, C4Value *iPlayer_C4V, C4Value *strDataName_C4V, C4Value *Data)
{
long iPlayer = iPlayer_C4V->getInt();
@ -2166,25 +1690,6 @@ static long FnDrawDefMap(C4AulContext *cctx, long iX, long iY, long iWdt, long i
return ::Landscape.DrawDefMap(iX, iY, iWdt, iHgt, FnStringPar(szMapDef));
}
struct C4ModLandscapeMatRec
{
long iMode, iClr1, iClr2;
};
DWORD FadeClr(DWORD dwClr1, DWORD dwClr2, BYTE byA1)
{
// darken colors and add them
DarkenClrBy(dwClr1, 255-byA1); DarkenClrBy(dwClr2, byA1);
return dwClr1+dwClr2;
}
void SmoothChars(signed char &r1, signed char &r2)
{
// lower the difference between two numbers
signed char d=(r2-r1)/4;
r1+=d; r2-=d;
}
static bool FnCreateParticle(C4AulContext *cthr, C4String *szName, long iX, long iY, long iXDir, long iYDir, long a, long b, C4Object *pObj, bool fBack)
{
// safety
@ -2564,27 +2069,6 @@ static C4Value FnEffectCall_C4V(C4AulContext *ctx, C4Value *pvpTarget, C4Value *
return pEffect->DoCall(pTarget, szCallFn, *pvVal1, *pvVal2, *pvVal3, *pvVal4, *pvVal5, *pvVal6, *pvVal7);
}
static long FnModulateColor(C4AulContext *cthr, long iClr1, long iClr2)
{
DWORD dwClr1 = iClr1;
DWORD dwClr2 = iClr2;
// default color
if (!dwClr1) dwClr1 = 0xffffff;
// get alpha
long iA1=dwClr1>>24, iA2=dwClr2>>24;
// modulate color values; mod alpha upwards
DWORD r = (((dwClr1 & 0xff) * (dwClr2 & 0xff)) >> 8) | // blue
(((dwClr1>> 8 & 0xff) * (dwClr2>>8 & 0xff)) & 0xff00) | // green
(((dwClr1>>16 & 0xff) * (dwClr2>>8 & 0xff00)) & 0xff0000) | // red
(Min<long>(iA1+iA2 - ((iA1*iA2)>>8), 255) << 24); // alpha
return r;
}
static long FnWildcardMatch(C4AulContext *ctx, C4String *psString, C4String *psWildcard)
{
return SWildcardMatchEx(FnStringPar(psString), FnStringPar(psWildcard));
}
static bool FnSetViewOffset(C4AulContext *ctx, long iPlayer, long iX, long iY)
{
if (!ValidPlr(iPlayer)) return 0;
@ -2794,11 +2278,6 @@ static long FnActivateGameGoalMenu(C4AulContext *ctx, long iPlayer)
return pPlr->Menu.ActivateGoals(pPlr->Number, pPlr->LocalControl && !::Control.isReplay());
}
static bool FnFatalError(C4AulContext *ctx, C4String *pErrorMsg)
{
throw new C4AulExecError(ctx->Obj, FormatString("script: %s", pErrorMsg ? pErrorMsg->GetCStr() : "(no error)").getData());
}
static bool FnPlayVideo(C4AulContext *ctx, C4String *pFilename)
{
// filename must be valid
@ -2807,36 +2286,6 @@ static bool FnPlayVideo(C4AulContext *ctx, C4String *pFilename)
return Game.VideoPlayer.PlayVideo(pFilename->GetCStr());
}
static bool FnStartCallTrace(C4AulContext *ctx)
{
extern void C4AulStartTrace();
C4AulStartTrace();
return true;
}
static bool FnStartScriptProfiler(C4AulContext *ctx, C4ID idScript)
{
// get script to profile
C4AulScript *pScript;
if (idScript)
{
C4Def *pDef = C4Id2Def(idScript);
if (!pDef) return false;
pScript = &pDef->Script;
}
else
pScript = &::ScriptEngine;
// profile it
C4AulProfiler::StartProfiling(pScript);
return true;
}
static bool FnStopScriptProfiler(C4AulContext *ctx)
{
C4AulProfiler::StopProfiling();
return true;
}
static bool FnCustomMessage(C4AulContext *ctx, C4String *pMsg, C4Object *pObj, long iOwner, long iOffX, long iOffY, long dwClr, C4ID idDeco, C4String *sPortrait, long dwFlags, long iHSize)
{
// safeties
@ -2878,30 +2327,6 @@ static bool FnCustomMessage(C4AulContext *ctx, C4String *pMsg, C4Object *pObj, l
return ::Messages.New(iType,sMsg,pObj,iOwner,iOffX,iOffY,(uint32_t)dwClr, idDeco, sPortrait ? sPortrait->GetCStr() : NULL, dwFlags, iHSize);
}
static C4String *FnTranslate(C4AulContext *ctx, C4String *text)
{
assert(!ctx->Obj || ctx->Def == ctx->Obj->Def);
if (!text || text->GetData().isNull()) return NULL;
// Find correct script: containing script unless -> operator used
C4AulScript *script = NULL;
if (ctx->Obj == ctx->Caller->Obj && ctx->Def == ctx->Caller->Def)
script = ctx->Caller->Func->pOrgScript;
else
script = &ctx->Def->Script;
assert(script);
try
{
return ::Strings.RegString(script->Translate(text->GetCStr()).c_str());
}
catch (C4LangStringTable::NoSuchTranslation &)
{
DebugLogF("WARNING: Translate: no translation for string \"%s\"", text->GetCStr());
// Trace
AulExec.LogCallStack();
return text;
}
}
/*static long FnSetSaturation(C4AulContext *ctx, long s)
{
return lpDDraw->SetSaturation(BoundBy(s,0l,255l));
@ -3022,55 +2447,21 @@ static bool FnGetPlayerControlEnabled(C4AulContext *ctx, long iplr, long ctrl)
return !plrctrl->IsControlDisabled(ctrl);
}
static Nillable<C4String *> FnGetConstantNameByValue(C4AulContext *ctx, int value, Nillable<C4String *> name_prefix, int idx)
extern C4ScriptConstDef C4ScriptGameConstMap[];
extern C4ScriptFnDef C4ScriptGameFnMap[];
void InitGameFunctionMap(C4AulScriptEngine *pEngine)
{
C4String *name_prefix_s = name_prefix;
// find a constant that has the specified value and prefix
for (int32_t i = 0; i < ::ScriptEngine.GlobalConsts.GetAnzItems(); ++i)
{
if (::ScriptEngine.GlobalConsts[i].getInt() == value)
{
const char *const_name = ::ScriptEngine.GlobalConstNames.GetItemUnsafe(i);
if (!name_prefix_s || SEqual2(const_name, name_prefix_s->GetCStr()))
if (!idx--)
// indexed constant found. return name minus prefix
return String(const_name + (name_prefix_s ? name_prefix_s->GetData().getLength() : 0));
}
}
// nothing found (at index)
return C4Void();
}
//=========================== C4Script Function Map ===================================
extern void InitObjectFunctionMap(C4AulScriptEngine *pEngine);
void InitFunctionMap(C4AulScriptEngine *pEngine)
{
InitObjectFunctionMap(pEngine);
// add all def constants (all Int)
for (C4ScriptConstDef *pCDef = &C4ScriptConstMap[0]; pCDef->Identifier; pCDef++)
for (C4ScriptConstDef *pCDef = &C4ScriptGameConstMap[0]; pCDef->Identifier; pCDef++)
{
assert(pCDef->ValType == C4V_Int); // only int supported currently
pEngine->RegisterGlobalConstant(pCDef->Identifier, C4VInt(pCDef->Data));
}
// add all def script funcs
for (C4ScriptFnDef *pDef = &C4ScriptFnMap[0]; pDef->Identifier; pDef++)
for (C4ScriptFnDef *pDef = &C4ScriptGameFnMap[0]; pDef->Identifier; pDef++)
pEngine->AddFunc(pDef->Identifier, pDef);
// AddFunc(pEngine, "SetSaturation", FnSetSaturation); //public: 0
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);
AddFunc(pEngine, "Smoke", FnSmoke);
AddFunc(pEngine, "Bubble", FnBubble);
@ -3080,8 +2471,6 @@ void InitFunctionMap(C4AulScriptEngine *pEngine)
AddFunc(pEngine, "GetPlayerName", FnGetPlayerName);
AddFunc(pEngine, "GetPlayerType", FnGetPlayerType);
AddFunc(pEngine, "GetPlayerColor", FnGetPlayerColor);
AddFunc(pEngine, "CreateArray", FnCreateArray);
AddFunc(pEngine, "CreatePropList", FnCreatePropList);
AddFunc(pEngine, "CreateObject", FnCreateObject);
AddFunc(pEngine, "CreateConstruction", FnCreateConstruction);
AddFunc(pEngine, "FindConstructionSite", FnFindConstructionSite);
@ -3113,7 +2502,6 @@ void InitFunctionMap(C4AulScriptEngine *pEngine)
AddFunc(pEngine, "PlaceVegetation", FnPlaceVegetation);
AddFunc(pEngine, "PlaceAnimal", FnPlaceAnimal);
AddFunc(pEngine, "GameOver", FnGameOver);
AddFunc(pEngine, "C4Id", FnC4Id, false);
AddFunc(pEngine, "ScriptGo", FnScriptGo);
AddFunc(pEngine, "GetHiRank", FnGetHiRank);
AddFunc(pEngine, "GetCrew", FnGetCrew);
@ -3145,8 +2533,6 @@ void InitFunctionMap(C4AulScriptEngine *pEngine)
AddFunc(pEngine, "GetSeason", FnGetSeason);
AddFunc(pEngine, "SetClimate", FnSetClimate);
AddFunc(pEngine, "GetClimate", FnGetClimate);
AddFunc(pEngine, "Distance", FnDistance);
AddFunc(pEngine, "Angle", FnAngle);
AddFunc(pEngine, "SetPlayerZoomByViewRange", FnSetPlayerZoomByViewRange);
AddFunc(pEngine, "SetPlayerViewLock", FnSetPlayerViewLock);
AddFunc(pEngine, "DoHomebaseMaterial", FnDoHomebaseMaterial);
@ -3161,11 +2547,9 @@ void InitFunctionMap(C4AulScriptEngine *pEngine)
AddFunc(pEngine, "ScriptCounter", FnScriptCounter);
AddFunc(pEngine, "SetFoW", FnSetFoW);
AddFunc(pEngine, "SetMaxPlayer", FnSetMaxPlayer);
AddFunc(pEngine, "GetChar", FnGetChar);
AddFunc(pEngine, "ActivateGameGoalMenu", FnActivateGameGoalMenu);
AddFunc(pEngine, "Object", FnObject);
AddFunc(pEngine, "GetTime", FnGetTime);
AddFunc(pEngine, "GetSystemTime", FnGetSystemTime, false);
AddFunc(pEngine, "GetMissionAccess", FnGetMissionAccess);
AddFunc(pEngine, "MaterialName", FnMaterialName);
AddFunc(pEngine, "GetNeededMatStr", FnGetNeededMatStr);
@ -3203,8 +2587,6 @@ void InitFunctionMap(C4AulScriptEngine *pEngine)
AddFunc(pEngine, "FxFireInfo", FnFxFireInfo, false);
AddFunc(pEngine, "RemoveEffect", FnRemoveEffect);
AddFunc(pEngine, "GetEffect", FnGetEffect);
AddFunc(pEngine, "ModulateColor", FnModulateColor);
AddFunc(pEngine, "WildcardMatch", FnWildcardMatch);
AddFunc(pEngine, "SetViewOffset", FnSetViewOffset);
AddFunc(pEngine, "SetPreSend", FnSetPreSend, false);
AddFunc(pEngine, "GetPlayerID", FnGetPlayerID);
@ -3223,16 +2605,11 @@ void InitFunctionMap(C4AulScriptEngine *pEngine)
AddFunc(pEngine, "SortScoreboard", FnSortScoreboard);
AddFunc(pEngine, "AddEvaluationData", FnAddEvaluationData);
AddFunc(pEngine, "HideSettlementScoreInEvaluation", FnHideSettlementScoreInEvaluation);
AddFunc(pEngine, "FatalError", FnFatalError);
AddFunc(pEngine, "ExtractMaterialAmount", FnExtractMaterialAmount);
AddFunc(pEngine, "GetEffectCount", FnGetEffectCount);
AddFunc(pEngine, "PlayVideo", FnPlayVideo, false);
AddFunc(pEngine, "StartCallTrace", FnStartCallTrace);
AddFunc(pEngine, "StartScriptProfiler", FnStartScriptProfiler);
AddFunc(pEngine, "StopScriptProfiler", FnStopScriptProfiler);
AddFunc(pEngine, "CustomMessage", FnCustomMessage);
AddFunc(pEngine, "PauseGame", FnPauseGame, false);
AddFunc(pEngine, "LocateFunc", FnLocateFunc);
AddFunc(pEngine, "PathFree", FnPathFree);
AddFunc(pEngine, "PathFree2", FnPathFree2);
AddFunc(pEngine, "SetNextMission", FnSetNextMission);
@ -3241,33 +2618,14 @@ void InitFunctionMap(C4AulScriptEngine *pEngine)
AddFunc(pEngine, "GetPlayerControlEnabled", FnGetPlayerControlEnabled);
//FIXME new C4AulDefCastFunc(pEngine, "ScoreboardCol", C4V_C4ID, C4V_Int);
AddFunc(pEngine, "SetLength", FnSetLength);
AddFunc(pEngine, "goto", Fn_goto);
AddFunc(pEngine, "this", Fn_this);
AddFunc(pEngine, "IncinerateLandscape", FnIncinerateLandscape);
AddFunc(pEngine, "GetGravity", FnGetGravity);
AddFunc(pEngine, "SetGravity", FnSetGravity);
AddFunc(pEngine, "GetConstantNameByValue", FnGetConstantNameByValue, false);
AddFunc(pEngine, "Translate", FnTranslate);
}
C4ScriptConstDef C4ScriptConstMap[]=
C4ScriptConstDef C4ScriptGameConstMap[]=
{
{ "C4V_Any" ,C4V_Int, C4V_Any},
{ "C4V_Int" ,C4V_Int, C4V_Int},
{ "C4V_Bool" ,C4V_Int, C4V_Bool},
{ "C4V_C4Object" ,C4V_Int, C4V_C4Object},
{ "C4V_String" ,C4V_Int, C4V_String},
{ "C4V_Array" ,C4V_Int, C4V_Array},
{ "C4V_PropList" ,C4V_Int, C4V_PropList},
{ "C4X_Ver1" ,C4V_Int, C4XVER1},
{ "C4X_Ver2" ,C4V_Int, C4XVER2},
{ "C4X_Ver3" ,C4V_Int, C4XVER3},
{ "C4X_Ver4" ,C4V_Int, C4XVER4},
{ "SkyPar_Keep" ,C4V_Int, SkyPar_KEEP},
{ "FX_OK" ,C4V_Int, C4Fx_OK }, // generic standard behaviour for all effect callbacks
@ -3391,12 +2749,9 @@ C4ScriptConstDef C4ScriptConstMap[]=
#define MkFnC4V (C4Value (*)(C4AulContext *cthr, C4Value*, C4Value*, C4Value*, C4Value*, C4Value*,\
C4Value*, C4Value*, C4Value*, C4Value*, C4Value*))
C4ScriptFnDef C4ScriptFnMap[]=
C4ScriptFnDef C4ScriptGameFnMap[]=
{
{ "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 },
{ "PlayerObjectCommand", 1 ,C4V_Bool ,{ C4V_Int ,C4V_String ,C4V_C4Object,C4V_Any ,C4V_Int ,C4V_C4Object,C4V_Any ,C4V_Int ,C4V_Any ,C4V_Any} ,0 , FnPlayerObjectCommand },
{ "FindObject", 1 ,C4V_C4Object ,{ C4V_Array ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any} ,0 , FnFindObject },
{ "FindObjects", 1 ,C4V_Array ,{ C4V_Array ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any} ,0 , FnFindObjects },
@ -3412,18 +2767,10 @@ C4ScriptFnDef C4ScriptFnMap[]=
{ "PlayerMessage", 1 ,C4V_Int ,{ C4V_Int ,C4V_String ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any} ,MkFnC4V &FnPlayerMessage_C4V, 0 },
{ "Message", 1 ,C4V_Bool ,{ C4V_String ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any} ,MkFnC4V &FnMessage_C4V, 0 },
{ "AddMessage", 1 ,C4V_Bool ,{ C4V_String ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any} ,MkFnC4V &FnAddMessage_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 },
{ "EditCursor", 1 ,C4V_C4Object ,{ C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any} ,0 , FnEditCursor },
{ "GetHomebaseMaterial", 1 ,C4V_Int ,{ C4V_Int ,C4V_PropList,C4V_Int ,C4V_Int ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any} ,MkFnC4V FnGetHomebaseMaterial_C4V , 0 },
{ "GetHomebaseProduction",1 ,C4V_Int ,{ C4V_Int ,C4V_PropList,C4V_Int ,C4V_Int ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any} ,MkFnC4V FnGetHomebaseProduction_C4V , 0 },
{ "GetType", 1 ,C4V_Int ,{ C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any} ,MkFnC4V FnGetType, 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_Any ,C4V_Array ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any} ,0, FnGetIndexOf },
{ "GetDefCoreVal", 1 ,C4V_Any ,{ C4V_String ,C4V_String ,C4V_Int ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any} ,MkFnC4V FnGetDefCoreVal, 0 },
{ "GetObjectVal", 1 ,C4V_Any ,{ C4V_String ,C4V_String ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any} ,MkFnC4V FnGetObjectVal, 0 },
{ "GetObjectInfoCoreVal", 1 ,C4V_Any ,{ C4V_String ,C4V_String ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any} ,MkFnC4V FnGetObjectInfoCoreVal, 0 },
@ -3438,8 +2785,6 @@ C4ScriptFnDef C4ScriptFnMap[]=
{ "CheckEffect", 1 ,C4V_Int ,{ C4V_String ,C4V_C4Object,C4V_Int ,C4V_Int ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any} ,MkFnC4V FnCheckEffect_C4V, 0 },
{ "EffectCall", 1 ,C4V_Any ,{ C4V_C4Object,C4V_PropList,C4V_String ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any} ,MkFnC4V FnEffectCall_C4V, 0 },
{ "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_Any ,{ C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any} ,0, 0 }
};

View File

@ -63,10 +63,10 @@ struct C4ScriptFnDef
C4Value (*FunctionC4V2)(struct C4AulContext *, C4Value *);
};
extern C4ScriptConstDef C4ScriptConstMap[];
extern C4ScriptFnDef C4ScriptFnMap[];
void InitFunctionMap(C4AulScriptEngine *pEngine); // add functions to engine
// add functions to engine
void InitGameFunctionMap(C4AulScriptEngine *pEngine);
void InitObjectFunctionMap(C4AulScriptEngine *pEngine);
void InitCoreFunctionMap(C4AulScriptEngine *pEngine);
bool C4ValueToMatrix(C4Value& value, StdMeshMatrix* matrix);
bool C4ValueToMatrix(const C4ValueArray& array, StdMeshMatrix* matrix);

View File

@ -51,6 +51,9 @@ 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 };
// Allow parameters to be nil
template<typename T>

View File

@ -0,0 +1,713 @@
/*
* OpenClonk, http://www.openclonk.org
*
* Copyright (c) 1998-2000 Matthes Bender
* Copyright (c) 2004, 2006-2007, 2010 Sven Eberhardt
* Copyright (c) 2005-2011 Günther Brammer
* Copyright (c) 2005-2006 Peter Wortmann
* Copyright (c) 2009 Nicolas Hake
* Copyright (c) 2010 Benjamin Herr
* Copyright (c) 2010 Armin Burgmeier
* Copyright (c) 2001-2009, RedWolf Design GmbH, http://www.clonk.de
*
* 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.
*/
/* Functions mapped by C4Script */
#include <C4Include.h>
#include <C4AulDefFunc.h>
#include <C4AulExec.h>
#include <C4Random.h>
#include <C4Version.h>
//========================== 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)
{
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 * cpType;
char szField[MaxFnStringParLen+1];
while (*cpFormat)
{
// Copy normal stuff
while (*cpFormat && (*cpFormat!='%'))
StringBuf.AppendChar(*cpFormat++);
// Field
if (*cpFormat=='%')
{
// Scan field type
for (cpType=cpFormat+1; *cpType && (*cpType=='.' || Inside(*cpType,'0','9')); cpType++) {}
// Copy field
SCopy(cpFormat,szField,cpType-cpFormat+1);
// Insert field by type
switch (*cpType)
{
// number
case 'd': case 'x': case 'X': case 'c':
{
if (!Par[cPar]) throw new C4AulExecError(cthr->Obj, "format placeholder without parameter");
StringBuf.AppendFormat(szField, Par[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();
StringBuf.Append(id.ToString());
cpFormat+=SLen(szField);
break;
}
// C4Value
case 'v':
{
if (!Par[cPar]) throw new C4AulExecError(cthr->Obj, "format placeholder without parameter");
StringBuf.Append(static_cast<const StdStrBuf&>(Par[cPar++]->GetDataString()));
cpFormat+=SLen(szField);
break;
}
// String
case 's':
{
// get string
if (!Par[cPar]) throw new C4AulExecError(cthr->Obj, "format placeholder without parameter");
const char *szStr = "(null)";
if (Par[cPar]->GetData())
{
C4String * pStr = Par[cPar++]->getStr();
if (!pStr) throw new C4AulExecError(cthr->Obj, "string format placeholder without string");
szStr = pStr->GetCStr();
}
StringBuf.AppendFormat(szField, szStr);
cpFormat+=SLen(szField);
break;
}
case '%':
StringBuf.AppendChar('%');
cpFormat+=SLen(szField);
break;
// Undefined / Empty
default:
StringBuf.AppendChar('%');
cpFormat++;
break;
}
}
}
return StringBuf;
}
bool C4ValueToMatrix(C4Value& value, StdMeshMatrix* matrix)
{
//if(value.GetType() != C4V_Array) return false;
const C4ValueArray* array = value.getArray();
if (!array) return false;
return C4ValueToMatrix(*array, matrix);
}
bool C4ValueToMatrix(const C4ValueArray& array, StdMeshMatrix* matrix)
{
if (array.GetSize() != 12) return false;
StdMeshMatrix& trans = *matrix;
trans(0,0) = array[0].getInt()/1000.0f;
trans(0,1) = array[1].getInt()/1000.0f;
trans(0,2) = array[2].getInt()/1000.0f;
trans(0,3) = array[3].getInt()/1000.0f;
trans(1,0) = array[4].getInt()/1000.0f;
trans(1,1) = array[5].getInt()/1000.0f;
trans(1,2) = array[6].getInt()/1000.0f;
trans(1,3) = array[7].getInt()/1000.0f;
trans(2,0) = array[8].getInt()/1000.0f;
trans(2,1) = array[9].getInt()/1000.0f;
trans(2,2) = array[10].getInt()/1000.0f;
trans(2,3) = array[11].getInt()/1000.0f;
return true;
}
//=============================== C4Script Functions ====================================
static C4Object *Fn_this(C4AulContext *cthr)
{
return cthr->Obj;
}
static C4PropList * FnCreatePropList(C4AulContext *cthr, C4PropList * prototype)
{
return C4PropList::New(prototype);
}
static C4Value FnGetProperty_C4V(C4AulContext *cthr, C4Value * key_C4V, C4Value * pObj_C4V)
{
C4PropList * pObj = pObj_C4V->_getPropList();
if (!pObj) pObj=cthr->Obj;
if (!pObj) pObj=cthr->Def;
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)
{
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->IsFrozen())
throw new C4AulExecError(cthr->Obj, "proplist write: proplist is readonly");
pObj->SetPropertyByS(key, *to);
return C4VTrue;
}
static C4Value FnResetProperty_C4V(C4AulContext *cthr, C4Value * key_C4V, C4Value * pObj_C4V)
{
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->IsFrozen())
throw new C4AulExecError(cthr->Obj, "proplist write: proplist is readonly");
pObj->ResetProperty(key);
return C4VTrue;
}
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)
{
Log(FnStringFormat(cthr, FnStringPar(szMessage->getStr()),iPar0,iPar1,iPar2,iPar3,iPar4,iPar5,iPar6,iPar7,iPar8).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)
{
DebugLog(FnStringFormat(cthr, FnStringPar(szMessage->getStr()),iPar0,iPar1,iPar2,iPar3,iPar4,iPar5,iPar6,iPar7,iPar8).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)
{
return C4VString(FnStringFormat(cthr, FnStringPar(szFormat->getStr()),iPar0,iPar1,iPar2,iPar3,iPar4,iPar5,iPar6,iPar7,iPar8));
}
static C4ID FnC4Id(C4AulContext *cthr, C4String *szID)
{
return(C4ID(FnStringPar(szID)));
}
static long FnAbs(C4AulContext *cthr, long iVal)
{
return Abs(iVal);
}
static long FnSin(C4AulContext *cthr, long iAngle, long iRadius, long iPrec)
{
if (!iPrec) iPrec = 1;
// Precalculate the modulo operation so the C4Fixed argument to Sin does not overflow
iAngle %= 360 * iPrec;
// Let itofix and fixtoi handle the division and multiplication because that can handle higher ranges
return fixtoi(Sin(itofix(iAngle, iPrec)), iRadius);
}
static long FnCos(C4AulContext *cthr, 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)
{
if (iValue<0) return 0;
long iSqrt = long(sqrt(double(iValue)));
if (iSqrt * iSqrt < iValue) iSqrt++;
if (iSqrt * iSqrt > iValue) iSqrt--;
return iSqrt;
}
static long FnAngle(C4AulContext *cthr, long iX1, long iY1, long iX2, long iY2, long iPrec)
{
long iAngle;
// Standard prec
if (!iPrec) iPrec = 1;
long dx=iX2-iX1,dy=iY2-iY1;
if (!dx)
{
if (dy>0) return 180 * iPrec;
else return 0;
}
if (!dy)
{
if (dx>0) return 90 * iPrec;
else return 270 * iPrec;
}
iAngle = static_cast<long>(180.0 * iPrec * atan2(static_cast<double>(Abs(dy)), static_cast<double>(Abs(dx))) / M_PI);
if (iX2>iX1 )
{
if (iY2<iY1) iAngle = (90 * iPrec) - iAngle;
else iAngle = (90 * iPrec) + iAngle;
}
else
{
if (iY2<iY1) iAngle = (270 * iPrec) + iAngle;
else iAngle = (270 * iPrec) - iAngle;
}
return iAngle;
}
static long FnArcSin(C4AulContext *cthr, long iVal, long iRadius)
{
// safety
if (!iRadius) return 0;
if (iVal > iRadius) return 0;
// calc arcsin
double f1 = iVal;
f1 = asin(f1/iRadius)*180.0/M_PI;
// return rounded angle
return (long) floor(f1+0.5);
}
static long FnArcCos(C4AulContext *cthr, long iVal, long iRadius)
{
// safety
if (!iRadius) return 0;
if (iVal > iRadius) return 0;
// calc arccos
double f1 = iVal;
f1 = acos(f1/iRadius)*180.0/M_PI;
// return rounded angle
return (long) floor(f1+0.5);
}
static long FnMin(C4AulContext *cthr, long iVal1, long iVal2)
{
return Min(iVal1,iVal2);
}
static long FnMax(C4AulContext *cthr, long iVal1, long iVal2)
{
return Max(iVal1,iVal2);
}
static long FnDistance(C4AulContext *cthr, 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)
{
return BoundBy(iVal,iRange1,iRange2);
}
static bool FnInside(C4AulContext *cthr, long iVal, long iRange1, long iRange2)
{
return Inside(iVal,iRange1,iRange2);
}
static long FnRandom(C4AulContext *cthr, long iRange)
{
return Random(iRange);
}
static long FnAsyncRandom(C4AulContext *cthr, long iRange)
{
return SafeRandom(iRange);
}
static C4Value FnGetType(C4AulContext *cthr, C4Value* Value)
{
return C4VInt(Value->GetType());
}
static C4ValueArray * FnCreateArray(C4AulContext *cthr, int iSize)
{
return new C4ValueArray(iSize);
}
static C4Value FnGetLength(C4AulContext *cthr, C4Value *pPars)
{
// support GetLength() etc.
if (!pPars[0]) return C4VNull;
C4ValueArray * pArray = pPars->getArray();
if (pArray)
return C4VInt(pArray->GetSize());
C4String * pStr = pPars->getStr();
if (pStr)
return C4VInt(pStr->GetData().getLength());
throw new C4AulExecError(cthr->Obj, "func \"GetLength\" par 0 cannot be converted to string or array");
}
static C4Value FnGetIndexOf(C4AulContext *cthr, C4Value *pPars)
{
// find first occurance of first parameter in array
// support GetIndexOf(x, 0)
if (!pPars[1]) return C4VInt(-1);
// if the second param is nonzero, it must be an array
const C4ValueArray * pArray = pPars[1].getArray();
if (!pArray)
throw new C4AulExecError(cthr->Obj, "func \"GetIndexOf\" par 1 cannot be converted to array");
// find the element by comparing data only - this may result in bogus results if an object ptr array is searched for an int
// however, that's rather unlikely and strange scripting style
int32_t iSize = pArray->GetSize();
long cmp = pPars[0].GetData().Int;
for (int32_t i = 0; i<iSize; ++i)
if (cmp == pArray->GetItem(i).GetData().Int)
// element found
return C4VInt(i);
// element not found
return C4VInt(-1);
}
static C4Void FnSetLength(C4AulContext *cthr, C4ValueArray *pArray, int iNewSize)
{
// safety
if (iNewSize<0 || iNewSize > C4ValueArray::MaxSize)
throw new C4AulExecError(cthr->Obj, FormatString("SetLength: invalid array size (%d)", iNewSize).getData());
// set new size
pArray->SetSize(iNewSize);
return C4Void();
}
static long FnGetChar(C4AulContext* cthr, C4String *pString, long iIndex)
{
const char *szText = FnStringPar(pString);
if (!szText) return 0;
// loop and check for end of string
for (int i=0; i<iIndex; i++, szText++)
if (!*szText) return 0;
// return indiced character value
return (unsigned char) *szText;
}
static C4Value FnEval(C4AulContext *cthr, C4Value *strScript_C4V)
{
// execute script in the same object
enum C4AulScript::Strict Strict = C4AulScript::MAXSTRICT;
if (cthr->Obj)
return cthr->Obj->Def->Script.DirectExec(cthr->Obj, FnStringPar(strScript_C4V->getStr()), "eval", true, Strict);
else if (cthr->Def)
return cthr->Def->Script.DirectExec(0, FnStringPar(strScript_C4V->getStr()), "eval", true, Strict);
else
return ::GameScript.DirectExec(0, FnStringPar(strScript_C4V->getStr()), "eval", true, Strict);
}
static bool FnLocateFunc(C4AulContext *cthr, C4String *funcname, C4Object *pObj, C4ID idDef)
{
// safety
if (!funcname || !funcname->GetCStr())
{
Log("No func name");
return false;
}
// determine script context
C4AulScript *pCheckScript;
if (pObj)
{
pCheckScript = &pObj->Def->Script;
}
else if (idDef)
{
C4Def *pDef = C4Id2Def(idDef);
if (!pDef) { Log("Invalid or unloaded def"); return false; }
pCheckScript = &pDef->Script;
}
else
{
if (!cthr || !cthr->Caller || !cthr->Caller->Func || !cthr->Caller->Func->Owner)
{
Log("No valid script context");
return false;
}
pCheckScript = cthr->Caller->Func->Owner;
}
// get function by name
C4AulFunc *pFunc = pCheckScript->GetFuncRecursive(funcname->GetCStr());
if (!pFunc)
{
LogF("Func %s not found", funcname->GetCStr());
}
else
{
const char *szPrefix = "";
while (pFunc)
{
C4AulScriptFunc *pSFunc = pFunc->SFunc();
if (!pSFunc)
{
LogF("%s%s (engine)", szPrefix, pFunc->Name);
}
else if (!pSFunc->pOrgScript)
{
LogF("%s%s (no owner)", szPrefix, pSFunc->Name);
}
else
{
int32_t iLine = SGetLine(pSFunc->pOrgScript->GetScript(), pSFunc->Script);
LogF("%s%s (%s:%d)", szPrefix, pFunc->Name, pSFunc->pOrgScript->ScriptName.getData(), (int)iLine);
}
// next func in overload chain
pFunc = pSFunc ? pSFunc->OwnerOverloaded : NULL;
szPrefix = "overloads ";
}
}
return true;
}
static long FnGetSystemTime(C4AulContext *cthr, long iWhat)
{
#ifdef _WIN32
// check network, record, etc
if (::Control.SyncMode()) return 0;
// check bounds
if (!Inside<long>(iWhat, 0, 7)) return 0;
SYSTEMTIME time;
GetLocalTime(&time);
// return queried value
return *(((WORD *) &time) + iWhat);
#else
return 0;
#endif
}
struct C4ModLandscapeMatRec
{
long iMode, iClr1, iClr2;
};
static DWORD FadeClr(DWORD dwClr1, DWORD dwClr2, BYTE byA1)
{
// darken colors and add them
DarkenClrBy(dwClr1, 255-byA1); DarkenClrBy(dwClr2, byA1);
return dwClr1+dwClr2;
}
static void SmoothChars(signed char &r1, signed char &r2)
{
// lower the difference between two numbers
signed char d=(r2-r1)/4;
r1+=d; r2-=d;
}
static long FnModulateColor(C4AulContext *cthr, long iClr1, long iClr2)
{
DWORD dwClr1 = iClr1;
DWORD dwClr2 = iClr2;
// default color
if (!dwClr1) dwClr1 = 0xffffff;
// get alpha
long iA1=dwClr1>>24, iA2=dwClr2>>24;
// modulate color values; mod alpha upwards
DWORD r = (((dwClr1 & 0xff) * (dwClr2 & 0xff)) >> 8) | // blue
(((dwClr1>> 8 & 0xff) * (dwClr2>>8 & 0xff)) & 0xff00) | // green
(((dwClr1>>16 & 0xff) * (dwClr2>>8 & 0xff00)) & 0xff0000) | // red
(Min<long>(iA1+iA2 - ((iA1*iA2)>>8), 255) << 24); // alpha
return r;
}
static long FnWildcardMatch(C4AulContext *ctx, C4String *psString, C4String *psWildcard)
{
return SWildcardMatchEx(FnStringPar(psString), FnStringPar(psWildcard));
}
static bool FnFatalError(C4AulContext *ctx, C4String *pErrorMsg)
{
throw new C4AulExecError(ctx->Obj, FormatString("script: %s", pErrorMsg ? pErrorMsg->GetCStr() : "(no error)").getData());
}
static bool FnStartCallTrace(C4AulContext *ctx)
{
extern void C4AulStartTrace();
C4AulStartTrace();
return true;
}
static bool FnStartScriptProfiler(C4AulContext *ctx, C4ID idScript)
{
// get script to profile
C4AulScript *pScript;
if (idScript)
{
C4Def *pDef = C4Id2Def(idScript);
if (!pDef) return false;
pScript = &pDef->Script;
}
else
pScript = &::ScriptEngine;
// profile it
C4AulProfiler::StartProfiling(pScript);
return true;
}
static bool FnStopScriptProfiler(C4AulContext *ctx)
{
C4AulProfiler::StopProfiling();
return true;
}
static C4String *FnTranslate(C4AulContext *ctx, C4String *text)
{
assert(!ctx->Obj || ctx->Def == ctx->Obj->Def);
if (!text || text->GetData().isNull()) return NULL;
// Find correct script: containing script unless -> operator used
C4AulScript *script = NULL;
if (ctx->Obj == ctx->Caller->Obj && ctx->Def == ctx->Caller->Def)
script = ctx->Caller->Func->pOrgScript;
else
script = &ctx->Def->Script;
assert(script);
try
{
return ::Strings.RegString(script->Translate(text->GetCStr()).c_str());
}
catch (C4LangStringTable::NoSuchTranslation &)
{
DebugLogF("WARNING: Translate: no translation for string \"%s\"", text->GetCStr());
// Trace
AulExec.LogCallStack();
return text;
}
}
static Nillable<C4String *> FnGetConstantNameByValue(C4AulContext *ctx, int value, Nillable<C4String *> name_prefix, int idx)
{
C4String *name_prefix_s = name_prefix;
// find a constant that has the specified value and prefix
for (int32_t i = 0; i < ::ScriptEngine.GlobalConsts.GetAnzItems(); ++i)
{
if (::ScriptEngine.GlobalConsts[i].getInt() == value)
{
const char *const_name = ::ScriptEngine.GlobalConstNames.GetItemUnsafe(i);
if (!name_prefix_s || SEqual2(const_name, name_prefix_s->GetCStr()))
if (!idx--)
// indexed constant found. return name minus prefix
return String(const_name + (name_prefix_s ? name_prefix_s->GetData().getLength() : 0));
}
}
// nothing found (at index)
return C4Void();
}
//=========================== C4Script Function Map ===================================
C4ScriptConstDef C4ScriptConstMap[]=
{
{ "C4V_Any" ,C4V_Int, C4V_Any},
{ "C4V_Int" ,C4V_Int, C4V_Int},
{ "C4V_Bool" ,C4V_Int, C4V_Bool},
{ "C4V_C4Object" ,C4V_Int, C4V_C4Object},
{ "C4V_String" ,C4V_Int, C4V_String},
{ "C4V_Array" ,C4V_Int, C4V_Array},
{ "C4V_PropList" ,C4V_Int, C4V_PropList},
{ "C4X_Ver1" ,C4V_Int, C4XVER1},
{ "C4X_Ver2" ,C4V_Int, C4XVER2},
{ "C4X_Ver3" ,C4V_Int, C4XVER3},
{ "C4X_Ver4" ,C4V_Int, C4XVER4},
{ NULL, C4V_Any, 0}
};
#define MkFnC4V (C4Value (*)(C4AulContext *cthr, C4Value*, C4Value*, C4Value*, C4Value*, C4Value*,\
C4Value*, C4Value*, C4Value*, C4Value*, C4Value*))
C4ScriptFnDef C4ScriptFnMap[]=
{
{ "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 },
{ "GetType", 1 ,C4V_Int ,{ C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any} ,MkFnC4V FnGetType, 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_Any ,C4V_Array ,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_Any ,{ C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any ,C4V_Any} ,0, 0 }
};
void InitCoreFunctionMap(C4AulScriptEngine *pEngine)
{
// add all def constants (all Int)
for (C4ScriptConstDef *pCDef = &C4ScriptConstMap[0]; pCDef->Identifier; pCDef++)
{
assert(pCDef->ValType == C4V_Int); // only int supported currently
pEngine->RegisterGlobalConstant(pCDef->Identifier, C4VInt(pCDef->Data));
}
// 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);
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, "GetSystemTime", FnGetSystemTime, false);
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);
AddFunc(pEngine, "SetLength", FnSetLength);
AddFunc(pEngine, "this", Fn_this);
AddFunc(pEngine, "GetConstantNameByValue", FnGetConstantNameByValue, false);
AddFunc(pEngine, "Translate", FnTranslate);
}