From 449cc186d5b8117d74ba22d6173497d00939f5f1 Mon Sep 17 00:00:00 2001 From: Piotr Dziwinski Date: Sat, 28 Apr 2012 17:53:17 +0200 Subject: Source files split into modules --- src/script/script.cpp | 3777 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 3777 insertions(+) create mode 100644 src/script/script.cpp (limited to 'src/script/script.cpp') diff --git a/src/script/script.cpp b/src/script/script.cpp new file mode 100644 index 0000000..62b2d25 --- /dev/null +++ b/src/script/script.cpp @@ -0,0 +1,3777 @@ +// * This file is part of the COLOBOT source code +// * Copyright (C) 2001-2008, Daniel ROUX & EPSITEC SA, www.epsitec.ch +// * +// * This program is free software: you can redistribute it and/or modify +// * it under the terms of the GNU General Public License as published by +// * the Free Software Foundation, either version 3 of the License, or +// * (at your option) any later version. +// * +// * This program is distributed in the hope that it will be useful, +// * but WITHOUT ANY WARRANTY; without even the implied warranty of +// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// * GNU General Public License for more details. +// * +// * You should have received a copy of the GNU General Public License +// * along with this program. If not, see http://www.gnu.org/licenses/. + +// script.cpp + +#define STRICT +#define D3D_OVERLOADS + +#include +#include +#include + +#include "CBot/CBotDll.h" +#include "struct.h" +#include "d3dengine.h" +#include "d3dmath.h" +#include "global.h" +#include "event.h" +#include "misc.h" +#include "iman.h" +#include "restext.h" +#include "math3d.h" +#include "robotmain.h" +#include "terrain.h" +#include "water.h" +#include "object.h" +#include "physics.h" +#include "interface.h" +#include "edit.h" +#include "list.h" +#include "text.h" +#include "displaytext.h" +#include "taskmanager.h" +#include "task.h" +#include "taskmanip.h" +#include "taskgoto.h" +#include "taskshield.h" +#include "cbottoken.h" +#include "script.h" + + + +#define CBOT_IPF 100 // CBOT: number of instructions / frame + +#define ERM_CONT 0 // if error -> continue +#define ERM_STOP 1 // if error -> stop + + + + +// Compiling a procedure without any parameters. + +CBotTypResult cNull(CBotVar* &var, void* user) +{ + if ( var != 0 ) return CBotErrOverParam; + return CBotTypResult(CBotTypFloat); +} + +// Compiling a procedure with a single real number. + +CBotTypResult cOneFloat(CBotVar* &var, void* user) +{ + if ( var == 0 ) return CBotTypResult(CBotErrLowParam); + if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); + var = var->GivNext(); + if ( var != 0 ) return CBotTypResult(CBotErrOverParam); + return CBotTypResult(CBotTypFloat); +} + +// Compiling a procedure with two real numbers. + +CBotTypResult cTwoFloat(CBotVar* &var, void* user) +{ + if ( var == 0 ) return CBotTypResult(CBotErrLowParam); + if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); + var = var->GivNext(); + + if ( var == 0 ) return CBotTypResult(CBotErrLowParam); + if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); + var = var->GivNext(); + + if ( var != 0 ) return CBotTypResult(CBotErrOverParam); + return CBotTypResult(CBotTypFloat); +} + +// Compiling a procedure with a "dot". + +CBotTypResult cPoint(CBotVar* &var, void* user) +{ + if ( var == 0 ) return CBotTypResult(CBotErrLowParam); + + if ( var->GivType() <= CBotTypDouble ) + { + var = var->GivNext(); + if ( var == 0 ) return CBotTypResult(CBotErrLowParam); + if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); + var = var->GivNext(); +//? if ( var == 0 ) return CBotTypResult(CBotErrLowParam); +//? if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); +//? var = var->GivNext(); + return CBotTypResult(0); + } + + if ( var->GivType() == CBotTypClass ) + { + if ( !var->IsElemOfClass("point") ) return CBotTypResult(CBotErrBadParam); + var = var->GivNext(); + return CBotTypResult(0); + } + + return CBotTypResult(CBotErrBadParam); +} + +// Compiling a procedure with a single "point". + +CBotTypResult cOnePoint(CBotVar* &var, void* user) +{ + CBotTypResult ret; + + ret = cPoint(var, user); + if ( ret.GivType() != 0 ) return ret; + + if ( var != 0 ) return CBotTypResult(CBotErrOverParam); + return CBotTypResult(CBotTypFloat); +} + +// Compiling a procedure with a single string. + +CBotTypResult cString(CBotVar* &var, void* user) +{ + if ( var == 0 ) return CBotTypResult(CBotErrLowParam); + if ( var->GivType() != CBotTypString && + var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); + var = var->GivNext(); + if ( var != 0 ) return CBotTypResult(CBotErrOverParam); + return CBotTypResult(CBotTypFloat); +} + + +// Seeking value in an array of integers. + +BOOL FindList(CBotVar* array, int type) +{ + while ( array != 0 ) + { + if ( type == array->GivValInt() ) return TRUE; + array = array->GivNext(); + } + return FALSE; +} + + +// Gives a parameter of type "point". + +BOOL GetPoint(CBotVar* &var, int& exception, D3DVECTOR& pos) +{ + CBotVar *pX, *pY, *pZ; + + if ( var->GivType() <= CBotTypDouble ) + { + pos.x = var->GivValFloat()*g_unit; + var = var->GivNext(); + + pos.z = var->GivValFloat()*g_unit; + var = var->GivNext(); + + pos.y = 0.0f; + } + else + { + pX = var->GivItem("x"); + if ( pX == NULL ) + { + exception = CBotErrUndefItem; return TRUE; + } + pos.x = pX->GivValFloat()*g_unit; + + pY = var->GivItem("y"); + if ( pY == NULL ) + { + exception = CBotErrUndefItem; return TRUE; + } + pos.z = pY->GivValFloat()*g_unit; // attention y -> z ! + + pZ = var->GivItem("z"); + if ( pZ == NULL ) + { + exception = CBotErrUndefItem; return TRUE; + } + pos.y = pZ->GivValFloat()*g_unit; // attention z -> y ! + + var = var->GivNext(); + } + return TRUE; +} + + +// Instruction "sin(degrees)". + +BOOL rSin(CBotVar* var, CBotVar* result, int& exception, void* user) +{ + float value; + + value = var->GivValFloat(); + result->SetValFloat(sinf(value*PI/180.0f)); + return TRUE; +} + +// Instruction "cos(degrees)". + +BOOL rCos(CBotVar* var, CBotVar* result, int& exception, void* user) +{ + float value; + + value = var->GivValFloat(); + result->SetValFloat(cosf(value*PI/180.0f)); + return TRUE; +} + +// Instruction "tan(degrees)". + +BOOL rTan(CBotVar* var, CBotVar* result, int& exception, void* user) +{ + float value; + + value = var->GivValFloat(); + result->SetValFloat(tanf(value*PI/180.0f)); + return TRUE; +} + +// Instruction "asin(degrees)". + +BOOL raSin(CBotVar* var, CBotVar* result, int& exception, void* user) +{ + float value; + + value = var->GivValFloat(); + result->SetValFloat(asinf(value)*180.0f/PI); + return TRUE; +} + +// Instruction "acos(degrees)". + +BOOL raCos(CBotVar* var, CBotVar* result, int& exception, void* user) +{ + float value; + + value = var->GivValFloat(); + result->SetValFloat(acosf(value)*180.0f/PI); + return TRUE; +} + +// Instruction "atan(degrees)". + +BOOL raTan(CBotVar* var, CBotVar* result, int& exception, void* user) +{ + float value; + + value = var->GivValFloat(); + result->SetValFloat(atanf(value)*180.0f/PI); + return TRUE; +} + +// Instruction "sqrt(value)". + +BOOL rSqrt(CBotVar* var, CBotVar* result, int& exception, void* user) +{ + float value; + + value = var->GivValFloat(); + result->SetValFloat(sqrtf(value)); + return TRUE; +} + +// Instruction "pow(x, y)". + +BOOL rPow(CBotVar* var, CBotVar* result, int& exception, void* user) +{ + float x, y; + + x = var->GivValFloat(); + var = var->GivNext(); + y = var->GivValFloat(); + result->SetValFloat(powf(x, y)); + return TRUE; +} + +// Instruction "rand()". + +BOOL rRand(CBotVar* var, CBotVar* result, int& exception, void* user) +{ + result->SetValFloat(Rand()); + return TRUE; +} + +// Instruction "abs()". + +BOOL rAbs(CBotVar* var, CBotVar* result, int& exception, void* user) +{ + float value; + + value = var->GivValFloat(); + result->SetValFloat(Abs(value)); + return TRUE; +} + + +// Compilation of the instruction "retobject(rank)". + +CBotTypResult cRetObject(CBotVar* &var, void* user) +{ + if ( var == 0 ) return CBotTypResult(CBotErrLowParam); + if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); + var = var->GivNext(); + if ( var != 0 ) return CBotTypResult(CBotErrOverParam); + + return CBotTypResult(CBotTypPointer, "object"); +} + +// Instruction "retobject(rank)". + +BOOL rRetObject(CBotVar* var, CBotVar* result, int& exception, void* user) +{ + CScript* script = ((CObject*)user)->RetRunScript(); + CObject* pObj; + int rank; + + rank = var->GivValInt(); + + pObj = (CObject*)script->m_iMan->SearchInstance(CLASS_OBJECT, rank); + if ( pObj == 0 ) + { + result->SetPointer(0); + } + else + { + result->SetPointer(pObj->RetBotVar()); + } + return TRUE; +} + + +// Compilation of the instruction "search(type, pos)". + +CBotTypResult cSearch(CBotVar* &var, void* user) +{ + CBotVar* array; + CBotTypResult ret; + + if ( var == 0 ) return CBotTypResult(CBotErrLowParam); + if ( var->GivType() == CBotTypArrayPointer ) + { + array = var->GivItemList(); + if ( array == 0 ) return CBotTypResult(CBotTypPointer); + if ( array->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); + } + else if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); + var = var->GivNext(); + if ( var != 0 ) + { + ret = cPoint(var, user); + if ( ret.GivType() != 0 ) return ret; + if ( var != 0 ) return CBotTypResult(CBotErrOverParam); + } + + return CBotTypResult(CBotTypPointer, "object"); +} + +// Instruction "search(type, pos)". + +BOOL rSearch(CBotVar* var, CBotVar* result, int& exception, void* user) +{ + CScript* script = ((CObject*)user)->RetRunScript(); + CObject *pObj, *pBest; + CBotVar* array; + D3DVECTOR pos, oPos; + BOOL bNearest = FALSE; + BOOL bArray; + float min, dist; + int type, oType, i; + + if ( var->GivType() == CBotTypArrayPointer ) + { + array = var->GivItemList(); + bArray = TRUE; + } + else + { + type = var->GivValInt(); + bArray = FALSE; + } + var = var->GivNext(); + if ( var != 0 ) + { + if ( !GetPoint(var, exception, pos) ) return TRUE; + bNearest = TRUE; + } + + min = 100000.0f; + pBest = 0; + for ( i=0 ; i<1000000 ; i++ ) + { + pObj = (CObject*)script->m_iMan->SearchInstance(CLASS_OBJECT, i); + if ( pObj == 0 ) break; + + if ( pObj->RetTruck() != 0 ) continue; // object transported? + if ( !pObj->RetActif() ) continue; + + oType = pObj->RetType(); + if ( oType == OBJECT_TOTO ) continue; + + if ( oType == OBJECT_RUINmobilew2 || + oType == OBJECT_RUINmobilet1 || + oType == OBJECT_RUINmobilet2 || + oType == OBJECT_RUINmobiler1 || + oType == OBJECT_RUINmobiler2 ) + { + oType = OBJECT_RUINmobilew1; // any ruin + } + + if ( oType == OBJECT_SCRAP2 || + oType == OBJECT_SCRAP3 || + oType == OBJECT_SCRAP4 || + oType == OBJECT_SCRAP5 ) // wastes? + { + oType = OBJECT_SCRAP1; // any waste + } + + if ( oType == OBJECT_BARRIER2 || + oType == OBJECT_BARRIER3 ) // barriers? + { + oType = OBJECT_BARRIER1; // any barrier + } + + if ( bArray ) + { + if ( !FindList(array, oType) ) continue; + } + else + { + if ( type != oType && type != OBJECT_NULL ) continue; + } + + if ( bNearest ) + { + oPos = pObj->RetPosition(0); + dist = Length2d(pos, oPos); + if ( dist < min ) + { + min = dist; + pBest = pObj; + } + } + else + { + pBest = pObj; + break; + } + } + + if ( pBest == 0 ) + { + result->SetPointer(0); + } + else + { + result->SetPointer(pBest->RetBotVar()); + } + return TRUE; +} + + +// Compilation of instruction "radar(type, angle, focus, min, max, sens)". + +CBotTypResult cRadar(CBotVar* &var, void* user) +{ + CBotVar* array; + + if ( var == 0 ) return CBotTypResult(CBotTypPointer, "object"); + if ( var->GivType() == CBotTypArrayPointer ) + { + array = var->GivItemList(); + if ( array == 0 ) return CBotTypResult(CBotTypPointer, "object"); + if ( array->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); // type + } + else if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); // type + var = var->GivNext(); + if ( var == 0 ) return CBotTypResult(CBotTypPointer, "object"); + if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); // angle + var = var->GivNext(); + if ( var == 0 ) return CBotTypResult(CBotTypPointer, "object"); + if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); // focus + var = var->GivNext(); + if ( var == 0 ) return CBotTypResult(CBotTypPointer, "object"); + if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); // min + var = var->GivNext(); + if ( var == 0 ) return CBotTypResult(CBotTypPointer, "object"); + if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); // max + var = var->GivNext(); + if ( var == 0 ) return CBotTypResult(CBotTypPointer, "object"); + if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); // sense + var = var->GivNext(); + if ( var == 0 ) return CBotTypResult(CBotTypPointer, "object"); + if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); // filter + var = var->GivNext(); + if ( var == 0 ) return CBotTypResult(CBotTypPointer, "object"); + return CBotTypResult(CBotErrOverParam); +} + +// Instruction "radar(type, angle, focus, min, max, sens, filter)". + +BOOL rRadar(CBotVar* var, CBotVar* result, int& exception, void* user) +{ + CScript* script = ((CObject*)user)->RetRunScript(); + CObject* pThis = (CObject*)user; + CObject *pObj, *pBest; + CPhysics* physics; + CBotVar* array; + D3DVECTOR iPos, oPos; + RadarFilter filter; + float best, minDist, maxDist, sens, iAngle, angle, focus, d, a; + int type, oType, i; + BOOL bArray; + + type = OBJECT_NULL; + angle = 0.0f; + focus = PI*2.0f; + minDist = 0.0f*g_unit; + maxDist = 1000.0f*g_unit; + sens = 1.0f; + filter = FILTER_NONE; + + if ( var != 0 ) + { + if ( var->GivType() == CBotTypArrayPointer ) + { + array = var->GivItemList(); + bArray = TRUE; + } + else + { + type = var->GivValInt(); + bArray = FALSE; + } + + var = var->GivNext(); + if ( var != 0 ) + { + angle = -var->GivValFloat()*PI/180.0f; + + var = var->GivNext(); + if ( var != 0 ) + { + focus = var->GivValFloat()*PI/180.0f; + + var = var->GivNext(); + if ( var != 0 ) + { + minDist = var->GivValFloat()*g_unit; + + var = var->GivNext(); + if ( var != 0 ) + { + maxDist = var->GivValFloat()*g_unit; + + var = var->GivNext(); + if ( var != 0 ) + { + sens = var->GivValFloat(); + + var = var->GivNext(); + if ( var != 0 ) + { + filter = (RadarFilter)var->GivValInt(); + } + } + } + } + } + } + } + + iPos = pThis->RetPosition(0); + iAngle = pThis->RetAngleY(0)+angle; + iAngle = NormAngle(iAngle); // 0..2*PI + + if ( sens >= 0.0f ) best = 100000.0f; + else best = 0.0f; + pBest = 0; + for ( i=0 ; i<1000000 ; i++ ) + { + pObj = (CObject*)script->m_iMan->SearchInstance(CLASS_OBJECT, i); + if ( pObj == 0 ) break; + if ( pObj == pThis ) continue; + + if ( pObj->RetTruck() != 0 ) continue; // object transported? + if ( !pObj->RetActif() ) continue; + if ( pObj->RetProxyActivate() ) continue; + + oType = pObj->RetType(); + if ( oType == OBJECT_TOTO ) continue; + + if ( oType == OBJECT_RUINmobilew2 || + oType == OBJECT_RUINmobilet1 || + oType == OBJECT_RUINmobilet2 || + oType == OBJECT_RUINmobiler1 || + oType == OBJECT_RUINmobiler2 ) + { + oType = OBJECT_RUINmobilew1; // any ruin + } + + if ( oType == OBJECT_SCRAP2 || + oType == OBJECT_SCRAP3 || + oType == OBJECT_SCRAP4 || + oType == OBJECT_SCRAP5 ) // wastes? + { + oType = OBJECT_SCRAP1; // any waste + } + + if ( oType == OBJECT_BARRIER2 || + oType == OBJECT_BARRIER3 ) // barriers? + { + oType = OBJECT_BARRIER1; // any barrier + } + + if ( filter == FILTER_ONLYLANDING ) + { + physics = pObj->RetPhysics(); + if ( physics != 0 && !physics->RetLand() ) continue; + } + if ( filter == FILTER_ONLYFLYING ) + { + physics = pObj->RetPhysics(); + if ( physics != 0 && physics->RetLand() ) continue; + } + + if ( bArray ) + { + if ( !FindList(array, oType) ) continue; + } + else + { + if ( type != oType && type != OBJECT_NULL ) continue; + } + + oPos = pObj->RetPosition(0); + d = Length2d(iPos, oPos); + if ( d < minDist || d > maxDist ) continue; // too close or too far? + + if ( focus >= PI*2.0f ) + { + if ( (sens >= 0.0f && d < best) || + (sens < 0.0f && d > best) ) + { + best = d; + pBest = pObj; + } + continue; + } + + a = RotateAngle(oPos.x-iPos.x, iPos.z-oPos.z); // CW ! + if ( TestAngle(a, iAngle-focus/2.0f, iAngle+focus/2.0f) ) + { + if ( (sens >= 0.0f && d < best) || + (sens < 0.0f && d > best) ) + { + best = d; + pBest = pObj; + } + } + } + + if ( pBest == 0 ) + { + result->SetPointer(0); + } + else + { + result->SetPointer(pBest->RetBotVar()); + } + return TRUE; +} + + +// Monitoring a task. + +BOOL Process(CScript* script, CBotVar* result, int &exception) +{ + Error err; + + err = script->m_primaryTask->IsEnded(); + if ( err != ERR_CONTINUE ) // task terminated? + { + delete script->m_primaryTask; + script->m_primaryTask = 0; + + script->m_bContinue = FALSE; + + if ( err == ERR_STOP ) err = ERR_OK; + result->SetValInt(err); // indicates the error or ok + if ( err != ERR_OK && script->m_errMode == ERM_STOP ) + { + exception = err; + return FALSE; + } + return TRUE; // it's all over + } + + script->m_primaryTask->EventProcess(script->m_event); + script->m_bContinue = TRUE; + return FALSE; // not done +} + + +// Compilation of the instruction "detect(type)". + +CBotTypResult cDetect(CBotVar* &var, void* user) +{ + if ( var == 0 ) return CBotTypResult(CBotErrLowParam); + if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); + var = var->GivNext(); + if ( var != 0 ) return CBotTypResult(CBotErrOverParam); + return CBotTypResult(CBotTypBoolean); +} + +// Instruction "detect(type)". + +BOOL rDetect(CBotVar* var, CBotVar* result, int& exception, void* user) +{ + CScript* script = ((CObject*)user)->RetRunScript(); + CObject* pThis = (CObject*)user; + CObject *pObj, *pGoal, *pBest; + CPhysics* physics; + CBotVar* array; + D3DVECTOR iPos, oPos; + RadarFilter filter; + float bGoal, best, minDist, maxDist, sens, iAngle, angle, focus, d, a; + int type, oType, i; + BOOL bArray; + Error err; + + exception = 0; + + if ( script->m_primaryTask == 0 ) // no task in progress? + { + type = OBJECT_NULL; + angle = 0.0f; + focus = 45.0f*PI/180.0f; + minDist = 0.0f*g_unit; + maxDist = 20.0f*g_unit; + sens = 1.0f; + filter = FILTER_NONE; + + if ( var != 0 ) + { + if ( var->GivType() == CBotTypArrayPointer ) + { + array = var->GivItemList(); + bArray = TRUE; + } + else + { + type = var->GivValInt(); + bArray = FALSE; + } + } + + iPos = pThis->RetPosition(0); + iAngle = pThis->RetAngleY(0)+angle; + iAngle = NormAngle(iAngle); // 0..2*PI + + bGoal = 100000.0f; + pGoal = 0; + if ( sens >= 0.0f ) best = 100000.0f; + else best = 0.0f; + pBest = 0; + for ( i=0 ; i<1000000 ; i++ ) + { + pObj = (CObject*)script->m_iMan->SearchInstance(CLASS_OBJECT, i); + if ( pObj == 0 ) break; + if ( pObj == pThis ) continue; + + if ( pObj->RetTruck() != 0 ) continue; // object transported? + if ( !pObj->RetActif() ) continue; + if ( pObj->RetProxyActivate() ) continue; + + oType = pObj->RetType(); + if ( oType == OBJECT_TOTO ) continue; + + if ( oType == OBJECT_RUINmobilew2 || + oType == OBJECT_RUINmobilet1 || + oType == OBJECT_RUINmobilet2 || + oType == OBJECT_RUINmobiler1 || + oType == OBJECT_RUINmobiler2 ) + { + oType = OBJECT_RUINmobilew1; // any ruin + } + + if ( oType == OBJECT_SCRAP2 || + oType == OBJECT_SCRAP3 || + oType == OBJECT_SCRAP4 || + oType == OBJECT_SCRAP5 ) // wastes? + { + oType = OBJECT_SCRAP1; // any waste + } + + if ( oType == OBJECT_BARRIER2 || + oType == OBJECT_BARRIER3 ) // barriers? + { + oType = OBJECT_BARRIER1; // any barrier + } + + if ( filter == FILTER_ONLYLANDING ) + { + physics = pObj->RetPhysics(); + if ( physics != 0 && !physics->RetLand() ) continue; + } + if ( filter == FILTER_ONLYFLYING ) + { + physics = pObj->RetPhysics(); + if ( physics != 0 && physics->RetLand() ) continue; + } + + if ( bArray ) + { + if ( !FindList(array, oType) ) continue; + } + else + { + if ( type != oType && type != OBJECT_NULL ) continue; + } + + oPos = pObj->RetPosition(0); + d = Length2d(iPos, oPos); + a = RotateAngle(oPos.x-iPos.x, iPos.z-oPos.z); // CW ! + + if ( d < bGoal && + TestAngle(a, iAngle-(5.0f*PI/180.0f)/2.0f, iAngle+(5.0f*PI/180.0f)/2.0f) ) + { + bGoal = d; + pGoal = pObj; + } + + if ( d < minDist || d > maxDist ) continue; // too close or too far? + + if ( focus >= PI*2.0f ) + { + if ( (sens >= 0.0f && d < best) || + (sens < 0.0f && d > best) ) + { + best = d; + pBest = pObj; + } + continue; + } + + if ( TestAngle(a, iAngle-focus/2.0f, iAngle+focus/2.0f) ) + { + if ( (sens >= 0.0f && d < best) || + (sens < 0.0f && d > best) ) + { + best = d; + pBest = pObj; + } + } + } + + pThis->StartDetectEffect(pGoal, pBest!=0); + + if ( pBest == 0 ) + { + script->m_returnValue = 0.0f; + } + else + { + script->m_returnValue = 1.0f; + } + + script->m_primaryTask = new CTaskManager(script->m_iMan, script->m_object); + err = script->m_primaryTask->StartTaskWait(0.3f); + if ( err != ERR_OK ) + { + delete script->m_primaryTask; + script->m_primaryTask = 0; + result->SetValInt(err); // shows the error + if ( script->m_errMode == ERM_STOP ) + { + exception = err; + return FALSE; + } + return TRUE; + } + } + if ( !Process(script, result, exception) ) return FALSE; // not finished + result->SetValFloat(script->m_returnValue); + return TRUE; +} + + +// Compilation of the instruction "direction(pos)". + +CBotTypResult cDirection(CBotVar* &var, void* user) +{ + CBotTypResult ret; + + if ( var == 0 ) return CBotTypResult(CBotErrLowParam); + ret = cPoint(var, user); + if ( ret.GivType() != 0 ) return ret; + if ( var != 0 ) return CBotTypResult(CBotErrOverParam); + + return CBotTypResult(CBotTypFloat); +} + +// Instruction "direction(pos)". + +BOOL rDirection(CBotVar* var, CBotVar* result, int& exception, void* user) +{ + CScript* script = ((CObject*)user)->RetRunScript(); + CObject* pThis = (CObject*)user; + D3DVECTOR iPos, oPos; + float a, g; + + if ( !GetPoint(var, exception, oPos) ) return TRUE; + + iPos = pThis->RetPosition(0); + + a = pThis->RetAngleY(0); + g = RotateAngle(oPos.x-iPos.x, iPos.z-oPos.z); // CW ! + + result->SetValFloat(-Direction(a, g)*180.0f/PI); + return TRUE; +} + + +// Compilation of the instruction "produce(pos, angle, type, scriptName)". + +CBotTypResult cProduce(CBotVar* &var, void* user) +{ + CBotTypResult ret; + + if ( var == 0 ) return CBotTypResult(CBotErrLowParam); + ret = cPoint(var, user); + if ( ret.GivType() != 0 ) return ret; + + if ( var == 0 ) return CBotTypResult(CBotErrLowParam); + if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); + var = var->GivNext(); + + if ( var == 0 ) return CBotTypResult(CBotErrLowParam); + if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); + var = var->GivNext(); + + if ( var == 0 ) return CBotTypResult(CBotErrLowParam); + if ( var->GivType() != CBotTypString ) return CBotTypResult(CBotErrBadString); + var = var->GivNext(); + + if ( var != 0 ) return CBotTypResult(CBotErrOverParam); + + return CBotTypResult(CBotTypFloat); +} + +// Instruction "produce(pos, angle, type, scriptName)". + +BOOL rProduce(CBotVar* var, CBotVar* result, int& exception, void* user) +{ + CScript* script = ((CObject*)user)->RetRunScript(); + CObject* object; + CBotString cbs; + const char* name; + D3DVECTOR pos; + float angle; + ObjectType type; + + if ( !GetPoint(var, exception, pos) ) return TRUE; + + angle = var->GivValFloat()*PI/180.0f; + var = var->GivNext(); + + type = (ObjectType)var->GivValInt(); + var = var->GivNext(); + + cbs = var->GivValString(); + name = cbs; + + if ( type == OBJECT_FRET || + type == OBJECT_STONE || + type == OBJECT_URANIUM || + type == OBJECT_METAL || + type == OBJECT_POWER || + type == OBJECT_ATOMIC || + type == OBJECT_BULLET || + type == OBJECT_BBOX || + type == OBJECT_KEYa || + type == OBJECT_KEYb || + type == OBJECT_KEYc || + type == OBJECT_KEYd || + type == OBJECT_TNT || + type == OBJECT_SCRAP1 || + type == OBJECT_SCRAP2 || + type == OBJECT_SCRAP3 || + type == OBJECT_SCRAP4 || + type == OBJECT_SCRAP5 || + type == OBJECT_BOMB || + type == OBJECT_WAYPOINT || + type == OBJECT_SHOW || + type == OBJECT_WINFIRE ) + { + object = new CObject(script->m_iMan); + if ( !object->CreateResource(pos, angle, type) ) + { + delete object; + result->SetValInt(1); // error + return TRUE; + } + } + else + if ( type == OBJECT_MOTHER || + type == OBJECT_ANT || + type == OBJECT_SPIDER || + type == OBJECT_BEE || + type == OBJECT_WORM ) + { + CObject* egg; + + object = new CObject(script->m_iMan); + if ( !object->CreateInsect(pos, angle, type) ) + { + delete object; + result->SetValInt(1); // error + return TRUE; + } + + egg = new CObject(script->m_iMan); + if ( !egg->CreateResource(pos, angle, OBJECT_EGG, 0.0f) ) + { + delete egg; + } + } + else + { + result->SetValInt(1); // impossible + return TRUE; + } + object->SetActivity(FALSE); + object->ReadProgram(0, (char*)name); + object->RunProgram(0); + + result->SetValInt(0); // no error + return TRUE; +} + + +// Compilation of the instruction "distance(p1, p2)". + +CBotTypResult cDistance(CBotVar* &var, void* user) +{ + CBotTypResult ret; + + if ( var == 0 ) return CBotTypResult(CBotErrLowParam); + ret = cPoint(var, user); + if ( ret.GivType() != 0 ) return ret; + + if ( var == 0 ) return CBotTypResult(CBotErrLowParam); + ret = cPoint(var, user); + if ( ret.GivType() != 0 ) return ret; + + if ( var != 0 ) return CBotTypResult(CBotErrOverParam); + + return CBotTypResult(CBotTypFloat); +} + +// Instruction "distance(p1, p2)". + +BOOL rDistance(CBotVar* var, CBotVar* result, int& exception, void* user) +{ + D3DVECTOR p1, p2; + float value; + + if ( !GetPoint(var, exception, p1) ) return TRUE; + if ( !GetPoint(var, exception, p2) ) return TRUE; + + value = Length(p1, p2); + result->SetValFloat(value/g_unit); + return TRUE; +} + +// Instruction "distance2d(p1, p2)". + +BOOL rDistance2d(CBotVar* var, CBotVar* result, int& exception, void* user) +{ + D3DVECTOR p1, p2; + float value; + + if ( !GetPoint(var, exception, p1) ) return TRUE; + if ( !GetPoint(var, exception, p2) ) return TRUE; + + value = Length2d(p1, p2); + result->SetValFloat(value/g_unit); + return TRUE; +} + + +// Compilation of the instruction "space(center, rMin, rMax, dist)". + +CBotTypResult cSpace(CBotVar* &var, void* user) +{ + CBotTypResult ret; + + if ( var == 0 ) return CBotTypResult(CBotTypIntrinsic, "point"); + ret = cPoint(var, user); + if ( ret.GivType() != 0 ) return ret; + + if ( var == 0 ) return CBotTypResult(CBotTypIntrinsic, "point"); + if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); + var = var->GivNext(); + + if ( var == 0 ) return CBotTypResult(CBotTypIntrinsic, "point"); + if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); + var = var->GivNext(); + + if ( var == 0 ) return CBotTypResult(CBotTypIntrinsic, "point"); + if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); + var = var->GivNext(); + + if ( var != 0 ) return CBotTypResult(CBotErrOverParam); + return CBotTypResult(CBotTypIntrinsic, "point"); +} + +// Instruction "space(center, rMin, rMax, dist)". + +BOOL rSpace(CBotVar* var, CBotVar* result, int& exception, void* user) +{ + CScript* script = ((CObject*)user)->RetRunScript(); + CObject* pThis = (CObject*)user; + CBotVar* pSub; + D3DVECTOR center; + float rMin, rMax, dist; + + rMin = 10.0f*g_unit; + rMax = 50.0f*g_unit; + dist = 4.0f*g_unit; + + if ( var == 0 ) + { + center = pThis->RetPosition(0); + } + else + { + if ( !GetPoint(var, exception, center) ) return TRUE; + + if ( var != 0 ) + { + rMin = var->GivValFloat()*g_unit; + var = var->GivNext(); + + if ( var != 0 ) + { + rMax = var->GivValFloat()*g_unit; + var = var->GivNext(); + + if ( var != 0 ) + { + dist = var->GivValFloat()*g_unit; + var = var->GivNext(); + } + } + } + } + script->m_main->FreeSpace(center, rMin, rMax, dist, pThis); + + if ( result != 0 ) + { + pSub = result->GivItemList(); + if ( pSub != 0 ) + { + pSub->SetValFloat(center.x/g_unit); + pSub = pSub->GivNext(); // "y" + pSub->SetValFloat(center.z/g_unit); + pSub = pSub->GivNext(); // "z" + pSub->SetValFloat(center.y/g_unit); + } + } + return TRUE; +} + + +// Compilation of the instruction "flatground(center, rMax)". + +CBotTypResult cFlatGround(CBotVar* &var, void* user) +{ + CBotTypResult ret; + + if ( var == 0 ) return CBotTypResult(CBotErrLowParam); + ret = cPoint(var, user); + if ( ret.GivType() != 0 ) return ret; + + if ( var == 0 ) return CBotTypResult(CBotErrLowParam); + if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); + var = var->GivNext(); + + if ( var != 0 ) return CBotTypResult(CBotErrOverParam); + + return CBotTypResult(CBotTypFloat); +} + +// Instruction "flatground(center, rMax)". + +BOOL rFlatGround(CBotVar* var, CBotVar* result, int& exception, void* user) +{ + CScript* script = ((CObject*)user)->RetRunScript(); + CObject* pThis = (CObject*)user; + D3DVECTOR center; + float rMax, dist; + + if ( !GetPoint(var, exception, center) ) return TRUE; + rMax = var->GivValFloat()*g_unit; + var = var->GivNext(); + + dist = script->m_main->RetFlatZoneRadius(center, rMax, pThis); + result->SetValFloat(dist/g_unit); + + return TRUE; +} + + +// Instruction "wait(t)". + +BOOL rWait(CBotVar* var, CBotVar* result, int& exception, void* user) +{ + CScript* script = ((CObject*)user)->RetRunScript(); + float value; + Error err; + + exception = 0; + + if ( script->m_primaryTask == 0 ) // no task in progress? + { + script->m_primaryTask = new CTaskManager(script->m_iMan, script->m_object); + value = var->GivValFloat(); + err = script->m_primaryTask->StartTaskWait(value); + if ( err != ERR_OK ) + { + delete script->m_primaryTask; + script->m_primaryTask = 0; + result->SetValInt(err); // shows the error + if ( script->m_errMode == ERM_STOP ) + { + exception = err; + return FALSE; + } + return TRUE; + } + } + return Process(script, result, exception); +} + +// Instruction "move(dist)". + +BOOL rMove(CBotVar* var, CBotVar* result, int& exception, void* user) +{ + CScript* script = ((CObject*)user)->RetRunScript(); + float value; + Error err; + + exception = 0; + + if ( script->m_primaryTask == 0 ) // no task in progress? + { + script->m_primaryTask = new CTaskManager(script->m_iMan, script->m_object); + value = var->GivValFloat(); + err = script->m_primaryTask->StartTaskAdvance(value*g_unit); + if ( err != ERR_OK ) + { + delete script->m_primaryTask; + script->m_primaryTask = 0; + result->SetValInt(err); // shows the error + if ( script->m_errMode == ERM_STOP ) + { + exception = err; + return FALSE; + } + return TRUE; + } + } + return Process(script, result, exception); +} + +// Instruction "turn(angle)". + +BOOL rTurn(CBotVar* var, CBotVar* result, int& exception, void* user) +{ + CScript* script = ((CObject*)user)->RetRunScript(); + float value; + Error err; + + exception = 0; + + if ( script->m_primaryTask == 0 ) // no task in progress? + { + script->m_primaryTask = new CTaskManager(script->m_iMan, script->m_object); + value = var->GivValFloat(); + err = script->m_primaryTask->StartTaskTurn(-value*PI/180.0f); + if ( err != ERR_OK ) + { + delete script->m_primaryTask; + script->m_primaryTask = 0; + result->SetValInt(err); // shows the error + if ( script->m_errMode == ERM_STOP ) + { + exception = err; + return FALSE; + } + return TRUE; + } + } + return Process(script, result, exception); +} + +// Compilation of the instruction "goto(pos, altitude, crash, goal)". + +CBotTypResult cGoto(CBotVar* &var, void* user) +{ + CBotTypResult ret; + + if ( var == 0 ) return CBotTypResult(CBotErrLowParam); + ret = cPoint(var, user); + if ( ret.GivType() != 0 ) return ret; + + if ( var == 0 ) return CBotTypResult(CBotTypFloat); + if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); + var = var->GivNext(); + + if ( var == 0 ) return CBotTypResult(CBotTypFloat); + if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); + var = var->GivNext(); + + if ( var == 0 ) return CBotTypResult(CBotTypFloat); + if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); + var = var->GivNext(); + + if ( var == 0 ) return CBotTypResult(CBotTypFloat); + return CBotTypResult(CBotErrOverParam); +} + +// Instruction "goto(pos, altitude, mode)". + +BOOL rGoto(CBotVar* var, CBotVar* result, int& exception, void* user) +{ + CScript* script = ((CObject*)user)->RetRunScript(); + D3DVECTOR pos; + TaskGotoGoal goal; + TaskGotoCrash crash; + float altitude; + Error err; + + exception = 0; + + if ( script->m_primaryTask == 0 ) // no task in progress? + { + script->m_primaryTask = new CTaskManager(script->m_iMan, script->m_object); + if ( !GetPoint(var, exception, pos) ) return TRUE; + + goal = TGG_DEFAULT; + crash = TGC_DEFAULT; + altitude = 0.0f*g_unit; + + if ( var != 0 ) + { + altitude = var->GivValFloat()*g_unit; + + var = var->GivNext(); + if ( var != 0 ) + { + goal = (TaskGotoGoal)var->GivValInt(); + + var = var->GivNext(); + if ( var != 0 ) + { + crash = (TaskGotoCrash)var->GivValInt(); + } + } + } + + err = script->m_primaryTask->StartTaskGoto(pos, altitude, goal, crash); + if ( err != ERR_OK ) + { + delete script->m_primaryTask; + script->m_primaryTask = 0; + result->SetValInt(err); // shows the error + if ( script->m_errMode == ERM_STOP ) + { + exception = err; + return FALSE; + } + return TRUE; + } + } + return Process(script, result, exception); +} + +// Instruction "find(type)". + +BOOL rFind(CBotVar* var, CBotVar* result, int& exception, void* user) +{ + CScript* script = ((CObject*)user)->RetRunScript(); + D3DVECTOR pos; + TaskGotoGoal goal; + TaskGotoCrash crash; + float altitude; + Error err; + CObject* pThis = (CObject*)user; + CObject *pObj, *pBest; + CBotVar* array; + D3DVECTOR iPos, oPos; + float best, minDist, maxDist, sens, iAngle, angle, focus, d, a; + int type, oType, i; + BOOL bArray; + + exception = 0; + + if ( script->m_primaryTask == 0 ) // no task in progress? + { + type = OBJECT_NULL; + angle = 0.0f; + focus = PI*2.0f; + minDist = 0.0f*g_unit; + maxDist = 1000.0f*g_unit; + sens = 1.0f; + + if ( var->GivType() == CBotTypArrayPointer ) + { + array = var->GivItemList(); + bArray = TRUE; + } + else + { + type = var->GivValInt(); + bArray = FALSE; + } + + best = 100000.0f; + pBest = 0; + for ( i=0 ; i<1000000 ; i++ ) + { + pObj = (CObject*)script->m_iMan->SearchInstance(CLASS_OBJECT, i); + if ( pObj == 0 ) break; + if ( pObj == pThis ) continue; + + if ( pObj->RetTruck() != 0 ) continue; // object transported? + if ( !pObj->RetActif() ) continue; + if ( pObj->RetProxyActivate() ) continue; + + oType = pObj->RetType(); + if ( oType == OBJECT_TOTO ) continue; + + if ( oType == OBJECT_RUINmobilew2 || + oType == OBJECT_RUINmobilet1 || + oType == OBJECT_RUINmobilet2 || + oType == OBJECT_RUINmobiler1 || + oType == OBJECT_RUINmobiler2 ) + { + oType = OBJECT_RUINmobilew1; // any ruin + } + + if ( oType == OBJECT_SCRAP2 || + oType == OBJECT_SCRAP3 || + oType == OBJECT_SCRAP4 || + oType == OBJECT_SCRAP5 ) // wastes? + { + oType = OBJECT_SCRAP1; // any waste + } + + if ( oType == OBJECT_BARRIER2 || + oType == OBJECT_BARRIER3 ) // barriers? + { + oType = OBJECT_BARRIER1; // any barrier + } + + if ( bArray ) + { + if ( !FindList(array, oType) ) continue; + } + else + { + if ( type != oType && type != OBJECT_NULL ) continue; + } + + oPos = pObj->RetPosition(0); + d = Length2d(iPos, oPos); + if ( d < minDist || d > maxDist ) continue; // too close or too far? + + if ( focus >= PI*2.0f ) + { + if ( d < best ) + { + best = d; + pBest = pObj; + } + continue; + } + + a = RotateAngle(oPos.x-iPos.x, iPos.z-oPos.z); // CW ! + if ( TestAngle(a, iAngle-focus/2.0f, iAngle+focus/2.0f) ) + { + if ( d < best ) + { + best = d; + pBest = pObj; + } + } + } + + if ( pBest == 0 ) + { + exception = ERR_FIND_IMPOSSIBLE; + return FALSE; + } + + pos = pBest->RetPosition(0); + goal = TGG_DEFAULT; + crash = TGC_DEFAULT; + altitude = 0.0f*g_unit; + + script->m_primaryTask = new CTaskManager(script->m_iMan, script->m_object); + err = script->m_primaryTask->StartTaskGoto(pos, altitude, goal, crash); + if ( err != ERR_OK ) + { + delete script->m_primaryTask; + script->m_primaryTask = 0; + result->SetValInt(err); // shows the error + if ( script->m_errMode == ERM_STOP ) + { + exception = err; + return FALSE; + } + return TRUE; + } + } + return Process(script, result, exception); +} + +// Compilation "grab/drop(oper)". + +CBotTypResult cGrabDrop(CBotVar* &var, void* user) +{ + if ( var == 0 ) return CBotTypResult(CBotTypFloat); + if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); + var = var->GivNext(); + if ( var != 0 ) return CBotTypResult(CBotErrOverParam); + return CBotTypResult(CBotTypFloat); +} + +// Instruction "grab(oper)". + +BOOL rGrab(CBotVar* var, CBotVar* result, int& exception, void* user) +{ + CScript* script = ((CObject*)user)->RetRunScript(); + CObject* pThis = (CObject*)user; + ObjectType oType; + TaskManipArm type; + Error err; + + exception = 0; + + if ( script->m_primaryTask == 0 ) // no task in progress? + { + script->m_primaryTask = new CTaskManager(script->m_iMan, script->m_object); + if ( var == 0 ) type = TMA_FFRONT; + else type = (TaskManipArm)var->GivValInt(); + + oType = pThis->RetType(); + if ( oType == OBJECT_HUMAN || + oType == OBJECT_TECH ) + { + err = script->m_primaryTask->StartTaskTake(); + } + else + { + err = script->m_primaryTask->StartTaskManip(TMO_GRAB, type); + } + + if ( err != ERR_OK ) + { + delete script->m_primaryTask; + script->m_primaryTask = 0; + result->SetValInt(err); // shows the error + if ( script->m_errMode == ERM_STOP ) + { + exception = err; + return FALSE; + } + return TRUE; + } + } + return Process(script, result, exception); +} + +// Instruction "drop(oper)". + +BOOL rDrop(CBotVar* var, CBotVar* result, int& exception, void* user) +{ + CScript* script = ((CObject*)user)->RetRunScript(); + CObject* pThis = (CObject*)user; + ObjectType oType; + TaskManipArm type; + Error err; + + exception = 0; + + if ( script->m_primaryTask == 0 ) // no task in progress? + { + script->m_primaryTask = new CTaskManager(script->m_iMan, script->m_object); + if ( var == 0 ) type = TMA_FFRONT; + else type = (TaskManipArm)var->GivValInt(); + + oType = pThis->RetType(); + if ( oType == OBJECT_HUMAN || + oType == OBJECT_TECH ) + { + err = script->m_primaryTask->StartTaskTake(); + } + else + { + err = script->m_primaryTask->StartTaskManip(TMO_DROP, type); + } + + if ( err != ERR_OK ) + { + delete script->m_primaryTask; + script->m_primaryTask = 0; + result->SetValInt(err); // shows the error + if ( script->m_errMode == ERM_STOP ) + { + exception = err; + return FALSE; + } + return TRUE; + } + } + return Process(script, result, exception); +} + +// Instruction "sniff()". + +BOOL rSniff(CBotVar* var, CBotVar* result, int& exception, void* user) +{ + CScript* script = ((CObject*)user)->RetRunScript(); + Error err; + + exception = 0; + + if ( script->m_primaryTask == 0 ) // no task in progress? + { + script->m_primaryTask = new CTaskManager(script->m_iMan, script->m_object); + err = script->m_primaryTask->StartTaskSearch(); + if ( err != ERR_OK ) + { + delete script->m_primaryTask; + script->m_primaryTask = 0; + result->SetValInt(err); // shows the error + if ( script->m_errMode == ERM_STOP ) + { + exception = err; + return FALSE; + } + return TRUE; + } + } + return Process(script, result, exception); +} + +// Compilation of the instruction "receive(nom, power)". + +CBotTypResult cReceive(CBotVar* &var, void* user) +{ + if ( var == 0 ) return CBotTypResult(CBotErrLowParam); + if ( var->GivType() != CBotTypString ) return CBotTypResult(CBotErrBadString); + var = var->GivNext(); + + if ( var == 0 ) return CBotTypResult(CBotTypFloat); + if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); + var = var->GivNext(); + + if ( var != 0 ) return CBotTypResult(CBotErrOverParam); + return CBotTypResult(CBotTypFloat); +} + +// Instruction "receive(nom, power)". + +BOOL rReceive(CBotVar* var, CBotVar* result, int& exception, void* user) +{ + CScript* script = ((CObject*)user)->RetRunScript(); + CObject* pThis = (CObject*)user; + CBotString cbs; + Error err; + const char* p; + float value, power; + + exception = 0; + + if ( script->m_primaryTask == 0 ) // no task in progress? + { + script->m_primaryTask = new CTaskManager(script->m_iMan, script->m_object); + + cbs = var->GivValString(); + p = cbs; + var = var->GivNext(); + + power = 10.0f*g_unit; + if ( var != 0 ) + { + power = var->GivValFloat()*g_unit; + var = var->GivNext(); + } + + err = script->m_primaryTask->StartTaskInfo((char*)p, 0.0f, power, FALSE); + if ( err != ERR_OK ) + { + delete script->m_primaryTask; + script->m_primaryTask = 0; + result->SetInit(IS_NAN); + return TRUE; + } + } + if ( !Process(script, result, exception) ) return FALSE; // not finished + + value = pThis->RetInfoReturn(); + if ( value == NAN ) + { + result->SetInit(IS_NAN); + } + else + { + result->SetValFloat(value); + } + return TRUE; +} + +// Compilation of the instruction "send(nom, value, power)". + +CBotTypResult cSend(CBotVar* &var, void* user) +{ + if ( var == 0 ) return CBotTypResult(CBotErrLowParam); + if ( var->GivType() != CBotTypString ) return CBotTypResult(CBotErrBadString); + var = var->GivNext(); + + if ( var == 0 ) return CBotTypResult(CBotErrLowParam); + if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); + var = var->GivNext(); + + if ( var == 0 ) return CBotTypResult(CBotTypFloat); + if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); + var = var->GivNext(); + + if ( var != 0 ) return CBotTypResult(CBotErrOverParam); + return CBotTypResult(CBotTypFloat); +} + +// Instruction "send(nom, value, power)". + +BOOL rSend(CBotVar* var, CBotVar* result, int& exception, void* user) +{ + CScript* script = ((CObject*)user)->RetRunScript(); + CObject* pThis = (CObject*)user; + CBotString cbs; + Error err; + const char* p; + float value, power; + + exception = 0; + + if ( script->m_primaryTask == 0 ) // no task in progress? + { + script->m_primaryTask = new CTaskManager(script->m_iMan, script->m_object); + + cbs = var->GivValString(); + p = cbs; + var = var->GivNext(); + + value = var->GivValFloat(); + var = var->GivNext(); + + power = 10.0f*g_unit; + if ( var != 0 ) + { + power = var->GivValFloat()*g_unit; + var = var->GivNext(); + } + + err = script->m_primaryTask->StartTaskInfo((char*)p, value, power, TRUE); + if ( err != ERR_OK ) + { + delete script->m_primaryTask; + script->m_primaryTask = 0; + result->SetValInt(err); // shows the error + if ( script->m_errMode == ERM_STOP ) + { + exception = err; + return FALSE; + } + return TRUE; + } + } + return Process(script, result, exception); +} + +// Seeks the nearest information terminal. + +CObject* SearchInfo(CScript* script, CObject* object, float power) +{ + CObject *pObj, *pBest; + D3DVECTOR iPos, oPos; + ObjectType type; + float dist, min; + int i; + + iPos = object->RetPosition(0); + + min = 100000.0f; + pBest = 0; + for ( i=0 ; i<1000000 ; i++ ) + { + pObj = (CObject*)script->m_iMan->SearchInstance(CLASS_OBJECT, i); + if ( pObj == 0 ) break; + + type = pObj->RetType(); + if ( type != OBJECT_INFO ) continue; + + if ( !pObj->RetActif() ) continue; + + oPos = pObj->RetPosition(0); + dist = Length(oPos, iPos); + if ( dist > power ) continue; // too far? + if ( dist < min ) + { + min = dist; + pBest = pObj; + } + } + + return pBest; +} + +// Compilation of the instruction "deleteinfo(nom, power)". + +CBotTypResult cDeleteInfo(CBotVar* &var, void* user) +{ + if ( var == 0 ) return CBotTypResult(CBotErrLowParam); + if ( var->GivType() != CBotTypString ) return CBotTypResult(CBotErrBadString); + var = var->GivNext(); + + if ( var == 0 ) return CBotTypResult(CBotTypFloat); + if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); + var = var->GivNext(); + + if ( var != 0 ) return CBotTypResult(CBotErrOverParam); + return CBotTypResult(CBotTypFloat); +} + +// Instruction "deleteinfo(nom, power)". + +BOOL rDeleteInfo(CBotVar* var, CBotVar* result, int& exception, void* user) +{ + CScript* script = ((CObject*)user)->RetRunScript(); + CObject* pThis = (CObject*)user; + CObject* pInfo; + CBotString cbs; + Info info; + const char* p; + float power; + int i, total; + + exception = 0; + + cbs = var->GivValString(); + p = cbs; + var = var->GivNext(); + + power = 10.0f*g_unit; + if ( var != 0 ) + { + power = var->GivValFloat()*g_unit; + var = var->GivNext(); + } + + pInfo = SearchInfo(script, pThis, power); + if ( pInfo == 0 ) + { + result->SetValFloat(0.0f); // false + return TRUE; + } + + total = pInfo->RetInfoTotal(); + for ( i=0 ; iRetInfo(i); + if ( strcmp(info.name, p) == 0 ) + { + pInfo->DeleteInfo(i); + result->SetValFloat(1.0f); // true + return TRUE; + } + } + result->SetValFloat(0.0f); // false + return TRUE; +} + +// Compilation of the instruction "testinfo(nom, power)". + +CBotTypResult cTestInfo(CBotVar* &var, void* user) +{ + if ( var == 0 ) return CBotTypResult(CBotErrLowParam); + if ( var->GivType() != CBotTypString ) return CBotTypResult(CBotErrBadString); + var = var->GivNext(); + + if ( var == 0 ) return CBotTypResult(CBotTypBoolean); + if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); + var = var->GivNext(); + + if ( var != 0 ) return CBotTypResult(CBotErrOverParam); + return CBotTypResult(CBotTypBoolean); +} + +// Instruction "testinfo(nom, power)". + +BOOL rTestInfo(CBotVar* var, CBotVar* result, int& exception, void* user) +{ + CScript* script = ((CObject*)user)->RetRunScript(); + CObject* pThis = (CObject*)user; + CObject* pInfo; + CBotString cbs; + Info info; + const char* p; + float power; + int i, total; + + exception = 0; + + cbs = var->GivValString(); + p = cbs; + var = var->GivNext(); + + power = 10.0f*g_unit; + if ( var != 0 ) + { + power = var->GivValFloat()*g_unit; + var = var->GivNext(); + } + + pInfo = SearchInfo(script, pThis, power); + if ( pInfo == 0 ) + { + result->SetValInt(FALSE); + return TRUE; + } + + total = pInfo->RetInfoTotal(); + for ( i=0 ; iRetInfo(i); + if ( strcmp(info.name, p) == 0 ) + { + result->SetValInt(TRUE); + return TRUE; + } + } + result->SetValInt(FALSE); + return TRUE; +} + +// Instruction "thump()". + +BOOL rThump(CBotVar* var, CBotVar* result, int& exception, void* user) +{ + CScript* script = ((CObject*)user)->RetRunScript(); + Error err; + + exception = 0; + + if ( script->m_primaryTask == 0 ) // no task in progress? + { + script->m_primaryTask = new CTaskManager(script->m_iMan, script->m_object); + err = script->m_primaryTask->StartTaskTerraform(); + if ( err != ERR_OK ) + { + delete script->m_primaryTask; + script->m_primaryTask = 0; + result->SetValInt(err); // shows the error + if ( script->m_errMode == ERM_STOP ) + { + exception = err; + return FALSE; + } + return TRUE; + } + } + return Process(script, result, exception); +} + +// Instruction "recycle()". + +BOOL rRecycle(CBotVar* var, CBotVar* result, int& exception, void* user) +{ + CScript* script = ((CObject*)user)->RetRunScript(); + Error err; + + exception = 0; + + if ( script->m_primaryTask == 0 ) // no task in progress? + { + script->m_primaryTask = new CTaskManager(script->m_iMan, script->m_object); + err = script->m_primaryTask->StartTaskRecover(); + if ( err != ERR_OK ) + { + delete script->m_primaryTask; + script->m_primaryTask = 0; + result->SetValInt(err); // shows the error + if ( script->m_errMode == ERM_STOP ) + { + exception = err; + return FALSE; + } + return TRUE; + } + } + return Process(script, result, exception); +} + +// Compilation "shield(oper, radius)". + +CBotTypResult cShield(CBotVar* &var, void* user) +{ + if ( var == 0 ) return CBotTypResult(CBotErrLowParam); + if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); + var = var->GivNext(); + + if ( var == 0 ) return CBotTypResult(CBotErrLowParam); + if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); + var = var->GivNext(); + + if ( var != 0 ) return CBotTypResult(CBotErrOverParam); + + return CBotTypResult(CBotTypFloat); +} + +// Instruction "shield(oper, radius)". + +BOOL rShield(CBotVar* var, CBotVar* result, int& exception, void* user) +{ + CScript* script = ((CObject*)user)->RetRunScript(); + CObject* pThis = (CObject*)user; + float oper, radius; + Error err; + + oper = var->GivValFloat(); // 0=down, 1=up + var = var->GivNext(); + + radius = var->GivValFloat(); + if ( radius < 10.0f ) radius = 10.0f; + if ( radius > 25.0f ) radius = 25.0f; + radius = (radius-10.0f)/15.0f; + + if ( *script->m_secondaryTask == 0 ) // shield folds? + { + if ( oper == 0.0f ) // down? + { + result->SetValInt(1); // shows the error + } + else // up ? + { + pThis->SetParam(radius); + + *script->m_secondaryTask = new CTaskManager(script->m_iMan, script->m_object); + err = (*script->m_secondaryTask)->StartTaskShield(TSM_UP, 1000.0f); + if ( err != ERR_OK ) + { + delete *script->m_secondaryTask; + *script->m_secondaryTask = 0; + result->SetValInt(err); // shows the error + } + } + } + else // shield deployed? + { + if ( oper == 0.0f ) // down? + { + (*script->m_secondaryTask)->StartTaskShield(TSM_DOWN, 0.0f); + } + else // up? + { +//? result->SetValInt(1); // shows the error + pThis->SetParam(radius); + (*script->m_secondaryTask)->StartTaskShield(TSM_UPDATE, 0.0f); + } + } + + return TRUE; +} + +// Compilation "fire(delay)". + +CBotTypResult cFire(CBotVar* &var, void* user) +{ +#if 0 + CObject* pThis = (CObject*)user; + ObjectType type; + + type = pThis->RetType(); + + if ( type == OBJECT_ANT ) + { + return cOnePoint(var, user); + } + else if ( type == OBJECT_SPIDER ) + { + return cNull(var, user); + } + else + { + if ( var == 0 ) return CBotTypResult(CBotTypFloat); + if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); + var = var->GivNext(); + if ( var != 0 ) return CBotTypResult(CBotErrOverParam); + return CBotTypResult(CBotTypFloat); + } +#else + return CBotTypResult(CBotTypFloat); +#endif +} + +// Instruction "fire(delay)". + +BOOL rFire(CBotVar* var, CBotVar* result, int& exception, void* user) +{ + CScript* script = ((CObject*)user)->RetRunScript(); + CObject* pThis = (CObject*)user; + float delay; + D3DVECTOR impact; + Error err; + ObjectType type; + + exception = 0; + + if ( script->m_primaryTask == 0 ) // no task in progress? + { + script->m_primaryTask = new CTaskManager(script->m_iMan, script->m_object); + + type = pThis->RetType(); + + if ( type == OBJECT_ANT ) + { + if ( !GetPoint(var, exception, impact) ) return TRUE; + impact.y += pThis->RetWaterLevel(); + err = script->m_primaryTask->StartTaskFireAnt(impact); + } + else if ( type == OBJECT_SPIDER ) + { + err = script->m_primaryTask->StartTaskSpiderExplo(); + } + else + { + if ( var == 0 ) delay = 0.0f; + else delay = var->GivValFloat(); + err = script->m_primaryTask->StartTaskFire(delay); + } + + if ( err != ERR_OK ) + { + delete script->m_primaryTask; + script->m_primaryTask = 0; + result->SetValInt(err); // shows the error + return TRUE; + } + } + return Process(script, result, exception); +} + +// Instruction "aim(dir)". + +BOOL rAim(CBotVar* var, CBotVar* result, int& exception, void* user) +{ + CScript* script = ((CObject*)user)->RetRunScript(); + float value; + Error err; + + exception = 0; + + if ( script->m_primaryTask == 0 ) // no task in progress? + { + script->m_primaryTask = new CTaskManager(script->m_iMan, script->m_object); + value = var->GivValFloat(); + err = script->m_primaryTask->StartTaskGunGoal(value*PI/180.0f, 0.0f); + if ( err != ERR_OK ) + { + delete script->m_primaryTask; + script->m_primaryTask = 0; + result->SetValInt(err); // shows the error + return TRUE; + } + } + return Process(script, result, exception); +} + +// Compilation of the instruction "motor(left, right)". + +CBotTypResult cMotor(CBotVar* &var, void* user) +{ + if ( var == 0 ) return CBotTypResult(CBotErrLowParam); + if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); + var = var->GivNext(); + + if ( var == 0 ) return CBotTypResult(CBotErrLowParam); + if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); + var = var->GivNext(); + + if ( var != 0 ) return CBotTypResult(CBotErrOverParam); + + return CBotTypResult(CBotTypFloat); +} + +// Instruction "motor(left, right)". + +BOOL rMotor(CBotVar* var, CBotVar* result, int& exception, void* user) +{ + CObject* pThis = (CObject*)user; + CPhysics* physics = ((CObject*)user)->RetPhysics(); + float left, right, speed, turn; + + left = var->GivValFloat(); + var = var->GivNext(); + right = var->GivValFloat(); + + speed = (left+right)/2.0f; + if ( speed < -1.0f ) speed = -1.0f; + if ( speed > 1.0f ) speed = 1.0f; + + turn = left-right; + if ( turn < -1.0f ) turn = -1.0f; + if ( turn > 1.0f ) turn = 1.0f; + + if ( pThis->RetFixed() ) // ant on the back? + { + speed = 0.0f; + turn = 0.0f; + } + + physics->SetMotorSpeedX(speed); // forward/backward + physics->SetMotorSpeedZ(turn); // turns + + return TRUE; +} + +// Instruction "jet(power)". + +BOOL rJet(CBotVar* var, CBotVar* result, int& exception, void* user) +{ + CPhysics* physics = ((CObject*)user)->RetPhysics(); + float value; + + value = var->GivValFloat(); + physics->SetMotorSpeedY(value); + + return TRUE; +} + +// Compilation of the instruction "topo(pos)". + +CBotTypResult cTopo(CBotVar* &var, void* user) +{ + CBotTypResult ret; + + if ( var == 0 ) return CBotTypResult(CBotErrLowParam); + ret = cPoint(var, user); + if ( ret.GivType() != 0 ) return ret; + + if ( var == 0 ) return CBotTypResult(CBotTypFloat); + return CBotTypResult(CBotErrOverParam); +} + +// Instruction "topo(pos)". + +BOOL rTopo(CBotVar* var, CBotVar* result, int& exception, void* user) +{ + CScript* script = ((CObject*)user)->RetRunScript(); + D3DVECTOR pos; + float level; + + exception = 0; + + if ( !GetPoint(var, exception, pos) ) return TRUE; + + level = script->m_terrain->RetFloorLevel(pos); + level -= script->m_water->RetLevel(); + result->SetValFloat(level/g_unit); + return TRUE; +} + +// Compilation of the instruction "message(string, type)". + +CBotTypResult cMessage(CBotVar* &var, void* user) +{ + if ( var == 0 ) return CBotTypResult(CBotErrLowParam); + if ( var->GivType() != CBotTypString && + var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); + var = var->GivNext(); + + if ( var == 0 ) return CBotTypResult(CBotTypFloat); + if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); + var = var->GivNext(); + + if ( var == 0 ) return CBotTypResult(CBotTypFloat); + return CBotTypResult(CBotErrOverParam); +} + +// Instruction "message(string, type)". + +BOOL rMessage(CBotVar* var, CBotVar* result, int& exception, void* user) +{ + CScript* script = ((CObject*)user)->RetRunScript(); + CBotString cbs; + const char* p; + TextType type; + + cbs = var->GivValString(); + p = cbs; + + type = TT_MESSAGE; + var = var->GivNext(); + if ( var != 0 ) + { + type = (TextType)var->GivValInt(); + } + + script->m_displayText->DisplayText((char*)p, script->m_object, 10.0f, type); + script->m_main->CheckEndMessage((char*)p); + + return TRUE; +} + +// Instruction "cmdline(rank)". + +BOOL rCmdline(CBotVar* var, CBotVar* result, int& exception, void* user) +{ + CScript* script = ((CObject*)user)->RetRunScript(); + CObject* pThis = (CObject*)user; + float value; + int rank; + + rank = var->GivValInt(); + value = pThis->RetCmdLine(rank); + result->SetValFloat(value); + + return TRUE; +} + +// Instruction "ismovie()". + +BOOL rIsMovie(CBotVar* var, CBotVar* result, int& exception, void* user) +{ + CScript* script = ((CObject*)user)->RetRunScript(); + float value; + + value = script->m_main->RetMovieLock()?1.0f:0.0f; + result->SetValFloat(value); + + return TRUE; +} + +// Instruction "errmode(mode)". + +BOOL rErrMode(CBotVar* var, CBotVar* result, int& exception, void* user) +{ + CScript* script = ((CObject*)user)->RetRunScript(); + int value; + + value = var->GivValInt(); + if ( value < 0 ) value = 0; + if ( value > 1 ) value = 1; + script->m_errMode = value; + + return TRUE; +} + +// Instruction "ipf(num)". + +BOOL rIPF(CBotVar* var, CBotVar* result, int& exception, void* user) +{ + CScript* script = ((CObject*)user)->RetRunScript(); + int value; + + value = var->GivValInt(); + if ( value < 1 ) value = 1; + if ( value > 10000 ) value = 10000; + script->m_ipf = value; + + return TRUE; +} + +// Instruction "abstime()". + +BOOL rAbsTime(CBotVar* var, CBotVar* result, int& exception, void* user) +{ + CScript* script = ((CObject*)user)->RetRunScript(); + float value; + + value = script->m_main->RetGameTime(); + result->SetValFloat(value); + return TRUE; +} + + +// Prepares a file name. + +void PrepareFilename(CBotString &filename, char *dir) +{ + int pos; + + pos = filename.ReverseFind('\\'); + if ( pos > 0 ) + { + filename = filename.Mid(pos+1); // removes folders + } + + pos = filename.ReverseFind('/'); + if ( pos > 0 ) + { + filename = filename.Mid(pos+1); // also those with / + } + + pos = filename.ReverseFind(':'); + if ( pos > 0 ) + { + filename = filename.Mid(pos+1); // also removes the drive letter C: + } + + filename = CBotString(dir) + CBotString("\\") + filename; +} + +// Instruction "deletefile(filename)". + +BOOL rDeleteFile(CBotVar* var, CBotVar* result, int& exception, void* user) +{ + CScript* script = ((CObject*)user)->RetRunScript(); + CBotString cbs; + const char* p; + char* dir; + + cbs = var->GivValString(); + dir = script->m_main->RetFilesDir(); + PrepareFilename(cbs, dir); + p = cbs; + DeleteFile(p); + + return TRUE; +} + +// Compilation of the instruction "pendown(color, width)". + +CBotTypResult cPenDown(CBotVar* &var, void* user) +{ + if ( var == 0 ) return CBotTypResult(CBotTypFloat); + if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); + var = var->GivNext(); + + if ( var == 0 ) return CBotTypResult(CBotTypFloat); + if ( var->GivType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum); + var = var->GivNext(); + + if ( var == 0 ) return CBotTypResult(CBotTypFloat); + return CBotTypResult(CBotErrOverParam); +} + +// Instruction "pendown(color, width)". + +BOOL rPenDown(CBotVar* var, CBotVar* result, int& exception, void* user) +{ + CScript* script = ((CObject*)user)->RetRunScript(); + CObject* pThis = (CObject*)user; + int color; + float width; + Error err; + + if ( pThis->RetType() == OBJECT_MOBILEdr ) + { + exception = 0; + + if ( script->m_primaryTask == 0 ) // no task in progress? + { + if ( var != 0 ) + { + color = var->GivValInt(); + if ( color < 0 ) color = 0; + if ( color > 17 ) color = 17; + pThis->SetTraceColor(color); + + var = var->GivNext(); + if ( var != 0 ) + { + width = var->GivValFloat(); + if ( width < 0.1f ) width = 0.1f; + if ( width > 1.0f ) width = 1.0f; + pThis->SetTraceWidth(width); + } + } + pThis->SetTraceDown(TRUE); + + script->m_primaryTask = new CTaskManager(script->m_iMan, script->m_object); + err = script->m_primaryTask->StartTaskPen(pThis->RetTraceDown(), pThis->RetTraceColor()); + if ( err != ERR_OK ) + { + delete script->m_primaryTask; + script->m_primaryTask = 0; + result->SetValInt(err); // shows the error + if ( script->m_errMode == ERM_STOP ) + { + exception = err; + return FALSE; + } + return TRUE; + } + } + return Process(script, result, exception); + } + else + { + if ( var != 0 ) + { + color = var->GivValInt(); + if ( color < 0 ) color = 0; + if ( color > 17 ) color = 17; + pThis->SetTraceColor(color); + + var = var->GivNext(); + if ( var != 0 ) + { + width = var->GivValFloat(); + if ( width < 0.1f ) width = 0.1f; + if ( width > 1.0f ) width = 1.0f; + pThis->SetTraceWidth(width); + } + } + pThis->SetTraceDown(TRUE); + + return TRUE; + } +} + +// Instruction "penup()". + +BOOL rPenUp(CBotVar* var, CBotVar* result, int& exception, void* user) +{ + CScript* script = ((CObject*)user)->RetRunScript(); + CObject* pThis = (CObject*)user; + Error err; + + if ( pThis->RetType() == OBJECT_MOBILEdr ) + { + exception = 0; + + if ( script->m_primaryTask == 0 ) // no task in progress? + { + pThis->SetTraceDown(FALSE); + + script->m_primaryTask = new CTaskManager(script->m_iMan, script->m_object); + err = script->m_primaryTask->StartTaskPen(pThis->RetTraceDown(), pThis->RetTraceColor()); + if ( err != ERR_OK ) + { + delete script->m_primaryTask; + script->m_primaryTask = 0; + result->SetValInt(err); // shows the error + if ( script->m_errMode == ERM_STOP ) + { + exception = err; + return FALSE; + } + return TRUE; + } + } + return Process(script, result, exception); + } + else + { + pThis->SetTraceDown(FALSE); + return TRUE; + } +} + +// Instruction "pencolor()". + +BOOL rPenColor(CBotVar* var, CBotVar* result, int& exception, void* user) +{ + CScript* script = ((CObject*)user)->RetRunScript(); + CPhysics* physics = ((CObject*)user)->RetPhysics(); + CObject* pThis = (CObject*)user; + int color; + Error err; + + if ( pThis->RetType() == OBJECT_MOBILEdr ) + { + exception = 0; + + if ( script->m_primaryTask == 0 ) // no task in progress? + { + color = var->GivValInt(); + if ( color < 0 ) color = 0; + if ( color > 17 ) color = 17; + pThis->SetTraceColor(color); + + script->m_primaryTask = new CTaskManager(script->m_iMan, script->m_object); + err = script->m_primaryTask->StartTaskPen(pThis->RetTraceDown(), pThis->RetTraceColor()); + if ( err != ERR_OK ) + { + delete script->m_primaryTask; + script->m_primaryTask = 0; + result->SetValInt(err); // shows the error + if ( script->m_errMode == ERM_STOP ) + { + exception = err; + return FALSE; + } + return TRUE; + } + } + return Process(script, result, exception); + } + else + { + color = var->GivValInt(); + if ( color < 0 ) color = 0; + if ( color > 17 ) color = 17; + pThis->SetTraceColor(color); + + return TRUE; + } +} + +// Instruction "penwidth()". + +BOOL rPenWidth(CBotVar* var, CBotVar* result, int& exception, void* user) +{ + CObject* pThis = (CObject*)user; + float width; + + width = var->GivValFloat(); + if ( width < 0.1f ) width = 0.1f; + if ( width > 1.0f ) width = 1.0f; + pThis->SetTraceWidth(width); + return TRUE; +} + + + +// Object's constructor. + +CScript::CScript(CInstanceManager* iMan, CObject* object, CTaskManager** secondaryTask) +{ + m_iMan = iMan; + m_iMan->AddInstance(CLASS_SCRIPT, this, 100); + + m_engine = (CD3DEngine*)m_iMan->SearchInstance(CLASS_ENGINE); + m_interface = (CInterface*)m_iMan->SearchInstance(CLASS_INTERFACE); + m_displayText = (CDisplayText*)m_iMan->SearchInstance(CLASS_DISPLAYTEXT); + m_main = (CRobotMain*)m_iMan->SearchInstance(CLASS_MAIN); + m_terrain = (CTerrain*)m_iMan->SearchInstance(CLASS_TERRAIN); + m_water = (CWater*)m_iMan->SearchInstance(CLASS_WATER); + m_botProg = 0; + m_object = object; + m_primaryTask = 0; + m_secondaryTask = secondaryTask; + + m_ipf = CBOT_IPF; + m_errMode = ERM_STOP; + m_len = 0; + m_script = 0; + m_bRun = FALSE; + m_bStepMode = FALSE; + m_bCompile = FALSE; + m_title[0] = 0; + m_cursor1 = 0; + m_cursor2 = 0; + m_filename[0] = 0; +} + +// Initializes all functions for module CBOT. + +void CScript::InitFonctions() +{ + CBotProgram::AddFunction("sin", rSin, cOneFloat); + CBotProgram::AddFunction("cos", rCos, cOneFloat); + CBotProgram::AddFunction("tan", rTan, cOneFloat); + CBotProgram::AddFunction("asin", raSin, cOneFloat); + CBotProgram::AddFunction("acos", raCos, cOneFloat); + CBotProgram::AddFunction("atan", raTan, cOneFloat); + CBotProgram::AddFunction("sqrt", rSqrt, cOneFloat); + CBotProgram::AddFunction("pow", rPow, cTwoFloat); + CBotProgram::AddFunction("rand", rRand, cNull); + CBotProgram::AddFunction("abs", rAbs, cOneFloat); + + CBotProgram::AddFunction("retobject", rRetObject, cRetObject); + CBotProgram::AddFunction("search", rSearch, cSearch); + CBotProgram::AddFunction("radar", rRadar, cRadar); + CBotProgram::AddFunction("detect", rDetect, cDetect); + CBotProgram::AddFunction("direction", rDirection, cDirection); + CBotProgram::AddFunction("produce", rProduce, cProduce); + CBotProgram::AddFunction("distance", rDistance, cDistance); + CBotProgram::AddFunction("distance2d",rDistance2d,cDistance); + CBotProgram::AddFunction("space", rSpace, cSpace); + CBotProgram::AddFunction("flatground",rFlatGround,cFlatGround); + CBotProgram::AddFunction("wait", rWait, cOneFloat); + CBotProgram::AddFunction("move", rMove, cOneFloat); + CBotProgram::AddFunction("turn", rTurn, cOneFloat); + CBotProgram::AddFunction("goto", rGoto, cGoto); + CBotProgram::AddFunction("find", rFind, cOneFloat); + CBotProgram::AddFunction("grab", rGrab, cGrabDrop); + CBotProgram::AddFunction("drop", rDrop, cGrabDrop); + CBotProgram::AddFunction("sniff", rSniff, cNull); + CBotProgram::AddFunction("receive", rReceive, cReceive); + CBotProgram::AddFunction("send", rSend, cSend); + CBotProgram::AddFunction("deleteinfo",rDeleteInfo,cDeleteInfo); + CBotProgram::AddFunction("testinfo", rTestInfo, cTestInfo); + CBotProgram::AddFunction("thump", rThump, cNull); + CBotProgram::AddFunction("recycle", rRecycle, cNull); + CBotProgram::AddFunction("shield", rShield, cShield); + CBotProgram::AddFunction("fire", rFire, cFire); + CBotProgram::AddFunction("aim", rAim, cOneFloat); + CBotProgram::AddFunction("motor", rMotor, cMotor); + CBotProgram::AddFunction("jet", rJet, cOneFloat); + CBotProgram::AddFunction("topo", rTopo, cTopo); + CBotProgram::AddFunction("message", rMessage, cMessage); + CBotProgram::AddFunction("cmdline", rCmdline, cOneFloat); + CBotProgram::AddFunction("ismovie", rIsMovie, cNull); + CBotProgram::AddFunction("errmode", rErrMode, cOneFloat); + CBotProgram::AddFunction("ipf", rIPF, cOneFloat); + CBotProgram::AddFunction("abstime", rAbsTime, cNull); + CBotProgram::AddFunction("deletefile",rDeleteFile,cString); + CBotProgram::AddFunction("pendown", rPenDown, cPenDown); + CBotProgram::AddFunction("penup", rPenUp, cNull); + CBotProgram::AddFunction("pencolor", rPenColor, cOneFloat); + CBotProgram::AddFunction("penwidth", rPenWidth, cOneFloat); +} + +// Object's destructor. + +CScript::~CScript() +{ + delete m_botProg; + delete m_primaryTask; + delete m_script; + m_script = 0; + m_len = 0; + + m_iMan->DeleteInstance(CLASS_SCRIPT, this); +} + + +// Gives the script editable block of text. + +void CScript::PutScript(CEdit* edit, char* name) +{ + if ( m_script == 0 ) + { + New(edit, name); + } + else + { + edit->SetText(m_script); + edit->SetCursor(m_cursor2, m_cursor1); + edit->ShowSelect(); + } + edit->SetFocus(TRUE); +} + +// The script takes a paved text. + +BOOL CScript::GetScript(CEdit* edit) +{ + int len; + + delete m_script; + m_script = 0; + + len = edit->RetTextLength(); + m_script = (char*)malloc(sizeof(char)*(len+1)); + + edit->GetText(m_script, len+1); + edit->GetCursor(m_cursor2, m_cursor1); + m_len = strlen(m_script); + + if ( !CheckToken() ) + { + edit->SetCursor(m_cursor2, m_cursor1); + edit->ShowSelect(); + edit->SetFocus(TRUE); + return FALSE; + } + + if ( !Compile() ) + { + edit->SetCursor(m_cursor2, m_cursor1); + edit->ShowSelect(); + edit->SetFocus(TRUE); + return FALSE; + } + + return TRUE; +} + +// Indicates whether a program is compiled correctly. + +BOOL CScript::RetCompile() +{ + return m_bCompile; +} + +// Indicates whether the program is empty. + +BOOL CScript::IsEmpty() +{ + int i; + + for ( i=0 ; iRetCheckToken() ) return TRUE; + + m_error = 0; + m_title[0] = 0; + m_token[0] = 0; + m_bCompile = FALSE; + + for ( i=0 ; iRetObligatoryToken() ; i++ ) + { + used[i] = 0; // token not used + } + + bt = CBotToken::CompileTokens(m_script, error); + while ( bt != 0 ) + { + bs = bt->GivString(); + token = bs; + type = bt->GivType(); + + cursor1 = bt->GivStart(); + cursor2 = bt->GivEnd(); + + i = m_main->IsObligatoryToken((char*)token); + if ( i != -1 ) + { + used[i] = 1; // token used + } + + if ( !m_main->IsProhibitedToken((char*)token) ) + { + m_error = ERR_PROHIBITEDTOKEN; + m_cursor1 = cursor1; + m_cursor2 = cursor2; + strcpy(m_title, ""); + CBotToken::Delete(bt); + return FALSE; + } + + bt = bt->GivNext(); + } + + // At least once every obligatory instruction? + for ( i=0 ; iRetObligatoryToken() ; i++ ) + { + if ( used[i] == 0 ) // token not used? + { + strcpy(m_token, m_main->RetObligatoryToken(i)); + m_error = ERR_OBLIGATORYTOKEN; + strcpy(m_title, ""); + CBotToken::Delete(bt); + return FALSE; + } + } + + CBotToken::Delete(bt); + return TRUE; +} + +// Compile the script of a paved text. + +BOOL CScript::Compile() +{ + CBotStringArray liste; + int i; + const char* p; + + m_error = 0; + m_cursor1 = 0; + m_cursor2 = 0; + m_title[0] = 0; + m_bCompile = FALSE; + + if ( IsEmpty() ) // program exist? + { + delete m_botProg; + m_botProg = 0; + return TRUE; + } + + if ( m_botProg == 0 ) + { + m_botProg = new CBotProgram(m_object->RetBotVar()); + } + + if ( m_botProg->Compile(m_script, liste, this) ) + { + if ( liste.GivSize() == 0 ) + { + strcpy(m_title, ""); + } + else + { + p = liste[0]; + i = 0; + while ( TRUE ) + { + if ( p[i] == 0 || p[i] == '(' ) break; + if ( i >= 20 ) + { + m_title[i++] = '.'; + m_title[i++] = '.'; + m_title[i++] = '.'; + break; + } + m_title[i] = p[i]; + i ++; + } + m_title[i] = 0; + } + m_bCompile = TRUE; + return TRUE; + } + else + { + m_botProg->GetError(m_error, m_cursor1, m_cursor2); + if ( m_cursor1 < 0 || m_cursor1 > m_len || + m_cursor2 < 0 || m_cursor2 > m_len ) + { + m_cursor1 = 0; + m_cursor2 = 0; + } + if ( m_error == 0 ) + { + m_cursor1 = m_cursor2 = 0; + } + strcpy(m_title, ""); + return FALSE; + } +} + + +// Returns the title of the script. + +void CScript::GetTitle(char* buffer) +{ + strcpy(buffer, m_title); +} + + +// Choice of mode of execution. + +void CScript::SetStepMode(BOOL bStep) +{ + m_bStepMode = bStep; +} + + +// Runs the program from the beginning. + +BOOL CScript::Run() +{ + if( m_botProg == 0 ) return FALSE; + if ( m_script == 0 || m_len == 0 ) return FALSE; + + if ( !m_botProg->Start(m_title) ) return FALSE; + + m_object->SetRunScript(this); + m_bRun = TRUE; + m_bContinue = FALSE; + m_ipf = CBOT_IPF; + m_errMode = ERM_STOP; + + if ( m_bStepMode ) // step by step mode? + { + Event newEvent; + ZeroMemory(&newEvent, sizeof(Event)); + Step(newEvent); + } + + return TRUE; +} + +// Continues the execution of current program. +// Returns TRUE when execution is finished. + +BOOL CScript::Continue(const Event &event) +{ + if( m_botProg == 0 ) return TRUE; + if ( !m_bRun ) return TRUE; + + m_event = event; + + if ( m_bStepMode ) // step by step mode? + { + if ( m_bContinue ) // instuction "move", "goto", etc. ? + { + if ( m_botProg->Run(m_object, 0) ) + { + m_botProg->GetError(m_error, m_cursor1, m_cursor2); + if ( m_cursor1 < 0 || m_cursor1 > m_len || + m_cursor2 < 0 || m_cursor2 > m_len ) + { + m_cursor1 = 0; + m_cursor2 = 0; + } + if ( m_error == 0 ) + { + m_cursor1 = m_cursor2 = 0; + } + m_bRun = FALSE; + + if ( m_error != 0 && m_errMode == ERM_STOP ) + { + char s[100]; + GetError(s); + m_displayText->DisplayText(s, m_object, 10.0f, TT_ERROR); + } + m_engine->SetPause(TRUE); // gives pause + return TRUE; + } + if ( !m_bContinue ) + { + m_engine->SetPause(TRUE); // gives pause + } + } + + return FALSE; + } + + if ( m_botProg->Run(m_object, m_ipf) ) + { + m_botProg->GetError(m_error, m_cursor1, m_cursor2); + if ( m_cursor1 < 0 || m_cursor1 > m_len || + m_cursor2 < 0 || m_cursor2 > m_len ) + { + m_cursor1 = 0; + m_cursor2 = 0; + } + if ( m_error == 0 ) + { + m_cursor1 = m_cursor2 = 0; + } + m_bRun = FALSE; + + if ( m_error != 0 && m_errMode == ERM_STOP ) + { + char s[100]; + GetError(s); + m_displayText->DisplayText(s, m_object, 10.0f, TT_ERROR); + } + return TRUE; + } + + return FALSE; +} + +// Continues the execution of current program. +// Returns TRUE when execution is finished. + +BOOL CScript::Step(const Event &event) +{ + if( m_botProg == 0 ) return TRUE; + if ( !m_bRun ) return TRUE; + if ( !m_bStepMode ) return FALSE; + + m_engine->SetPause(FALSE); + m_engine->StepSimul(0.01f); // advance of 10ms + m_engine->SetPause(TRUE); + + m_event = event; + + if ( m_botProg->Run(m_object, 0) ) // step mode + { + m_botProg->GetError(m_error, m_cursor1, m_cursor2); + if ( m_cursor1 < 0 || m_cursor1 > m_len || + m_cursor2 < 0 || m_cursor2 > m_len ) + { + m_cursor1 = 0; + m_cursor2 = 0; + } + if ( m_error == 0 ) + { + m_cursor1 = m_cursor2 = 0; + } + m_bRun = FALSE; + + if ( m_error != 0 && m_errMode == ERM_STOP ) + { + char s[100]; + GetError(s); + m_displayText->DisplayText(s, m_object, 10.0f, TT_ERROR); + } + return TRUE; + } + + if ( m_bContinue ) // instuction "move", "goto", etc. ? + { + m_engine->SetPause(FALSE); // removes the pause + } + return FALSE; +} + +// Stops the program. + +void CScript::Stop() +{ + if ( !m_bRun ) return; + + if( m_botProg != 0 ) + { + m_botProg->Stop(); + } + + if ( m_primaryTask != 0 ) + { + m_primaryTask->Abort(); + delete m_primaryTask; + m_primaryTask = 0; + } + + m_bRun = FALSE; +} + +// Indicates whether the program runs. + +BOOL CScript::IsRunning() +{ + return m_bRun; +} + +// Indicates whether the program continues a step. + +BOOL CScript::IsContinue() +{ + return m_bContinue; +} + + +// Gives the position of the cursor during the execution. + +BOOL CScript::GetCursor(int &cursor1, int &cursor2) +{ + const char* funcName; + + cursor1 = cursor2 = 0; + + if( m_botProg == 0 ) return FALSE; + if ( !m_bRun ) return FALSE; + + m_botProg->GetRunPos(funcName, cursor1, cursor2); + if ( cursor1 < 0 || cursor1 > m_len || + cursor2 < 0 || cursor2 > m_len ) + { + cursor1 = 0; + cursor2 = 0; + } + return TRUE; +} + + +// Put of the variables in a list. + +void PutList(char *baseName, BOOL bArray, CBotVar *var, CList *list, int &rankList) +{ + CBotString bs; + CBotVar *svar, *pStatic; + char varName[100]; + char buffer[100]; + const char *p; + int index, type; + + if ( var == 0 && baseName[0] != 0 ) + { + sprintf(buffer, "%s = null;", baseName); + list->SetName(rankList++, buffer); + return; + } + + index = 0; + while ( var != 0 ) + { + var->Maj(NULL, FALSE); + pStatic = var->GivStaticVar(); // finds the static element + + bs = pStatic->GivName(); // variable name + p = bs; +//? if ( strcmp(p, "this") == 0 ) +//? { +//? var = var->GivNext(); +//? continue; +//? } + + if ( baseName[0] == 0 ) + { + sprintf(varName, "%s", p); + } + else + { + if ( bArray ) + { + sprintf(varName, "%s[%d]", baseName, index); + } + else + { + sprintf(varName, "%s.%s", baseName, p); + } + } + + type = pStatic->GivType(); + + if ( type < CBotTypBoolean ) + { + CBotString value; + value = pStatic->GivValString(); + p = value; + sprintf(buffer, "%s = %s;", varName, p); + list->SetName(rankList++, buffer); + } + else if ( type == CBotTypString ) + { + CBotString value; + value = pStatic->GivValString(); + p = value; + sprintf(buffer, "%s = \"%s\";", varName, p); + list->SetName(rankList++, buffer); + } + else if ( type == CBotTypArrayPointer ) + { + svar = pStatic->GivItemList(); + PutList(varName, TRUE, svar, list, rankList); + } + else if ( type == CBotTypClass || + type == CBotTypPointer ) + { + svar = pStatic->GivItemList(); + PutList(varName, FALSE, svar, list, rankList); + } + else + { + sprintf(buffer, "%s = ?;", varName); + list->SetName(rankList++, buffer); + } + + index ++; + var = var->GivNext(); + } +} + +// Fills a list with variables. + +void CScript::UpdateList(CList* list) +{ + CBotVar *var; + const char *progName, *funcName; + int total, select, level, cursor1, cursor2, rank; + + if( m_botProg == 0 ) return; + + total = list->RetTotal(); + select = list->RetSelect(); + + list->Flush(); // empty list + m_botProg->GetRunPos(progName, cursor1, cursor2); + if ( progName == 0 ) return; + + level = 0; + rank = 0; + while ( TRUE ) + { + var = m_botProg->GivStackVars(funcName, level--); + if ( funcName != progName ) break; + + PutList("", FALSE, var, list, rank); + } + + if ( total == list->RetTotal() ) // same total? + { + list->SetSelect(select); + } + + list->SetTooltip(""); + list->SetState(STATE_ENABLE); +} + + +// Colorize the text according to syntax. + +void CScript::ColorizeScript(CEdit* edit) +{ + CBotToken* bt; + CBotString bs; + const char* token; + int error, type, cursor1, cursor2, color; + + edit->ClearFormat(); + + bt = CBotToken::CompileTokens(edit->RetText(), error); + while ( bt != 0 ) + { + bs = bt->GivString(); + token = bs; + type = bt->GivType(); + + cursor1 = bt->GivStart(); + cursor2 = bt->GivEnd(); + + color = 0; + if ( type >= TokenKeyWord && type < TokenKeyWord+100 ) + { + color = COLOR_TOKEN; + } + if ( type >= TokenKeyDeclare && type < TokenKeyDeclare+100 ) + { + color = COLOR_TYPE; + } + if ( type >= TokenKeyVal && type < TokenKeyVal+100 ) + { + color = COLOR_CONST; + } + if ( type == TokenTypVar ) + { + if ( IsType(token) ) + { + color = COLOR_TYPE; + } + else if ( IsFunction(token) ) + { + color = COLOR_TOKEN; + } + } + if ( type == TokenTypDef ) + { + color = COLOR_CONST; + } + + if ( cursor1 < cursor2 && color != 0 ) + { + edit->SetFormat(cursor1, cursor2, color); + } + + bt = bt->GivNext(); + } + + CBotToken::Delete(bt); +} + + +// Seeks a token at random in a script. +// Returns the index of the start of the token found, or -1. + +int SearchToken(char* script, char* token) +{ + int lScript, lToken, i, iFound; + int found[100]; + char* p; + + lScript = strlen(script); + lToken = strlen(token); + iFound = 0; + for ( i=0 ; i= 100 ) break; + } + } + + if ( iFound == 0 ) return -1; + return found[rand()%iFound]; +} + +// Removes a token in a script. + +void DeleteToken(char* script, int pos, int len) +{ + while ( TRUE ) + { + script[pos] = script[pos+len]; + if ( script[pos++] == 0 ) break; + } +} + +// Inserts a token in a script. + +void InsertToken(char* script, int pos, char* token) +{ + int lScript, lToken, i; + + lScript = strlen(script); + lToken = strlen(token); + for ( i=lScript ; i>=pos ; i-- ) + { + script[i+lToken] = script[i]; + } + memcpy(script+pos, token, lToken); +} + +// Introduces a virus into a program. + +BOOL CScript::IntroduceVirus() +{ + int i, start, iFound; + int found[11*2]; + char* newScript; + + char* names[11*2] = + { + "==", "!=", + "!=", "==", + ">", "<", + "<", ">", + "true", "false", + "false", "true", + "grab", "drop", + "drop", "grab", + "InFront", "Behind", + "Behind", "EnergyCell", + "EnergyCell", "InFront", + }; + + iFound = 0; + for ( i=0 ; i<11 ; i++ ) + { + start = SearchToken(m_script, names[i*2]); + if ( start != -1 ) + { + found[iFound++] = i*2; + found[iFound++] = start; + } + } + if ( iFound == 0 ) return FALSE; + + i = (rand()%(iFound/2))*2; + start = found[i+1]; + i = found[i+0]; + + newScript = (char*)malloc(sizeof(char)*(m_len+strlen(names[i+1])+1)); + strcpy(newScript, m_script); + delete m_script; + m_script = newScript; + + DeleteToken(m_script, start, strlen(names[i])); + InsertToken(m_script, start, names[i+1]); + m_len = strlen(m_script); + Compile(); // recompile with the virus + + return TRUE; +} + + +// Returns the number of the error. + +int CScript::RetError() +{ + return m_error; +} + +// Returns the text of the error. + +void CScript::GetError(char* buffer) +{ + if ( m_error == 0 ) + { + buffer[0] = 0; + } + else + { + if ( m_error == ERR_OBLIGATORYTOKEN ) + { + char s[100]; + GetResource(RES_ERR, m_error, s); + sprintf(buffer, s, m_token); + } + else if ( m_error < 1000 ) + { + GetResource(RES_ERR, m_error, buffer); + } + else + { + GetResource(RES_CBOT, m_error, buffer); + } + } +} + + +// New program. + +void CScript::New(CEdit* edit, char* name) +{ + FILE *file = NULL; + char res[100]; + char text[100]; + char filename[100]; + char script[500]; + char buffer[500]; + char *sf; + int cursor1, cursor2, len, i, j; + + GetResource(RES_TEXT, RT_SCRIPT_NEW, res); + if ( name[0] == 0 ) strcpy(text, res); + else strcpy(text, name); + + sprintf(script, "extern void object::%s()\n{\n\t\n\t\n\t\n}\n", text); + edit->SetText(script, FALSE); + + if ( strcmp(text, res) == 0 ) + { + cursor1 = 20; + cursor2 = 20+strlen(text); // update "New" + } + else + { + if ( edit->RetAutoIndent() ) + { + cursor1 = 20+strlen(text)+6; + cursor2 = cursor1; // cursor in { } + } + else + { + cursor1 = 20+strlen(text)+8; + cursor2 = cursor1; // cursor in { } + } + } + + edit->SetCursor(cursor2, cursor1); + edit->ShowSelect(); + edit->SetFocus(TRUE); + + sf = m_main->RetScriptFile(); + if ( sf[0] != 0 ) // Load an empty program specific? + { + strcpy(filename, "script\\"); + strcat(filename, sf); + file = fopen(filename, "rb"); + if ( file != NULL ) + { + fseek(file, 0, SEEK_END); + len = ftell(file); + fseek(file, 0, SEEK_SET); + + if ( len > 500-1 ) len = 500-1; + fread(buffer, 1, len, file); + buffer[len] = 0; + fclose(file); + + cursor1 = 0; + i = 0; + j = 0; + while ( TRUE ) + { + if ( buffer[i] == 0 ) break; + + if ( buffer[i] == '\r' ) + { + i ++; + continue; + } + + if ( buffer[i] == '\t' && edit->RetAutoIndent() ) + { + i ++; + continue; + } + + if ( buffer[i+0] == '%' && + buffer[i+1] == 's' ) + { + strcpy(script+j, text); + j += strlen(text); + i += 2; + continue; + } + + if ( buffer[i] == '#' ) + { + cursor1 = j; + i ++; + continue; + } + + script[j++] = buffer[i++]; + } + script[j] = 0; + edit->SetText(script, FALSE); + + cursor2 = cursor1; + edit->SetCursor(cursor2, cursor1); + edit->ShowSelect(); + edit->SetFocus(TRUE); + } + } + + ColorizeScript(edit); +} + + +// Provided a script for all parts. + +BOOL CScript::SendScript(char* text) +{ + m_len = strlen(text); + m_script = (char*)malloc(sizeof(char)*(m_len+1)); + strcpy(m_script, text); + if ( !CheckToken() ) return FALSE; + if ( !Compile() ) return FALSE; + + return TRUE; +} + +// Reads a script as a text file. + +BOOL CScript::ReadScript(char* filename) +{ + FILE* file; + CEdit* edit; + char name[100]; + + if ( strchr(filename, '\\') == 0 ) + { + strcpy(name, "script\\"); + strcat(name, filename); + } + else + { +//? strcpy(name, filename); + UserDir(name, filename, ""); + } + + file = fopen(name, "rb"); + if ( file == NULL ) return FALSE; + fclose(file); + + delete m_script; + m_script = 0; + + edit = m_interface->CreateEdit(FPOINT(0.0f, 0.0f), FPOINT(0.0f, 0.0f), 0, EVENT_EDIT9); + edit->SetMaxChar(EDITSTUDIOMAX); + edit->SetAutoIndent(m_engine->RetEditIndentMode()); + edit->ReadText(name); + GetScript(edit); + m_interface->DeleteControl(EVENT_EDIT9); + return TRUE; +} + +// Writes a script as a text file. + +BOOL CScript::WriteScript(char* filename) +{ + CEdit* edit; + char name[100]; + + if ( strchr(filename, '\\') == 0 ) + { + strcpy(name, "script\\"); + strcat(name, filename); + } + else + { + strcpy(name, filename); + } + + if ( m_script == 0 ) + { + remove(filename); + return FALSE; + } + + edit = m_interface->CreateEdit(FPOINT(0.0f, 0.0f), FPOINT(0.0f, 0.0f), 0, EVENT_EDIT9); + edit->SetMaxChar(EDITSTUDIOMAX); + edit->SetAutoIndent(m_engine->RetEditIndentMode()); + edit->SetText(m_script); + edit->WriteText(name); + m_interface->DeleteControl(EVENT_EDIT9); + return TRUE; +} + + +// Reads a stack of script by execution as a file. + +BOOL CScript::ReadStack(FILE *file) +{ + int nb; + + fRead(&nb, sizeof(int), 1, file); + fRead(&m_ipf, sizeof(int), 1, file); + fRead(&m_errMode, sizeof(int), 1, file); + + if ( m_botProg == 0 ) return FALSE; + if ( !m_botProg->RestoreState(file) ) return FALSE; + + m_object->SetRunScript(this); + m_bRun = TRUE; + m_bContinue = FALSE; + return TRUE; +} + +// Writes a stack of script by execution as a file. + +BOOL CScript::WriteStack(FILE *file) +{ + int nb; + + nb = 2; + fWrite(&nb, sizeof(int), 1, file); + fWrite(&m_ipf, sizeof(int), 1, file); + fWrite(&m_errMode, sizeof(int), 1, file); + + return m_botProg->SaveState(file); +} + + +// Compares two scripts. + +BOOL CScript::Compare(CScript* other) +{ + if ( m_len != other->m_len ) return FALSE; + + return ( strcmp(m_script, other->m_script) == 0 ); +} + + +// Management of the file name when the script is saved. + +void CScript::SetFilename(char *filename) +{ + strcpy(m_filename, filename); +} + +char* CScript::RetFilename() +{ + return m_filename; +} + -- cgit v1.2.3-1-g7c22