forked from Mirrors/openclonk
Split C4Script.cpp into game functions and C4Script support functions
parent
d82815087e
commit
111df0392c
|
@ -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
|
||||
|
|
|
@ -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 \
|
||||
|
|
|
@ -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())
|
||||
|
|
|
@ -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 }
|
||||
|
||||
};
|
|
@ -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);
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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);
|
||||
}
|
Loading…
Reference in New Issue