Merged CBrain into CProgrammableObject

master
krzys-h 2015-08-10 18:16:00 +02:00
parent 726cfbda77
commit abb272600e
26 changed files with 955 additions and 1187 deletions

View File

@ -149,7 +149,6 @@ set(BASE_SOURCES
object/auto/autovault.cpp
object/auto/autopowerstation.cpp
object/auto/autotower.cpp
object/brain.cpp
object/drive_type.cpp
object/level/parser.cpp
object/level/parserexceptions.cpp

View File

@ -26,7 +26,6 @@
#include "math/geometry.h"
#include "object/brain.h"
#include "object/object_manager.h"
#include "object/old_object.h"
@ -185,11 +184,11 @@ bool CAutoEgg::EventProcess(const Event &event)
if (alien->Implements(ObjectInterfaceType::Programmable))
{
CBrain* brain = dynamic_cast<CProgrammableObject*>(alien)->GetBrain();
CProgrammableObject* programmable = dynamic_cast<CProgrammableObject*>(alien);
Program* program = brain->AddProgram();
brain->ReadProgram(program, m_alienProgramName.c_str());
brain->RunProgram(program);
Program* program = programmable->AddProgram();
programmable->ReadProgram(program, m_alienProgramName.c_str());
programmable->RunProgram(program);
}
Init();
}
@ -332,4 +331,3 @@ bool CAutoEgg::Read(CLevelParserLine* line)
return true;
}

View File

@ -25,7 +25,6 @@
#include "math/geometry.h"
#include "object/brain.h"
#include "object/object_create_params.h"
#include "object/object_manager.h"
#include "object/old_object.h"
@ -408,7 +407,6 @@ bool CAutoFactory::EventProcess(const Event &event)
}
vehicle->SetLock(false); // vehicle useable
//? vehicle->GetPhysics()->GetBrain()->StartTaskAdvance(16.0f);
vehicle->SetRotationY(m_object->GetRotationY()+Math::PI);
vehicle->SetScale(1.0f);
@ -416,8 +414,8 @@ bool CAutoFactory::EventProcess(const Event &event)
{
if (vehicle->Implements(ObjectInterfaceType::Programmable))
{
CBrain* brain = dynamic_cast<CProgrammableObject*>(vehicle)->GetBrain();
Program* program = brain->AddProgram();
CProgrammableObject* programmable = dynamic_cast<CProgrammableObject*>(vehicle);
Program* program = programmable->AddProgram();
if (boost::regex_search(m_program, boost::regex("^[A-Za-z0-9_]+$"))) // Public function name?
{
@ -433,7 +431,7 @@ bool CAutoFactory::EventProcess(const Event &event)
program->script->SendScript(m_program.c_str());
}
brain->RunProgram(program);
programmable->RunProgram(program);
}
}
}
@ -680,13 +678,13 @@ bool CAutoFactory::CreateVehicle()
if (vehicle->Implements(ObjectInterfaceType::Programmable))
{
CBrain* brain = dynamic_cast<CProgrammableObject*>(vehicle)->GetBrain();
CProgrammableObject* programmable = dynamic_cast<CProgrammableObject*>(vehicle);
for ( int i=0 ; ; i++ )
{
char* name = m_main->GetNewScriptName(m_type, i);
if ( name == nullptr ) break;
Program* prog = brain->GetOrAddProgram(i);
brain->ReadProgram(prog, name);
Program* prog = programmable->GetOrAddProgram(i);
programmable->ReadProgram(prog, name);
prog->readOnly = true;
}
}

View File

@ -1,785 +0,0 @@
/*
* This file is part of the Colobot: Gold Edition source code
* Copyright (C) 2001-2014, Daniel Roux, EPSITEC SA & TerranovaTeam
* http://epsiteс.ch; http://colobot.info; http://github.com/colobot
*
* 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://gnu.org/licenses
*/
#include "object/brain.h"
#include "common/make_unique.h"
#include "math/geometry.h"
#include "object/old_object.h"
#include "object/robotmain.h"
#include "object/interface/task_executor_object.h"
#include "object/level/parserline.h"
#include "object/level/parserparam.h"
#include "object/motion/motion.h"
#include "object/motion/motionvehicle.h"
#include "object/task/taskmanager.h"
#include "physics/physics.h"
#include "script/script.h"
#include "ui/studio.h"
#include "ui/controls/edit.h"
#include <iomanip>
#include <algorithm>
const int MAXTRACERECORD = 1000;
// Object's constructor.
CBrain::CBrain(COldObject* object)
{
m_object = object;
assert(object->Implements(ObjectInterfaceType::TaskExecutor));
m_taskExecutor = dynamic_cast<CTaskExecutorObject*>(m_object);
m_physics = nullptr;
m_motion = nullptr;
m_engine = Gfx::CEngine::GetInstancePointer();
m_main = CRobotMain::GetInstancePointer();
m_camera = m_main->GetCamera();
m_program.clear();
m_currentProgram = nullptr;
m_bBurn = false;
m_bActiveVirus = false;
m_time = 0.0f;
m_burnTime = 0.0f;
m_buttonAxe = EVENT_NULL;
m_scriptRun = nullptr;
m_soluceName[0] = 0;
m_traceRecord = false;
}
// Object's destructor.
CBrain::~CBrain()
{
}
void CBrain::SetPhysics(CPhysics* physics)
{
m_physics = physics;
}
void CBrain::SetMotion(CMotion* motion)
{
m_motion = motion;
}
// Saves all parameters of the object.
bool CBrain::Write(CLevelParserLine* line)
{
line->AddParam("bVirusActive", MakeUnique<CLevelParserParam>(m_bActiveVirus));
if ( m_object->GetType() == OBJECT_MOBILErs )
{
line->AddParam("bShieldActive", MakeUnique<CLevelParserParam>(m_taskExecutor->IsBackgroundTask()));
}
return true;
}
// Restores all parameters of the object.
bool CBrain::Read(CLevelParserLine* line)
{
m_bActiveVirus = line->GetParam("bVirusActive")->AsBool(false);
if ( m_object->GetType() == OBJECT_MOBILErs )
{
if( line->GetParam("bShieldActive")->AsBool(false) )
{
m_taskExecutor->StartTaskShield(TSM_START);
}
}
return true;
}
// Management of an event.
bool CBrain::EventProcess(const Event &event)
{
if ( event.type == EVENT_FRAME )
{
EventFrame(event);
}
if ( !m_object->GetSelect() && // robot pas sélectionné ?
m_currentProgram == nullptr &&
!m_taskExecutor->IsForegroundTask() )
{
float axeX = 0.0f;
float axeY = 0.0f;
float axeZ = 0.0f;
if ( m_object->GetBurn() ) // Gifted?
{
if ( !m_bBurn ) // beginning?
{
m_bBurn = true;
m_burnTime = 0.0f;
}
axeZ = -1.0f; // tomb
if ( !m_object->GetFixed() &&
(m_object->GetType() == OBJECT_ANT ||
m_object->GetType() == OBJECT_SPIDER ||
m_object->GetType() == OBJECT_WORM ) )
{
axeY = 2.0f; // zigzag disorganized fast
if ( m_object->GetType() == OBJECT_WORM ) axeY = 5.0f;
axeX = 0.5f+sinf(m_time* 1.0f)*0.5f+
sinf(m_time* 6.0f)*2.0f+
sinf(m_time*21.0f)*0.2f;
float factor = 1.0f-m_burnTime/15.0f; // slow motion
if ( factor < 0.0f ) factor = 0.0f;
axeY *= factor;
axeX *= factor;
}
}
m_physics->SetMotorSpeedX(axeY); // move forward/move back
m_physics->SetMotorSpeedY(axeZ); // up / down
m_physics->SetMotorSpeedZ(axeX); // rotate
return true;
}
if ( m_currentProgram != nullptr &&
m_object->GetRuin() )
{
StopProgram();
return true;
}
if ( !m_object->GetSelect() ) return true; // robot not selected?
if ( m_taskExecutor->IsForegroundTask() || // current task?
m_currentProgram != nullptr )
{
if ( !m_taskExecutor->IsForegroundTask() || !m_taskExecutor->GetForegroundTask()->IsPilot() ) return true;
}
if ( event.type == EVENT_OBJECT_LEFT ||
event.type == EVENT_OBJECT_RIGHT ||
event.type == EVENT_OBJECT_UP ||
event.type == EVENT_OBJECT_DOWN ||
event.type == EVENT_OBJECT_GASUP ||
event.type == EVENT_OBJECT_GASDOWN )
{
m_buttonAxe = event.type;
}
if ( event.type == EVENT_MOUSE_BUTTON_UP )
{
m_buttonAxe = EVENT_NULL;
}
float axeX = event.motionInput.x;
float axeY = event.motionInput.y;
float axeZ = event.motionInput.z;
if ( (!m_main->GetTrainerPilot() &&
m_object->GetTrainer()) ||
!m_main->CanPlayerInteract() ) // drive vehicle?
{
axeX = 0.0f;
axeY = 0.0f;
axeZ = 0.0f; // Remote control impossible!
}
if ( m_buttonAxe == EVENT_OBJECT_LEFT ) axeX = -1.0f;
if ( m_buttonAxe == EVENT_OBJECT_RIGHT ) axeX = 1.0f;
if ( m_buttonAxe == EVENT_OBJECT_UP ) axeY = 1.0f;
if ( m_buttonAxe == EVENT_OBJECT_DOWN ) axeY = -1.0f;
if ( m_buttonAxe == EVENT_OBJECT_GASUP ) axeZ = 1.0f;
if ( m_buttonAxe == EVENT_OBJECT_GASDOWN ) axeZ = -1.0f;
if ( m_object->GetType() == OBJECT_MOBILEdr && m_object->GetManual() ) // scribbler in manual mode?
{
if ( axeX != 0.0f ) axeY = 0.0f; // if running -> not moving!
axeX *= 0.5f;
axeY *= 0.5f;
}
if ( !m_main->IsResearchDone(RESEARCH_FLY, m_object->GetTeam()) )
{
axeZ = -1.0f; // tomb
}
axeX += m_camera->GetMotorTurn(); // additional power according to camera
if ( axeX > 1.0f ) axeX = 1.0f;
if ( axeX < -1.0f ) axeX = -1.0f;
m_physics->SetMotorSpeedX(axeY); // move forward/move back
m_physics->SetMotorSpeedY(axeZ); // up/down
m_physics->SetMotorSpeedZ(axeX); // rotate
return true;
}
// The brain is changing by time.
bool CBrain::EventFrame(const Event &event)
{
m_time += event.rTime;
if ( m_bBurn ) m_burnTime += event.rTime;
if ( m_engine->GetPause() ) return true;
if ( !m_object->GetActivity() ) return true;
if ( m_currentProgram != nullptr ) // current program?
{
if ( m_currentProgram->script->Continue() )
{
StopProgram();
}
}
if ( m_traceRecord ) // registration of the design in progress?
{
TraceRecordFrame();
}
return true;
}
// Stops the running program.
void CBrain::StopProgram()
{
m_taskExecutor->StopForegroundTask();
if ( m_object->GetType() == OBJECT_HUMAN ||
m_object->GetType() == OBJECT_TECH ) return;
if ( m_currentProgram != nullptr )
{
m_currentProgram->script->Stop();
}
m_currentProgram = nullptr;
m_physics->SetMotorSpeedX(0.0f);
m_physics->SetMotorSpeedY(0.0f);
m_physics->SetMotorSpeedZ(0.0f);
m_motion->SetAction(-1);
m_object->UpdateInterface();
m_main->UpdateShortcuts();
m_object->CreateSelectParticle();
}
// Introduces a virus into a program.
// Returns true if it was inserted.
bool CBrain::IntroduceVirus()
{
if(m_program.size() == 0) return false;
for ( int i=0 ; i<50 ; i++ )
{
int j = rand()%m_program.size();
if ( m_program[j]->script->IntroduceVirus() ) // tries to introduce
{
m_bActiveVirus = true; // active virus
return true;
}
}
return false;
}
// Active Virus indicates that the object is contaminated. Unlike ch'tites (??? - Programerus)
// letters which automatically disappear after a while,
// ActiveVirus does not disappear after you edit the program
// (Even if the virus is not fixed).
void CBrain::SetActiveVirus(bool bActive)
{
m_bActiveVirus = bActive;
if ( !m_bActiveVirus ) // virus disabled?
{
m_object->SetVirusMode(false); // chtites (??? - Programerus) letters also
}
}
bool CBrain::GetActiveVirus()
{
return m_bActiveVirus;
}
// Indicates whether a program is running.
bool CBrain::IsProgram()
{
return m_currentProgram != nullptr;
}
// Starts a program.
void CBrain::RunProgram(Program* program)
{
if ( program->script->Run() )
{
m_currentProgram = program; // start new program
m_object->UpdateInterface();
m_object->CreateSelectParticle();
m_main->UpdateShortcuts();
if(m_object->GetTrainer())
m_main->StartMissionTimer();
}
}
// Returns the current program.
int CBrain::GetProgram()
{
if(m_currentProgram == nullptr)
return -1;
for(unsigned int i = 0; i < m_program.size(); i++)
{
if(m_program[i].get() == m_currentProgram)
{
return i;
}
}
return -1;
}
// Name management scripts to load.
void CBrain::SetScriptRun(Program* program)
{
m_scriptRun = program;
}
Program* CBrain::GetScriptRun()
{
return m_scriptRun;
}
void CBrain::SetSoluceName(char *name)
{
strcpy(m_soluceName, name);
}
char* CBrain::GetSoluceName()
{
return m_soluceName;
}
// Load a script solution, in the first free script.
// If there is already an identical script, nothing is loaded.
bool CBrain::ReadSoluce(char* filename)
{
Program* prog = AddProgram();
if ( !ReadProgram(prog, filename) ) return false; // load solution
prog->readOnly = true;
for(unsigned int i = 0; i < m_program.size(); i++)
{
if(m_program[i].get() == prog) continue;
//TODO: This is bad. It's very sensitive to things like \n vs \r\n etc.
if ( m_program[i]->script->Compare(prog->script.get()) ) // the same already?
{
m_program[i]->readOnly = true; // Mark is as read-only
RemoveProgram(prog);
return false;
}
}
return true;
}
// Load a script with a text file.
bool CBrain::ReadProgram(Program* program, const char* filename)
{
if ( program->script->ReadScript(filename) ) return true;
return false;
}
// Indicates whether a program is compiled correctly.
bool CBrain::GetCompile(Program* program)
{
return program->script->GetCompile();
}
// Saves a script in a text file.
bool CBrain::WriteProgram(Program* program, const char* filename)
{
if ( program->script->WriteScript(filename) ) return true;
return false;
}
// Load a stack of script implementation from a file.
bool CBrain::ReadStack(FILE *file)
{
short op;
fRead(&op, sizeof(short), 1, file);
if ( op == 1 ) // run ?
{
fRead(&op, sizeof(short), 1, file); // program rank
if ( op >= 0 )
{
assert(op < static_cast<int>(m_program.size())); //TODO: is it good?
//TODO: m_selScript = op;
if ( !m_program[op]->script->ReadStack(file) ) return false;
}
}
return true;
}
// Save the script implementation stack of a file.
bool CBrain::WriteStack(FILE *file)
{
short op;
if ( m_currentProgram != nullptr && // current program?
m_currentProgram->script->IsRunning() )
{
op = 1; // run
fWrite(&op, sizeof(short), 1, file);
op = GetProgram();
fWrite(&op, sizeof(short), 1, file);
return m_currentProgram->script->WriteStack(file);
}
op = 0; // stop
fWrite(&op, sizeof(short), 1, file);
return true;
}
// Start of registration of the design.
void CBrain::TraceRecordStart()
{
if (m_traceRecord)
{
TraceRecordStop();
}
CMotionVehicle* motionVehicle = dynamic_cast<CMotionVehicle*>(m_motion);
assert(motionVehicle != nullptr);
m_traceRecord = true;
m_traceOper = TO_STOP;
m_tracePos = m_object->GetPosition();
m_traceAngle = m_object->GetRotationY();
if ( motionVehicle->GetTraceDown() ) // pencil down?
{
m_traceColor = motionVehicle->GetTraceColor();
}
else // pen up?
{
m_traceColor = TraceColor::Default;
}
m_traceRecordBuffer = MakeUniqueArray<TraceRecord>(MAXTRACERECORD);
m_traceRecordIndex = 0;
}
// Saving the current drawing.
void CBrain::TraceRecordFrame()
{
TraceOper oper = TO_STOP;
Math::Vector pos;
float angle, len, speed;
CMotionVehicle* motionVehicle = dynamic_cast<CMotionVehicle*>(m_motion);
assert(motionVehicle != nullptr);
speed = m_physics->GetLinMotionX(MO_REASPEED);
if ( speed > 0.0f ) oper = TO_ADVANCE;
if ( speed < 0.0f ) oper = TO_RECEDE;
speed = m_physics->GetCirMotionY(MO_REASPEED);
if ( speed != 0.0f ) oper = TO_TURN;
TraceColor color = TraceColor::Default;
if ( motionVehicle->GetTraceDown() ) // pencil down?
{
color = motionVehicle->GetTraceColor();
}
if ( oper != m_traceOper ||
color != m_traceColor )
{
if ( m_traceOper == TO_ADVANCE ||
m_traceOper == TO_RECEDE )
{
pos = m_object->GetPosition();
len = Math::DistanceProjected(pos, m_tracePos);
TraceRecordOper(m_traceOper, len);
}
if ( m_traceOper == TO_TURN )
{
angle = m_object->GetRotationY()-m_traceAngle;
TraceRecordOper(m_traceOper, angle);
}
if ( color != m_traceColor )
{
TraceRecordOper(TO_PEN, static_cast<float>(color));
}
m_traceOper = oper;
m_tracePos = m_object->GetPosition();
m_traceAngle = m_object->GetRotationY();
m_traceColor = color;
}
}
// End of the registration of the design. Program generates the CBOT.
void CBrain::TraceRecordStop()
{
TraceOper lastOper, curOper;
float lastParam, curParam;
m_traceRecord = false;
std::stringstream buffer;
buffer << "extern void object::AutoDraw()\n{\n";
lastOper = TO_STOP;
lastParam = 0.0f;
for ( int i=0 ; i<m_traceRecordIndex ; i++ )
{
curOper = m_traceRecordBuffer[i].oper;
curParam = m_traceRecordBuffer[i].param;
if ( curOper == lastOper )
{
if ( curOper == TO_PEN )
{
lastParam = curParam;
}
else
{
lastParam += curParam;
}
}
else
{
TraceRecordPut(buffer, lastOper, lastParam);
lastOper = curOper;
lastParam = curParam;
}
}
TraceRecordPut(buffer, lastOper, lastParam);
m_traceRecordBuffer.reset();
buffer << "}\n";
Program* prog = AddProgram();
prog->script->SendScript(buffer.str().c_str());
}
// Saves an instruction CBOT.
bool CBrain::TraceRecordOper(TraceOper oper, float param)
{
int i;
i = m_traceRecordIndex;
if ( i >= MAXTRACERECORD ) return false;
m_traceRecordBuffer[i].oper = oper;
m_traceRecordBuffer[i].param = param;
m_traceRecordIndex = i+1;
return true;
}
// Generates an instruction CBOT.
bool CBrain::TraceRecordPut(std::stringstream& buffer, TraceOper oper, float param)
{
if ( oper == TO_ADVANCE )
{
param /= g_unit;
buffer << "\tmove(" << std::fixed << std::setprecision(1) << param << ");\n";
}
if ( oper == TO_RECEDE )
{
param /= g_unit;
buffer << "\tmove(-" << std::fixed << std::setprecision(1) << param << ");\n";
}
if ( oper == TO_TURN )
{
param = -param*180.0f/Math::PI;
buffer << "\tturn(" << static_cast<int>(param) << ");\n";
}
if ( oper == TO_PEN )
{
TraceColor color = static_cast<TraceColor>(static_cast<int>(param));
if ( color == TraceColor::Default )
buffer << "\tpenup();\n";
else
buffer << "\tpendown(" << TraceColorName(color) << ");\n";
}
return true;
}
bool CBrain::IsTraceRecord()
{
return m_traceRecord;
}
Program* CBrain::AddProgram()
{
auto program = MakeUnique<Program>();
program->script = MakeUnique<CScript>(m_object);
program->readOnly = false;
program->runnable = true;
Program* prog = program.get();
AddProgram(std::move(program));
return prog;
}
void CBrain::AddProgram(std::unique_ptr<Program> program)
{
m_program.push_back(std::move(program));
m_object->UpdateInterface();
}
void CBrain::RemoveProgram(Program* program)
{
if(m_currentProgram == program)
{
StopProgram();
}
m_program.erase(
std::remove_if(m_program.begin(), m_program.end(),
[program](std::unique_ptr<Program>& prog) { return prog.get() == program; }),
m_program.end());
}
Program* CBrain::CloneProgram(Program* program)
{
Program* newprog = AddProgram();
// TODO: Is there any reason CScript doesn't have a function to get the program code directly?
Ui::CEdit* edit = new Ui::CEdit();
edit->SetMaxChar(Ui::EDITSTUDIOMAX);
program->script->PutScript(edit, "");
newprog->script->GetScript(edit);
delete edit;
return newprog;
}
std::vector<std::unique_ptr<Program>>& CBrain::GetPrograms()
{
return m_program;
}
int CBrain::GetProgramCount()
{
return static_cast<int>(m_program.size());
}
int CBrain::GetProgramIndex(Program* program)
{
for(unsigned int i = 0; i < m_program.size(); i++)
{
if(m_program[i].get() == program)
{
return i;
}
}
return -1;
}
Program* CBrain::GetProgram(int index)
{
if(index < 0 || index >= static_cast<int>(m_program.size()))
return nullptr;
return m_program[index].get();
}
Program* CBrain::GetOrAddProgram(int index)
{
if(index < 0)
return nullptr;
if(index < static_cast<int>(m_program.size()))
return m_program[index].get();
for(int i = m_program.size(); i < index; i++)
{
AddProgram();
}
return AddProgram();
}

View File

@ -1,170 +0,0 @@
/*
* This file is part of the Colobot: Gold Edition source code
* Copyright (C) 2001-2014, Daniel Roux, EPSITEC SA & TerranovaTeam
* http://epsiteс.ch; http://colobot.info; http://github.com/colobot
*
* 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://gnu.org/licenses
*/
/**
* \file object/brain.h
* \brief CBrain - dispatches commands to objects
*/
#pragma once
#include "common/event.h"
#include "object/trace_color.h"
#include <vector>
#include <sstream>
#include <memory>
class COldObject;
class CTaskExecutorObject;
class CPhysics;
class CMotion;
class CScript;
class CRobotMain;
class CLevelParserLine;
namespace Gfx
{
class CEngine;
class CCamera;
} /* Gfx */
enum TraceOper
{
TO_STOP = 0, // stop
TO_ADVANCE = 1, // advance
TO_RECEDE = 2, // back
TO_TURN = 3, // rotate
TO_PEN = 4, // color change
};
struct TraceRecord
{
TraceOper oper;
float param;
};
struct Program
{
std::unique_ptr<CScript> script;
std::string filename;
bool readOnly;
bool runnable;
};
class CBrain
{
public:
CBrain(COldObject* object);
~CBrain();
void SetPhysics(CPhysics* physics);
void SetMotion(CMotion* motion);
bool EventProcess(const Event &event);
bool Write(CLevelParserLine* line);
bool Read(CLevelParserLine* line);
bool IsProgram();
void RunProgram(Program* program);
int GetProgram();
void StopProgram();
bool IntroduceVirus();
void SetActiveVirus(bool bActive);
bool GetActiveVirus();
void SetScriptRun(Program* rank);
Program* GetScriptRun();
void SetSoluceName(char *name);
char* GetSoluceName();
bool ReadSoluce(char* filename);
bool ReadProgram(Program* program, const char* filename);
bool GetCompile(Program* program);
bool WriteProgram(Program* program, const char* filename);
bool ReadStack(FILE *file);
bool WriteStack(FILE *file);
Program* AddProgram();
void AddProgram(std::unique_ptr<Program> program);
void RemoveProgram(Program* program);
Program* CloneProgram(Program* program);
std::vector<std::unique_ptr<Program>>& GetPrograms();
int GetProgramCount();
Program* GetProgram(int index);
Program* GetOrAddProgram(int index);
int GetProgramIndex(Program* program);
//! Start recording trace
void TraceRecordStart();
//! Stop recording trace and generate CBot program
void TraceRecordStop();
//! Returns true if trace recording is in progress
bool IsTraceRecord();
protected:
bool EventFrame(const Event &event);
//! Save current status to recording buffer
void TraceRecordFrame();
//! Save this operation to recording buffer
bool TraceRecordOper(TraceOper oper, float param);
//! Convert this recording operation to CBot instruction
bool TraceRecordPut(std::stringstream& buffer, TraceOper oper, float param);
protected:
CRobotMain* m_main;
Gfx::CEngine* m_engine;
Gfx::CCamera* m_camera;
COldObject* m_object;
CTaskExecutorObject* m_taskExecutor;
CPhysics* m_physics;
CMotion* m_motion;
std::vector<std::unique_ptr<Program>> m_program;
Program* m_currentProgram;
bool m_bBurn;
bool m_bActiveVirus;
Program* m_scriptRun;
char m_soluceName[50];
EventType m_buttonAxe;
float m_time;
float m_burnTime;
bool m_traceRecord;
TraceOper m_traceOper;
Math::Vector m_tracePos;
float m_traceAngle;
TraceColor m_traceColor;
int m_traceRecordIndex;
std::unique_ptr<TraceRecord[]> m_traceRecordBuffer;
};

View File

@ -21,7 +21,15 @@
#include "object/object_interface_type.h"
class CBrain;
class CScript;
struct Program
{
std::unique_ptr<CScript> script;
std::string filename;
bool readOnly;
bool runnable;
};
/**
* \class CProgrammableObject
@ -39,11 +47,42 @@ public:
virtual ~CProgrammableObject()
{}
//! Returns CBrain
/** If only the object implements ObjectInterfaceType::Programmable,
* returned object will always be non-null*/
virtual CBrain* GetBrain() = 0;
virtual bool IsProgram() = 0;
virtual void RunProgram(Program* program) = 0;
virtual int GetProgram() = 0;
virtual void StopProgram() = 0;
virtual bool IntroduceVirus() = 0;
virtual void SetActiveVirus(bool bActive) = 0;
virtual bool GetActiveVirus() = 0;
// TODO: CBrain interface can actually be moved here
virtual void SetScriptRun(Program* rank) = 0;
virtual Program* GetScriptRun() = 0;
virtual void SetSoluceName(char *name) = 0;
virtual char* GetSoluceName() = 0;
virtual bool ReadSoluce(char* filename) = 0;
virtual bool ReadProgram(Program* program, const char* filename) = 0;
virtual bool GetCompile(Program* program) = 0;
virtual bool WriteProgram(Program* program, const char* filename) = 0;
virtual bool ReadStack(FILE *file) = 0;
virtual bool WriteStack(FILE *file) = 0;
virtual Program* AddProgram() = 0;
virtual void AddProgram(std::unique_ptr<Program> program) = 0;
virtual void RemoveProgram(Program* program) = 0;
virtual Program* CloneProgram(Program* program) = 0;
virtual std::vector<std::unique_ptr<Program>>& GetPrograms() = 0;
virtual int GetProgramCount() = 0;
virtual Program* GetProgram(int index) = 0;
virtual Program* GetOrAddProgram(int index) = 0;
virtual int GetProgramIndex(Program* program) = 0;
//! Start recording trace
virtual void TraceRecordStart() = 0;
//! Stop recording trace and generate CBot program
virtual void TraceRecordStop() = 0;
//! Returns true if trace recording is in progress
virtual bool IsTraceRecord() = 0;
};

View File

@ -38,7 +38,6 @@ class COldModelManager;
}
class CApplication;
class CBrain;
class CPhysics;
class COldObject;
class CRobotMain;

View File

@ -30,11 +30,11 @@
#include "math/geometry.h"
#include "object/brain.h"
#include "object/object_manager.h"
#include "object/old_object.h"
#include "object/interface/powered_object.h"
#include "object/interface/programmable_object.h"
#include "object/interface/transportable_object.h"
#include "physics/physics.h"

View File

@ -35,6 +35,8 @@ namespace Gfx
struct ModelCrashSphere;
} // namespace Gfx
class CLevelParserLine;
/**
* \class CObject
* \brief Base class for all 3D in-game objects

View File

@ -30,7 +30,6 @@
#include "math/geometry.h"
#include "object/brain.h"
#include "object/object_create_params.h"
#include "object/old_object.h"
#include "object/robotmain.h"
@ -2632,7 +2631,6 @@ CObjectUPtr CObjectFactory::CreateVehicle(const ObjectCreateParams& params)
obj->SetShowLimitRadius(showLimitRadius);
auto physics = MakeUnique<CPhysics>(obj.get());
auto brain = MakeUnique<CBrain>(obj.get());
std::unique_ptr<CMotion> motion;
if ( type == OBJECT_HUMAN ||
@ -2649,14 +2647,12 @@ CObjectUPtr CObjectFactory::CreateVehicle(const ObjectCreateParams& params)
motion = MakeUnique<CMotionVehicle>(obj.get());
}
brain->SetMotion(motion.get());
brain->SetPhysics(physics.get());
motion->SetPhysics(physics.get());
physics->SetMotion(motion.get());
motion->Create(pos, angle, type, power, m_oldModelManager);
obj->SetBrain(std::move(brain));
obj->SetProgrammable(true);
obj->SetMotion(std::move(motion));
obj->SetPhysics(std::move(physics));
@ -2677,7 +2673,6 @@ CObjectUPtr CObjectFactory::CreateInsect(const ObjectCreateParams& params)
obj->SetTeam(params.team);
auto physics = MakeUnique<CPhysics>(obj.get());
auto brain = MakeUnique<CBrain>(obj.get());
std::unique_ptr<CMotion> motion;
if ( type == OBJECT_MOTHER )
@ -2703,15 +2698,13 @@ CObjectUPtr CObjectFactory::CreateInsect(const ObjectCreateParams& params)
assert(motion != nullptr);
physics->SetMotion(motion.get());
brain->SetMotion(motion.get());
brain->SetPhysics(physics.get());
motion->SetPhysics(physics.get());
motion->Create(pos, angle, type, 0.0f, m_oldModelManager);
obj->SetMotion(std::move(motion));
obj->SetPhysics(std::move(physics));
obj->SetBrain(std::move(brain));
obj->SetProgrammable(true);
return std::move(obj);
}

View File

@ -37,7 +37,6 @@
#include "math/geometry.h"
#include "object/brain.h"
#include "object/object_manager.h"
#include "object/robotmain.h"
@ -56,11 +55,16 @@
#include "physics/physics.h"
#include "script/cbottoken.h"
#include "script/script.h"
#include "script/scriptfunc.h"
#include "ui/object_interface.h"
#include "ui/studio.h"
#include "ui/controls/edit.h"
#include <boost/lexical_cast.hpp>
#include <iomanip>
@ -83,6 +87,8 @@ static float debug_arm2 = 0.0f;
static float debug_arm3 = 0.0f;
#endif
const int MAXTRACERECORD = 1000;
// Object's constructor.
@ -96,7 +102,7 @@ COldObject::COldObject(int id)
, CCarrierObject(m_implementedInterfaces)
, CPoweredObject(m_implementedInterfaces)
{
// A bit of a hack since CBrain is set externally in SetBrain()
// A bit of a hack since we don't have subclasses yet, set externally in SetProgrammable()
m_implementedInterfaces[static_cast<int>(ObjectInterfaceType::Programmable)] = false;
// Another hack
m_implementedInterfaces[static_cast<int>(ObjectInterfaceType::Jostleable)] = false;
@ -191,6 +197,18 @@ COldObject::COldObject(int id)
m_activity = true;
m_currentProgram = nullptr;
m_bActiveVirus = false;
m_time = 0.0f;
m_burnTime = 0.0f;
m_buttonAxe = EVENT_NULL;
m_scriptRun = nullptr;
m_soluceName[0] = 0;
m_traceRecord = false;
DeleteAllCrashSpheres();
m_botVar = CScriptFunctions::CreateObjectVar(this);
@ -331,18 +349,18 @@ void COldObject::DeleteObject(bool bAll)
if ( !bAll ) m_main->CreateShortcuts();
}
// Simplifies a object (he was the brain, among others).
// Simplifies a object (he was the programmable, among others).
void COldObject::Simplify()
{
m_implementedInterfaces[static_cast<int>(ObjectInterfaceType::Programmable)] = false;
if ( m_brain != nullptr )
if ( Implements(ObjectInterfaceType::Programmable) )
{
m_brain->StopProgram();
StopProgram();
}
m_main->SaveOneScript(this);
m_implementedInterfaces[static_cast<int>(ObjectInterfaceType::Programmable)] = false;
if ( m_physics != nullptr )
{
m_physics->DeleteObject();
@ -355,11 +373,6 @@ void COldObject::Simplify()
m_objectInterface.reset();
}
if ( m_brain != nullptr )
{
m_brain.reset();
}
if ( m_motion != nullptr )
{
m_motion->DeleteObject();
@ -568,9 +581,9 @@ bool COldObject::ExplodeObject(ExplosionType type, float force, float decay)
if ( shield == 0.0f ) // dead?
{
if ( m_brain != nullptr )
if ( Implements(ObjectInterfaceType::Programmable) )
{
m_brain->StopProgram();
StopProgram();
}
m_main->SaveOneScript(this);
}
@ -839,9 +852,14 @@ void COldObject::Write(CLevelParserLine* line)
m_motion->Write(line);
}
if ( m_brain != nullptr )
if ( Implements(ObjectInterfaceType::Programmable) )
{
m_brain->Write(line);
line->AddParam("bVirusActive", MakeUnique<CLevelParserParam>(m_bActiveVirus));
if ( m_type == OBJECT_MOBILErs )
{
line->AddParam("bShieldActive", MakeUnique<CLevelParserParam>(IsBackgroundTask()));
}
}
if ( m_physics != nullptr )
@ -905,9 +923,16 @@ void COldObject::Read(CLevelParserLine* line)
m_motion->Read(line);
}
if ( m_brain != nullptr )
if ( Implements(ObjectInterfaceType::Programmable) )
{
m_brain->Read(line);
m_bActiveVirus = line->GetParam("bVirusActive")->AsBool(false);
if ( m_type == OBJECT_MOBILErs )
{
if( line->GetParam("bShieldActive")->AsBool(false) )
{
StartTaskShield(TSM_START);
}
}
}
if ( m_physics != nullptr )
{
@ -1857,9 +1882,103 @@ bool COldObject::EventProcess(const Event &event)
}
}
if ( m_brain != nullptr )
if ( Implements(ObjectInterfaceType::Programmable) )
{
m_brain->EventProcess(event);
if ( GetRuin() && m_currentProgram != nullptr )
{
StopProgram();
}
if ( !GetSelect() && // robot pas sélectionné ?
m_currentProgram == nullptr &&
!IsForegroundTask() )
{
float axeX = 0.0f;
float axeY = 0.0f;
float axeZ = 0.0f;
if ( m_bBurn ) // Gifted?
{
axeZ = -1.0f; // tomb
if ( !GetFixed() &&
(m_type == OBJECT_ANT ||
m_type == OBJECT_SPIDER ||
m_type == OBJECT_WORM ) )
{
axeY = 2.0f; // zigzag disorganized fast
if ( m_type == OBJECT_WORM ) axeY = 5.0f;
axeX = 0.5f+sinf(m_time* 1.0f)*0.5f+
sinf(m_time* 6.0f)*2.0f+
sinf(m_time*21.0f)*0.2f;
float factor = 1.0f-m_burnTime/15.0f; // slow motion
if ( factor < 0.0f ) factor = 0.0f;
axeY *= factor;
axeX *= factor;
}
}
m_physics->SetMotorSpeedX(axeY); // move forward/move back
m_physics->SetMotorSpeedY(axeZ); // up / down
m_physics->SetMotorSpeedZ(axeX); // rotate
}
else if (GetSelect())
{
if ( (IsForegroundTask() && GetForegroundTask()->IsPilot()) || m_currentProgram == nullptr )
{
if ( event.type == EVENT_OBJECT_LEFT ||
event.type == EVENT_OBJECT_RIGHT ||
event.type == EVENT_OBJECT_UP ||
event.type == EVENT_OBJECT_DOWN ||
event.type == EVENT_OBJECT_GASUP ||
event.type == EVENT_OBJECT_GASDOWN )
{
m_buttonAxe = event.type;
}
if ( event.type == EVENT_MOUSE_BUTTON_UP )
{
m_buttonAxe = EVENT_NULL;
}
float axeX = event.motionInput.x;
float axeY = event.motionInput.y;
float axeZ = event.motionInput.z;
if ( (!m_main->GetTrainerPilot() &&
GetTrainer()) ||
!m_main->CanPlayerInteract() ) // drive vehicle?
{
axeX = 0.0f;
axeY = 0.0f;
axeZ = 0.0f; // Remote control impossible!
}
if ( m_buttonAxe == EVENT_OBJECT_LEFT ) axeX = -1.0f;
if ( m_buttonAxe == EVENT_OBJECT_RIGHT ) axeX = 1.0f;
if ( m_buttonAxe == EVENT_OBJECT_UP ) axeY = 1.0f;
if ( m_buttonAxe == EVENT_OBJECT_DOWN ) axeY = -1.0f;
if ( m_buttonAxe == EVENT_OBJECT_GASUP ) axeZ = 1.0f;
if ( m_buttonAxe == EVENT_OBJECT_GASDOWN ) axeZ = -1.0f;
if ( m_type == OBJECT_MOBILEdr && GetManual() ) // scribbler in manual mode?
{
if ( axeX != 0.0f ) axeY = 0.0f; // if running -> not moving!
axeX *= 0.5f;
axeY *= 0.5f;
}
if ( !m_main->IsResearchDone(RESEARCH_FLY, GetTeam()) )
{
axeZ = -1.0f; // tomb
}
axeX += m_camera->GetMotorTurn(); // additional power according to camera
if ( axeX > 1.0f ) axeX = 1.0f;
if ( axeX < -1.0f ) axeX = -1.0f;
m_physics->SetMotorSpeedX(axeY); // move forward/move back
m_physics->SetMotorSpeedY(axeZ); // up/down
m_physics->SetMotorSpeedZ(axeX); // rotate
}
}
}
if ( m_objectInterface != nullptr )
@ -1903,8 +2022,12 @@ bool COldObject::EventFrame(const Event &event)
return true;
}
m_time += event.rTime;
if ( m_engine->GetPause() && m_type != OBJECT_SHOW ) return true;
if ( m_bBurn ) m_burnTime += event.rTime;
m_aTime += event.rTime;
m_shotTime += event.rTime;
@ -1929,6 +2052,25 @@ bool COldObject::EventFrame(const Event &event)
}
}
if (Implements(ObjectInterfaceType::Programmable))
{
if ( GetActivity() )
{
if ( m_currentProgram != nullptr ) // current program?
{
if ( m_currentProgram->script->Continue() )
{
StopProgram();
}
}
if ( m_traceRecord ) // registration of the design in progress?
{
TraceRecordFrame();
}
}
}
// NOTE: This MUST be called AFTER CScriptFunctions::Process, otherwise weird stuff may happen to scripts
EndedTask();
@ -2404,9 +2546,9 @@ void COldObject::SetVirusMode(bool bEnable)
m_bVirusMode = bEnable;
m_virusTime = 0.0f;
if ( m_bVirusMode && m_brain != nullptr )
if ( m_bVirusMode && Implements(ObjectInterfaceType::Programmable) )
{
if ( !m_brain->IntroduceVirus() ) // tries to infect
if ( !IntroduceVirus() ) // tries to infect
{
m_bVirusMode = false; // program was not contaminated!
}
@ -2679,6 +2821,7 @@ bool COldObject::IsExploding()
void COldObject::SetBurn(bool bBurn)
{
m_bBurn = bBurn;
m_burnTime = 0.0f;
//? if ( m_botVar != 0 )
//? {
@ -2696,9 +2839,9 @@ void COldObject::SetDead(bool bDead)
{
m_bDead = bDead;
if ( bDead && m_brain != nullptr )
if ( bDead && Implements(ObjectInterfaceType::Programmable) )
{
m_brain->StopProgram(); // stops the current task
StopProgram(); // stops the current task
}
//? if ( m_botVar != 0 )
@ -2827,14 +2970,6 @@ void COldObject::SetShowLimitRadius(float radius)
m_showLimitRadius = radius;
}
// Indicates whether a program is under execution.
bool COldObject::IsProgram()
{
if ( m_brain == nullptr ) return false;
return m_brain->IsProgram();
}
// Creates or removes particles associated to the object.
@ -3082,17 +3217,10 @@ void COldObject::SetPhysics(std::unique_ptr<CPhysics> physics)
m_physics = std::move(physics);
}
// Returns the brain associated to the object.
CBrain* COldObject::GetBrain()
// TODO: Temporary hack until we'll have subclasses for objects
void COldObject::SetProgrammable(bool programmable)
{
return m_brain.get();
}
void COldObject::SetBrain(std::unique_ptr<CBrain> brain)
{
m_implementedInterfaces[static_cast<int>(ObjectInterfaceType::Programmable)] = true;
m_brain = std::move(brain);
m_implementedInterfaces[static_cast<int>(ObjectInterfaceType::Programmable)] = programmable;
}
// Returns the movement associated to the object.
@ -3497,3 +3625,512 @@ void COldObject::UpdateInterface()
m_objectInterface->UpdateInterface();
}
}
// Stops the running program.
void COldObject::StopProgram()
{
StopForegroundTask();
if ( m_type == OBJECT_HUMAN ||
m_type == OBJECT_TECH ) return;
if ( m_currentProgram != nullptr )
{
m_currentProgram->script->Stop();
}
m_currentProgram = nullptr;
m_physics->SetMotorSpeedX(0.0f);
m_physics->SetMotorSpeedY(0.0f);
m_physics->SetMotorSpeedZ(0.0f);
m_motion->SetAction(-1);
UpdateInterface();
m_main->UpdateShortcuts();
CreateSelectParticle();
}
// Introduces a virus into a program.
// Returns true if it was inserted.
bool COldObject::IntroduceVirus()
{
if(m_program.size() == 0) return false;
for ( int i=0 ; i<50 ; i++ )
{
int j = rand()%m_program.size();
if ( m_program[j]->script->IntroduceVirus() ) // tries to introduce
{
m_bActiveVirus = true; // active virus
return true;
}
}
return false;
}
// Active Virus indicates that the object is contaminated. Unlike ch'tites (??? - Programerus)
// letters which automatically disappear after a while,
// ActiveVirus does not disappear after you edit the program
// (Even if the virus is not fixed).
void COldObject::SetActiveVirus(bool bActive)
{
m_bActiveVirus = bActive;
if ( !m_bActiveVirus ) // virus disabled?
{
SetVirusMode(false); // chtites (??? - Programerus) letters also
}
}
bool COldObject::GetActiveVirus()
{
return m_bActiveVirus;
}
// Indicates whether a program is running.
bool COldObject::IsProgram()
{
return m_currentProgram != nullptr;
}
// Starts a program.
void COldObject::RunProgram(Program* program)
{
if ( program->script->Run() )
{
m_currentProgram = program; // start new program
UpdateInterface();
CreateSelectParticle();
m_main->UpdateShortcuts();
if(GetTrainer())
m_main->StartMissionTimer();
}
}
// Returns the current program.
int COldObject::GetProgram()
{
if(m_currentProgram == nullptr)
return -1;
for(unsigned int i = 0; i < m_program.size(); i++)
{
if(m_program[i].get() == m_currentProgram)
{
return i;
}
}
return -1;
}
// Name management scripts to load.
void COldObject::SetScriptRun(Program* program)
{
m_scriptRun = program;
}
Program* COldObject::GetScriptRun()
{
return m_scriptRun;
}
void COldObject::SetSoluceName(char *name)
{
strcpy(m_soluceName, name);
}
char* COldObject::GetSoluceName()
{
return m_soluceName;
}
// Load a script solution, in the first free script.
// If there is already an identical script, nothing is loaded.
bool COldObject::ReadSoluce(char* filename)
{
Program* prog = AddProgram();
if ( !ReadProgram(prog, filename) ) return false; // load solution
prog->readOnly = true;
for(unsigned int i = 0; i < m_program.size(); i++)
{
if(m_program[i].get() == prog) continue;
//TODO: This is bad. It's very sensitive to things like \n vs \r\n etc.
if ( m_program[i]->script->Compare(prog->script.get()) ) // the same already?
{
m_program[i]->readOnly = true; // Mark is as read-only
RemoveProgram(prog);
return false;
}
}
return true;
}
// Load a script with a text file.
bool COldObject::ReadProgram(Program* program, const char* filename)
{
if ( program->script->ReadScript(filename) ) return true;
return false;
}
// Indicates whether a program is compiled correctly.
bool COldObject::GetCompile(Program* program)
{
return program->script->GetCompile();
}
// Saves a script in a text file.
bool COldObject::WriteProgram(Program* program, const char* filename)
{
if ( program->script->WriteScript(filename) ) return true;
return false;
}
// Load a stack of script implementation from a file.
bool COldObject::ReadStack(FILE *file)
{
short op;
fRead(&op, sizeof(short), 1, file);
if ( op == 1 ) // run ?
{
fRead(&op, sizeof(short), 1, file); // program rank
if ( op >= 0 )
{
assert(op < static_cast<int>(m_program.size())); //TODO: is it good?
//TODO: m_selScript = op;
if ( !m_program[op]->script->ReadStack(file) ) return false;
}
}
return true;
}
// Save the script implementation stack of a file.
bool COldObject::WriteStack(FILE *file)
{
short op;
if ( m_currentProgram != nullptr && // current program?
m_currentProgram->script->IsRunning() )
{
op = 1; // run
fWrite(&op, sizeof(short), 1, file);
op = GetProgram();
fWrite(&op, sizeof(short), 1, file);
return m_currentProgram->script->WriteStack(file);
}
op = 0; // stop
fWrite(&op, sizeof(short), 1, file);
return true;
}
// Start of registration of the design.
void COldObject::TraceRecordStart()
{
if (m_traceRecord)
{
TraceRecordStop();
}
CMotionVehicle* motionVehicle = dynamic_cast<CMotionVehicle*>(m_motion.get());
assert(motionVehicle != nullptr);
m_traceRecord = true;
m_traceOper = TO_STOP;
m_tracePos = GetPosition();
m_traceAngle = GetRotationY();
if ( motionVehicle->GetTraceDown() ) // pencil down?
{
m_traceColor = motionVehicle->GetTraceColor();
}
else // pen up?
{
m_traceColor = TraceColor::Default;
}
m_traceRecordBuffer = MakeUniqueArray<TraceRecord>(MAXTRACERECORD);
m_traceRecordIndex = 0;
}
// Saving the current drawing.
void COldObject::TraceRecordFrame()
{
TraceOper oper = TO_STOP;
Math::Vector pos;
float angle, len, speed;
CMotionVehicle* motionVehicle = dynamic_cast<CMotionVehicle*>(m_motion.get());
assert(motionVehicle != nullptr);
speed = m_physics->GetLinMotionX(MO_REASPEED);
if ( speed > 0.0f ) oper = TO_ADVANCE;
if ( speed < 0.0f ) oper = TO_RECEDE;
speed = m_physics->GetCirMotionY(MO_REASPEED);
if ( speed != 0.0f ) oper = TO_TURN;
TraceColor color = TraceColor::Default;
if ( motionVehicle->GetTraceDown() ) // pencil down?
{
color = motionVehicle->GetTraceColor();
}
if ( oper != m_traceOper ||
color != m_traceColor )
{
if ( m_traceOper == TO_ADVANCE ||
m_traceOper == TO_RECEDE )
{
pos = GetPosition();
len = Math::DistanceProjected(pos, m_tracePos);
TraceRecordOper(m_traceOper, len);
}
if ( m_traceOper == TO_TURN )
{
angle = GetRotationY()-m_traceAngle;
TraceRecordOper(m_traceOper, angle);
}
if ( color != m_traceColor )
{
TraceRecordOper(TO_PEN, static_cast<float>(color));
}
m_traceOper = oper;
m_tracePos = GetPosition();
m_traceAngle = GetRotationY();
m_traceColor = color;
}
}
// End of the registration of the design. Program generates the CBOT.
void COldObject::TraceRecordStop()
{
TraceOper lastOper, curOper;
float lastParam, curParam;
m_traceRecord = false;
std::stringstream buffer;
buffer << "extern void object::AutoDraw()\n{\n";
lastOper = TO_STOP;
lastParam = 0.0f;
for ( int i=0 ; i<m_traceRecordIndex ; i++ )
{
curOper = m_traceRecordBuffer[i].oper;
curParam = m_traceRecordBuffer[i].param;
if ( curOper == lastOper )
{
if ( curOper == TO_PEN )
{
lastParam = curParam;
}
else
{
lastParam += curParam;
}
}
else
{
TraceRecordPut(buffer, lastOper, lastParam);
lastOper = curOper;
lastParam = curParam;
}
}
TraceRecordPut(buffer, lastOper, lastParam);
m_traceRecordBuffer.reset();
buffer << "}\n";
Program* prog = AddProgram();
prog->script->SendScript(buffer.str().c_str());
}
// Saves an instruction CBOT.
bool COldObject::TraceRecordOper(TraceOper oper, float param)
{
int i;
i = m_traceRecordIndex;
if ( i >= MAXTRACERECORD ) return false;
m_traceRecordBuffer[i].oper = oper;
m_traceRecordBuffer[i].param = param;
m_traceRecordIndex = i+1;
return true;
}
// Generates an instruction CBOT.
bool COldObject::TraceRecordPut(std::stringstream& buffer, TraceOper oper, float param)
{
if ( oper == TO_ADVANCE )
{
param /= g_unit;
buffer << "\tmove(" << std::fixed << std::setprecision(1) << param << ");\n";
}
if ( oper == TO_RECEDE )
{
param /= g_unit;
buffer << "\tmove(-" << std::fixed << std::setprecision(1) << param << ");\n";
}
if ( oper == TO_TURN )
{
param = -param*180.0f/Math::PI;
buffer << "\tturn(" << static_cast<int>(param) << ");\n";
}
if ( oper == TO_PEN )
{
TraceColor color = static_cast<TraceColor>(static_cast<int>(param));
if ( color == TraceColor::Default )
buffer << "\tpenup();\n";
else
buffer << "\tpendown(" << TraceColorName(color) << ");\n";
}
return true;
}
bool COldObject::IsTraceRecord()
{
return m_traceRecord;
}
Program* COldObject::AddProgram()
{
auto program = MakeUnique<Program>();
program->script = MakeUnique<CScript>(this);
program->readOnly = false;
program->runnable = true;
Program* prog = program.get();
AddProgram(std::move(program));
return prog;
}
void COldObject::AddProgram(std::unique_ptr<Program> program)
{
m_program.push_back(std::move(program));
UpdateInterface();
}
void COldObject::RemoveProgram(Program* program)
{
if(m_currentProgram == program)
{
StopProgram();
}
m_program.erase(
std::remove_if(m_program.begin(), m_program.end(),
[program](std::unique_ptr<Program>& prog) { return prog.get() == program; }),
m_program.end());
}
Program* COldObject::CloneProgram(Program* program)
{
Program* newprog = AddProgram();
// TODO: Is there any reason CScript doesn't have a function to get the program code directly?
Ui::CEdit* edit = new Ui::CEdit();
edit->SetMaxChar(Ui::EDITSTUDIOMAX);
program->script->PutScript(edit, "");
newprog->script->GetScript(edit);
delete edit;
return newprog;
}
std::vector<std::unique_ptr<Program>>& COldObject::GetPrograms()
{
return m_program;
}
int COldObject::GetProgramCount()
{
return static_cast<int>(m_program.size());
}
int COldObject::GetProgramIndex(Program* program)
{
for(unsigned int i = 0; i < m_program.size(); i++)
{
if(m_program[i].get() == program)
{
return i;
}
}
return -1;
}
Program* COldObject::GetProgram(int index)
{
if(index < 0 || index >= static_cast<int>(m_program.size()))
return nullptr;
return m_program[index].get();
}
Program* COldObject::GetOrAddProgram(int index)
{
if(index < 0)
return nullptr;
if(index < static_cast<int>(m_program.size()))
return m_program[index].get();
for(int i = m_program.size(); i < index; i++)
{
AddProgram();
}
return AddProgram();
}

View File

@ -55,6 +55,21 @@ struct ObjectPart
Math::Matrix matWorld;
};
enum TraceOper
{
TO_STOP = 0, // stop
TO_ADVANCE = 1, // advance
TO_RECEDE = 2, // back
TO_TURN = 3, // rotate
TO_PEN = 4, // color change
};
struct TraceRecord
{
TraceOper oper;
float param;
};
namespace Ui
{
class CObjectInterface;
@ -76,7 +91,7 @@ class COldObject : public CObject,
protected:
void DeleteObject(bool bAll=false);
void SetPhysics(std::unique_ptr<CPhysics> physics);
void SetBrain(std::unique_ptr<CBrain> brain);
void SetProgrammable(bool programmable);
void SetMotion(std::unique_ptr<CMotion> motion);
void SetAuto(std::unique_ptr<CAuto> automat);
void SetShowLimitRadius(float radius);
@ -227,8 +242,8 @@ public:
//! Management of object "activity" (temporairly stops program execution, right now used only by Aliens in eggs)
//@{
void SetActivity(bool activity);
bool GetActivity();
void SetActivity(bool activity) override;
bool GetActivity() override;
//@}
void SetVisible(bool bVisible);
@ -270,14 +285,12 @@ public:
bool StartShowLimit() override;
void StopShowLimit() override;
bool IsProgram() override;
void CreateSelectParticle();
void SetRunScript(CScript* script);
CScript* GetRunScript() override;
CBotVar* GetBotVar() override;
CPhysics* GetPhysics() override;
CBrain* GetBrain() override;
CMotion* GetMotion() override;
CAuto* GetAuto() override;
@ -336,6 +349,45 @@ public:
void UpdateInterface();
bool IsProgram() override;
void RunProgram(Program* program) override;
int GetProgram() override;
void StopProgram() override;
bool IntroduceVirus() override;
void SetActiveVirus(bool bActive) override;
bool GetActiveVirus() override;
void SetScriptRun(Program* rank) override;
Program* GetScriptRun() override;
void SetSoluceName(char *name) override;
char* GetSoluceName() override;
bool ReadSoluce(char* filename) override;
bool ReadProgram(Program* program, const char* filename) override;
bool GetCompile(Program* program) override;
bool WriteProgram(Program* program, const char* filename) override;
bool ReadStack(FILE *file) override;
bool WriteStack(FILE *file) override;
Program* AddProgram() override;
void AddProgram(std::unique_ptr<Program> program) override;
void RemoveProgram(Program* program) override;
Program* CloneProgram(Program* program) override;
std::vector<std::unique_ptr<Program>>& GetPrograms() override;
int GetProgramCount() override;
Program* GetProgram(int index) override;
Program* GetOrAddProgram(int index) override;
int GetProgramIndex(Program* program) override;
//! Start recording trace
void TraceRecordStart() override;
//! Stop recording trace and generate CBot program
void TraceRecordStop() override;
//! Returns true if trace recording is in progress
bool IsTraceRecord() override;
protected:
bool EventFrame(const Event &event);
void VirusFrame(float rTime);
@ -352,6 +404,13 @@ protected:
Error EndedTask();
//! Save current status to recording buffer
void TraceRecordFrame();
//! Save this operation to recording buffer
bool TraceRecordOper(TraceOper oper, float param);
//! Convert this recording operation to CBot instruction
bool TraceRecordPut(std::stringstream& buffer, TraceOper oper, float param);
protected:
Gfx::CEngine* m_engine;
Gfx::CLightManager* m_lightMan;
@ -362,7 +421,6 @@ protected:
CSoundInterface* m_sound;
std::unique_ptr<CPhysics> m_physics;
std::unique_ptr<CBrain> m_brain;
std::unique_ptr<CMotion> m_motion;
std::unique_ptr<CAuto> m_auto;
std::unique_ptr<Ui::CObjectInterface> m_objectInterface;
@ -441,4 +499,25 @@ protected:
bool m_activity;
std::unique_ptr<CTaskManager> m_foregroundTask;
std::unique_ptr<CTaskManager> m_backgroundTask;
std::vector<std::unique_ptr<Program>> m_program;
Program* m_currentProgram;
bool m_bActiveVirus;
Program* m_scriptRun;
char m_soluceName[50];
EventType m_buttonAxe;
float m_time;
float m_burnTime;
bool m_traceRecord;
TraceOper m_traceOper;
Math::Vector m_tracePos;
float m_traceAngle;
TraceColor m_traceColor;
int m_traceRecordIndex;
std::unique_ptr<TraceRecord[]> m_traceRecordBuffer;
};

View File

@ -397,11 +397,6 @@ void COldObjectInterface::StopShowLimit()
}
bool COldObjectInterface::IsProgram()
{
throw std::logic_error("IsProgram: not implemented!");
}
CScript* COldObjectInterface::GetRunScript()
{
throw std::logic_error("GetRunScript: not implemented!");

View File

@ -33,17 +33,11 @@
#include <string>
class CApplication;
class CPhysics;
class CBrain;
class CMotion;
class CAuto;
class CDisplayText;
class CRobotMain;
class CBotVar;
class CScript;
class CLevelParserLine;
struct Program;
struct Character
@ -175,8 +169,6 @@ public:
virtual bool StartShowLimit();
virtual void StopShowLimit();
virtual bool IsProgram();
virtual CScript* GetRunScript();
virtual CBotVar* GetBotVar();
virtual CPhysics* GetPhysics();
@ -192,4 +184,3 @@ public:
virtual float GetInfoReturn();
};

View File

@ -56,7 +56,6 @@
#include "math/const.h"
#include "math/geometry.h"
#include "object/brain.h"
#include "object/mainmovie.h"
#include "object/object.h"
#include "object/object_create_exception.h"
@ -3468,13 +3467,13 @@ void CRobotMain::CreateScene(bool soluce, bool fixScene, bool resetObject)
m_controller->SetIgnoreBuildCheck(true);
if (m_controller->Implements(ObjectInterfaceType::Programmable))
{
CBrain* brain = dynamic_cast<CProgrammableObject*>(m_controller)->GetBrain();
CProgrammableObject* programmable = dynamic_cast<CProgrammableObject*>(m_controller);
if (line->GetParam("script")->IsDefined())
{
Program* program = brain->AddProgram();
Program* program = programmable->AddProgram();
program->filename = "../" + line->GetParam("script")->AsPath("ai");
program->readOnly = true;
brain->SetScriptRun(program);
programmable->SetScriptRun(program);
}
}
continue;
@ -3637,7 +3636,7 @@ void CRobotMain::CreateScene(bool soluce, bool fixScene, bool resetObject)
std::map<int, Program*> loadedPrograms;
if (oldObj->Implements(ObjectInterfaceType::Programmable))
{
CBrain* brain = dynamic_cast<CProgrammableObject*>(oldObj)->GetBrain();
CProgrammableObject* programmable = dynamic_cast<CProgrammableObject*>(oldObj);
bool allFilled = true;
for (int i = 0; i < 10 || allFilled; i++)
@ -3647,7 +3646,7 @@ void CRobotMain::CreateScene(bool soluce, bool fixScene, bool resetObject)
std::string opRunnable = "scriptRunnable" + boost::lexical_cast<std::string>(i+1); // scriptRunnable1..scriptRunnable10
if (line->GetParam(op)->IsDefined())
{
Program* program = brain->AddProgram();
Program* program = programmable->AddProgram();
program->filename = "../" + line->GetParam(op)->AsPath("ai");
program->readOnly = line->GetParam(opReadOnly)->AsBool(true);
program->runnable = line->GetParam(opRunnable)->AsBool(true);
@ -3663,7 +3662,7 @@ void CRobotMain::CreateScene(bool soluce, bool fixScene, bool resetObject)
if (i != 0)
{
run = i-1;
brain->SetScriptRun(loadedPrograms[run]);
programmable->SetScriptRun(loadedPrograms[run]);
}
}
CAuto* automat = oldObj->GetAuto();
@ -3688,7 +3687,7 @@ void CRobotMain::CreateScene(bool soluce, bool fixScene, bool resetObject)
}
if (soluce && oldObj->Implements(ObjectInterfaceType::Programmable) && line->GetParam("soluce")->IsDefined())
dynamic_cast<CProgrammableObject*>(oldObj)->GetBrain()
dynamic_cast<CProgrammableObject*>(oldObj)
->SetSoluceName(const_cast<char*>(line->GetParam("soluce")->AsPath("ai").c_str()));
if (line->GetParam("reset")->AsBool(false))
@ -4684,27 +4683,27 @@ void CRobotMain::CompileScript(bool soluce)
m_ui->GetLoadingScreen()->SetProgress(0.75f+objectProgress*0.25f, RT_LOADING_PROGRAMS, "for object "+StrUtils::ToString<int>(objCounter+1)+" / "+StrUtils::ToString<int>(numObjects));
objCounter++;
CBrain* brain = dynamic_cast<CProgrammableObject*>(obj)->GetBrain();
for (auto& prog : brain->GetPrograms())
CProgrammableObject* programmable = dynamic_cast<CProgrammableObject*>(obj);
for (auto& prog : programmable->GetPrograms())
{
Program* program = prog.get();
if (program->filename.empty()) continue;
std::string name = "ai/" + program->filename;
if (! brain->ReadProgram(program, const_cast<char*>(name.c_str())))
if (! programmable->ReadProgram(program, const_cast<char*>(name.c_str())))
{
GetLogger()->Error("Unable to read script from file \"%s\"\n", name.c_str());
}
//? if (!brain->GetCompile(program)) nbError++;
//? if (!programmable->GetCompile(program)) nbError++;
}
if (soluce)
{
char* name = brain->GetSoluceName();
char* name = programmable->GetSoluceName();
if (name[0] != 0)
{
brain->ReadSoluce(name); // load solution
programmable->ReadSoluce(name); // load solution
}
}
@ -4716,11 +4715,11 @@ void CRobotMain::CompileScript(bool soluce)
{
if (! obj->Implements(ObjectInterfaceType::Programmable)) continue;
CBrain* brain = dynamic_cast<CProgrammableObject*>(obj)->GetBrain();
Program* program = brain->GetScriptRun();
CProgrammableObject* programmable = dynamic_cast<CProgrammableObject*>(obj);
Program* program = programmable->GetScriptRun();
if (program != nullptr)
{
brain->RunProgram(program); // starts the program
programmable->RunProgram(program); // starts the program
}
}
}
@ -4730,7 +4729,7 @@ void CRobotMain::LoadOneScript(CObject *obj)
{
if (! obj->Implements(ObjectInterfaceType::Programmable)) return;
CBrain* brain = dynamic_cast<CProgrammableObject*>(obj)->GetBrain();
CProgrammableObject* programmable = dynamic_cast<CProgrammableObject*>(obj);
if (!IsSelectable(obj)) return;
@ -4749,10 +4748,10 @@ void CRobotMain::LoadOneScript(CObject *obj)
if (CResourceManager::Exists(filename))
{
Program* program = brain->GetOrAddProgram(i);
if(brain->GetCompile(program)) continue; // If already loaded (e.g. from level file), skip
brain->ReadProgram(program, filename.c_str());
//? if (!brain->GetCompile(program)) nbError++;
Program* program = programmable->GetOrAddProgram(i);
if(programmable->GetCompile(program)) continue; // If already loaded (e.g. from level file), skip
programmable->ReadProgram(program, filename.c_str());
//? if (!programmable->GetCompile(program)) nbError++;
}
}
}
@ -4764,7 +4763,7 @@ void CRobotMain::LoadFileScript(CObject *obj, const char* filename, int objRank)
if (! obj->Implements(ObjectInterfaceType::Programmable)) return;
CBrain* brain = dynamic_cast<CProgrammableObject*>(obj)->GetBrain();
CProgrammableObject* programmable = dynamic_cast<CProgrammableObject*>(obj);
ObjectType type = obj->GetType();
if (type == OBJECT_HUMAN) return;
@ -4778,9 +4777,9 @@ void CRobotMain::LoadFileScript(CObject *obj, const char* filename, int objRank)
sprintf(fn, "%s/prog%.3d%.3d.txt", dirname.c_str(), objRank, i);
if (CResourceManager::Exists(fn))
{
Program* program = brain->GetOrAddProgram(i);
brain->ReadProgram(program, fn);
//? if (!brain->GetCompile(program)) nbError++;
Program* program = programmable->GetOrAddProgram(i);
programmable->ReadProgram(program, fn);
//? if (!programmable->GetCompile(program)) nbError++;
}
}
}
@ -4800,7 +4799,7 @@ void CRobotMain::SaveOneScript(CObject *obj)
{
if (! obj->Implements(ObjectInterfaceType::Programmable)) return;
CBrain* brain = dynamic_cast<CProgrammableObject*>(obj)->GetBrain();
CProgrammableObject* programmable = dynamic_cast<CProgrammableObject*>(obj);
if (!IsSelectable(obj)) return;
@ -4811,7 +4810,7 @@ void CRobotMain::SaveOneScript(CObject *obj)
if (objRank == -1) return;
char categoryChar = GetLevelCategoryDir(m_levelCategory)[0];
auto& programs = brain->GetPrograms();
auto& programs = programmable->GetPrograms();
// TODO: Find a better way to do that
for (unsigned int i = 0; i <= 999; i++)
{
@ -4821,7 +4820,7 @@ void CRobotMain::SaveOneScript(CObject *obj)
if (i < programs.size())
{
brain->WriteProgram(programs[i].get(), filename.c_str());
programmable->WriteProgram(programs[i].get(), filename.c_str());
}
else
{
@ -4838,7 +4837,7 @@ void CRobotMain::SaveFileScript(CObject *obj, const char* filename, int objRank)
if (! obj->Implements(ObjectInterfaceType::Programmable)) return;
CBrain* brain = dynamic_cast<CProgrammableObject*>(obj)->GetBrain();
CProgrammableObject* programmable = dynamic_cast<CProgrammableObject*>(obj);
ObjectType type = obj->GetType();
if (type == OBJECT_HUMAN) return;
@ -4847,14 +4846,14 @@ void CRobotMain::SaveFileScript(CObject *obj, const char* filename, int objRank)
dirname = dirname.substr(0, dirname.find_last_of("/"));
char fn[MAX_FNAME]; //TODO: Refactor to std::string
auto& programs = brain->GetPrograms();
auto& programs = programmable->GetPrograms();
// TODO: Find a better way to do that
for (unsigned int i = 0; i <= 999; i++)
{
sprintf(fn, "%s/prog%.3d%.3d.txt", dirname.c_str(), objRank, i);
if (i < programs.size())
{
brain->WriteProgram(programs[i].get(), fn);
programmable->WriteProgram(programs[i].get(), fn);
}
else
{
@ -4870,12 +4869,12 @@ bool CRobotMain::SaveFileStack(CObject *obj, FILE *file, int objRank)
if (! obj->Implements(ObjectInterfaceType::Programmable)) return true;
CBrain* brain = dynamic_cast<CProgrammableObject*>(obj)->GetBrain();
CProgrammableObject* programmable = dynamic_cast<CProgrammableObject*>(obj);
ObjectType type = obj->GetType();
if (type == OBJECT_HUMAN) return true;
return brain->WriteStack(file);
return programmable->WriteStack(file);
}
//! Resumes the execution stack of the program in a robot
@ -4885,12 +4884,12 @@ bool CRobotMain::ReadFileStack(CObject *obj, FILE *file, int objRank)
if (! obj->Implements(ObjectInterfaceType::Programmable)) return true;
CBrain* brain = dynamic_cast<CProgrammableObject*>(obj)->GetBrain();
CProgrammableObject* programmable = dynamic_cast<CProgrammableObject*>(obj);
ObjectType type = obj->GetType();
if (type == OBJECT_HUMAN) return true;
return brain->ReadStack(file);
return programmable->ReadStack(file);
}
@ -5005,15 +5004,15 @@ void CRobotMain::IOWriteObject(CLevelParserLine* line, CObject* obj)
if (obj->Implements(ObjectInterfaceType::Programmable))
{
CBrain* brain = dynamic_cast<CProgrammableObject*>(obj)->GetBrain();
CProgrammableObject* programmable = dynamic_cast<CProgrammableObject*>(obj);
int run = brain->GetProgram();
int run = programmable->GetProgram();
if (run != -1)
{
line->AddParam("run", MakeUnique<CLevelParserParam>(run+1));
}
auto& programs = brain->GetPrograms();
auto& programs = programmable->GetPrograms();
for (unsigned int i = 0; i < programs.size(); i++)
{
if (programs[i]->readOnly)
@ -5249,19 +5248,19 @@ CObject* CRobotMain::IOReadObject(CLevelParserLine *line, const char* filename,
if (obj->Implements(ObjectInterfaceType::Programmable))
{
CBrain* brain = dynamic_cast<CProgrammableObject*>(obj)->GetBrain();
CProgrammableObject* programmable = dynamic_cast<CProgrammableObject*>(obj);
if (run != -1)
{
Program* program = brain->GetOrAddProgram(run-1);
brain->SetScriptRun(program); // marks the program to be started
Program* program = programmable->GetOrAddProgram(run-1);
programmable->SetScriptRun(program); // marks the program to be started
}
for (unsigned int i = 0; i <= 999; i++)
{
if (line->GetParam("scriptReadOnly" + boost::lexical_cast<std::string>(i+1))->AsBool(false))
{
Program* prog = brain->GetOrAddProgram(i);
Program* prog = programmable->GetOrAddProgram(i);
prog->readOnly = true;
}
}
@ -5371,12 +5370,12 @@ CObject* CRobotMain::IOReadScene(std::string filename, std::string filecbot)
if (! obj->Implements(ObjectInterfaceType::Programmable)) continue;
if (obj->GetDefRank() == -1) continue;
CBrain* brain = dynamic_cast<CProgrammableObject*>(obj)->GetBrain();
CProgrammableObject* programmable = dynamic_cast<CProgrammableObject*>(obj);
Program* program = brain->GetScriptRun();
Program* program = programmable->GetScriptRun();
if (program != nullptr)
{
brain->RunProgram(program); // starts the program
programmable->RunProgram(program); // starts the program
}
}

View File

@ -43,10 +43,10 @@ CTask::CTask(COldObject* object)
m_object = object;
m_physics = m_object->GetPhysics();
m_brain = nullptr;
m_programmable = nullptr;
if (object->Implements(ObjectInterfaceType::Programmable))
{
m_brain = dynamic_cast<CProgrammableObject*>(m_object)->GetBrain();
m_programmable = dynamic_cast<CProgrammableObject*>(m_object);
}
m_motion = m_object->GetMotion();
}
@ -88,4 +88,3 @@ bool CTask::Abort()
{
return true;
}

View File

@ -28,10 +28,10 @@
#include "math/const.h"
class CBrain;
class CPhysics;
class CMotion;
class COldObject;
class CProgrammableObject;
class CRobotMain;
class CSoundInterface;
@ -80,11 +80,11 @@ protected:
Gfx::CTerrain* m_terrain;
Gfx::CWater* m_water;
Gfx::CCamera* m_camera;
CMotion* m_motion;
CBrain* m_brain;
CPhysics* m_physics;
COldObject* m_object;
CRobotMain* m_main;
CSoundInterface* m_sound;
};
COldObject* m_object;
CProgrammableObject* m_programmable;
CMotion* m_motion;
CPhysics* m_physics;
};

View File

@ -27,7 +27,6 @@
#include "math/geometry.h"
#include "object/brain.h"
#include "object/object_manager.h"
#include "object/old_object.h"
#include "object/robotmain.h"
@ -578,4 +577,3 @@ float CTaskShield::GetRadius()
{
return RADIUS_SHIELD_MIN + (RADIUS_SHIELD_MAX-RADIUS_SHIELD_MIN)*m_object->GetParam();
}

View File

@ -25,13 +25,11 @@
#include "math/geometry.h"
#include "object/brain.h"
#include "object/object_manager.h"
#include "object/old_object.h"
#include "object/robotmain.h"
#include "object/interface/powered_object.h"
#include "object/interface/programmable_object.h"
#include "object/motion/motionant.h"
#include "object/motion/motionspider.h"

View File

@ -35,7 +35,6 @@
#include "math/geometry.h"
#include "object/brain.h"
#include "object/object_manager.h"
#include "object/old_object.h"
#include "object/robotmain.h"
@ -3829,7 +3828,7 @@ Error CPhysics::GetError()
if (m_object->Implements(ObjectInterfaceType::Programmable))
{
if ( dynamic_cast<CProgrammableObject*>(m_object)->GetBrain()->GetActiveVirus() )
if ( dynamic_cast<CProgrammableObject*>(m_object)->GetActiveVirus() )
{
return ERR_VEH_VIRUS;
}

View File

@ -35,7 +35,6 @@
class CObject;
class COldObject;
class CBrain;
class CMotion;
class CSoundInterface;
class CLevelParserLine;
@ -111,7 +110,6 @@ public:
bool EventProcess(const Event &event);
void SetBrain(CBrain* brain);
void SetMotion(CMotion* motion);
void SetType(PhysicsType type);
@ -216,11 +214,11 @@ protected:
Gfx::CTerrain* m_terrain;
Gfx::CWater* m_water;
Gfx::CCamera* m_camera;
COldObject* m_object;
CBrain* m_brain;
CMotion* m_motion;
CSoundInterface* m_sound;
COldObject* m_object;
CMotion* m_motion;
PhysicsType m_type; // TYPE_*
float m_gravity; // force of gravity
float m_time; // absolute time

View File

@ -35,7 +35,6 @@
#include "math/all.h"
#include "object/brain.h"
#include "object/object.h"
#include "object/object_manager.h"
#include "object/robotmain.h"
@ -45,6 +44,7 @@
#include "object/auto/autobase.h"
#include "object/auto/autofactory.h"
#include "object/interface/programmable_object.h"
#include "object/interface/task_executor_object.h"
#include "object/level/parser.h"
@ -1611,10 +1611,10 @@ bool CScriptFunctions::rProduce(CBotVar* var, CBotVar* result, int& exception, v
std::string name2 = InjectLevelPathsForCurrentLevel(name, "ai");
if (object->Implements(ObjectInterfaceType::Programmable))
{
CBrain* brain = dynamic_cast<CProgrammableObject*>(object)->GetBrain();
Program* program = brain->AddProgram();
brain->ReadProgram(program, name2.c_str());
brain->RunProgram(program);
CProgrammableObject* programmable = dynamic_cast<CProgrammableObject*>(object);
Program* program = programmable->AddProgram();
programmable->ReadProgram(program, name2.c_str());
programmable->RunProgram(program);
}
}

View File

@ -27,6 +27,8 @@
#include "object/object.h"
#include "object/object_manager.h"
#include "object/interface/programmable_object.h"
namespace Ui
{
@ -233,7 +235,7 @@ bool CMainShort::UpdateShortcuts()
if ( pc != nullptr )
{
pc->SetState(STATE_CHECK, m_shortcuts[i]->GetSelect());
pc->SetState(STATE_RUN, m_shortcuts[i]->IsProgram());
pc->SetState(STATE_RUN, m_shortcuts[i]->Implements(ObjectInterfaceType::Programmable) && dynamic_cast<CProgrammableObject*>(m_shortcuts[i])->IsProgram());
}
}
return true;

View File

@ -28,7 +28,6 @@
#include "math/geometry.h"
#include "object/brain.h"
#include "object/old_object.h"
#include "object/interface/carrier_object.h"
@ -63,7 +62,7 @@ CObjectInterface::CObjectInterface(COldObject* object)
assert(object->Implements(ObjectInterfaceType::TaskExecutor));
m_taskExecutor = dynamic_cast<CTaskExecutorObject*>(m_object);
assert(object->Implements(ObjectInterfaceType::Programmable));
m_brain = dynamic_cast<CProgrammableObject*>(m_object)->GetBrain();
m_programmable = dynamic_cast<CProgrammableObject*>(m_object);
m_physics = m_object->GetPhysics();
m_motion = m_object->GetMotion();
@ -194,8 +193,8 @@ bool CObjectInterface::EventProcess(const Event &event)
index = data->key-KEY(1);
else if(data->key == KEY(0))
index = 9;
if(index < 0) index = m_brain->GetProgramCount()-1;
if(index > static_cast<int>(m_brain->GetProgramCount())-1) index = 0;
if(index < 0) index = m_programmable->GetProgramCount()-1;
if(index > static_cast<int>(m_programmable->GetProgramCount())-1) index = 0;
if(GetSelScript() != index)
{
@ -226,29 +225,29 @@ bool CObjectInterface::EventProcess(const Event &event)
if ( action == EVENT_OBJECT_PROGRUN )
{
if ( !m_brain->IsProgram() )
if ( !m_programmable->IsProgram() )
{
if(m_selScript < m_brain->GetProgramCount())
if(m_selScript < m_programmable->GetProgramCount())
{
m_brain->RunProgram(m_brain->GetProgram(m_selScript));
m_programmable->RunProgram(m_programmable->GetProgram(m_selScript));
}
}
else
{
m_brain->StopProgram();
m_programmable->StopProgram();
}
}
if ( action == EVENT_OBJECT_PROGSTART )
{
m_main->SaveOneScript(m_object);
if(m_selScript < m_brain->GetProgramCount())
if(m_selScript < m_programmable->GetProgramCount())
{
m_brain->RunProgram(m_brain->GetProgram(m_selScript));
m_programmable->RunProgram(m_programmable->GetProgram(m_selScript));
}
}
if ( action == EVENT_OBJECT_PROGSTOP )
{
m_brain->StopProgram();
m_programmable->StopProgram();
}
if ( action == EVENT_STUDIO_OK )
{
@ -263,8 +262,8 @@ bool CObjectInterface::EventProcess(const Event &event)
if( action == EVENT_STUDIO_CLONE )
{
StopEditScript(false);
Program* newProgram = m_brain->CloneProgram(m_brain->GetProgram(m_selScript));
m_selScript = m_brain->GetProgramIndex(newProgram);
Program* newProgram = m_programmable->CloneProgram(m_programmable->GetProgram(m_selScript));
m_selScript = m_programmable->GetProgramIndex(newProgram);
m_main->SaveOneScript(m_object);
UpdateInterface();
@ -296,29 +295,29 @@ bool CObjectInterface::EventProcess(const Event &event)
}
}
if ( m_taskExecutor->IsForegroundTask() || // current task?
m_brain->IsProgram() )
m_programmable->IsProgram() )
{
if ( action == EVENT_OBJECT_PROGRUN )
{
m_brain->StopProgram();
m_programmable->StopProgram();
}
if ( action == EVENT_OBJECT_PROGEDIT )
{
if(m_selScript < m_brain->GetProgramCount())
if(m_selScript < m_programmable->GetProgramCount())
{
StartEditScript(m_brain->GetProgram(m_selScript), m_main->GetScriptName());
StartEditScript(m_programmable->GetProgram(m_selScript), m_main->GetScriptName());
}
}
if ( !m_taskExecutor->IsForegroundTask() || !m_taskExecutor->GetForegroundTask()->IsPilot() ) return true;
}
if ( !m_brain->IsProgram() )
if ( !m_programmable->IsProgram() )
{
if( action == EVENT_OBJECT_PROGADD )
{
Program* program = m_brain->AddProgram();
m_selScript = m_brain->GetProgramIndex(program);
Program* program = m_programmable->AddProgram();
m_selScript = m_programmable->GetProgramIndex(program);
m_main->SaveOneScript(m_object);
UpdateInterface();
@ -332,11 +331,11 @@ bool CObjectInterface::EventProcess(const Event &event)
if( action == EVENT_OBJECT_PROGREMOVE )
{
if(m_selScript < m_brain->GetProgramCount())
if(m_selScript < m_programmable->GetProgramCount())
{
m_brain->RemoveProgram(m_brain->GetProgram(m_selScript));
if(m_selScript >= m_brain->GetProgramCount())
m_selScript = m_brain->GetProgramCount()-1;
m_programmable->RemoveProgram(m_programmable->GetProgram(m_selScript));
if(m_selScript >= m_programmable->GetProgramCount())
m_selScript = m_programmable->GetProgramCount()-1;
m_main->SaveOneScript(m_object);
UpdateInterface();
@ -351,10 +350,10 @@ bool CObjectInterface::EventProcess(const Event &event)
if( action == EVENT_OBJECT_PROGCLONE )
{
if(m_selScript < m_brain->GetProgramCount())
if(m_selScript < m_programmable->GetProgramCount())
{
m_brain->CloneProgram(m_brain->GetProgram(m_selScript));
m_selScript = m_brain->GetProgramCount()-1;
m_programmable->CloneProgram(m_programmable->GetProgram(m_selScript));
m_selScript = m_programmable->GetProgramCount()-1;
m_main->SaveOneScript(m_object);
UpdateInterface();
@ -370,7 +369,7 @@ bool CObjectInterface::EventProcess(const Event &event)
if( action == EVENT_OBJECT_PROGMOVEUP )
{
std::iter_swap(m_brain->GetPrograms().begin() + m_selScript, m_brain->GetPrograms().begin() + m_selScript - 1);
std::iter_swap(m_programmable->GetPrograms().begin() + m_selScript, m_programmable->GetPrograms().begin() + m_selScript - 1);
m_selScript--;
m_main->SaveOneScript(m_object);
@ -385,7 +384,7 @@ bool CObjectInterface::EventProcess(const Event &event)
if( action == EVENT_OBJECT_PROGMOVEDOWN )
{
std::iter_swap(m_brain->GetPrograms().begin() + m_selScript, m_brain->GetPrograms().begin() + m_selScript + 1);
std::iter_swap(m_programmable->GetPrograms().begin() + m_selScript, m_programmable->GetPrograms().begin() + m_selScript + 1);
m_selScript++;
m_main->SaveOneScript(m_object);
@ -407,25 +406,25 @@ bool CObjectInterface::EventProcess(const Event &event)
if ( action == EVENT_OBJECT_PROGEDIT )
{
if(m_selScript < m_brain->GetProgramCount())
if(m_selScript < m_programmable->GetProgramCount())
{
StartEditScript(m_brain->GetProgram(m_selScript), m_main->GetScriptName());
StartEditScript(m_programmable->GetProgram(m_selScript), m_main->GetScriptName());
}
}
if ( action == EVENT_OBJECT_PROGRUN )
{
m_brain->StopProgram(); // stops the current program
if(m_selScript < m_brain->GetProgramCount())
m_programmable->StopProgram(); // stops the current program
if(m_selScript < m_programmable->GetProgramCount())
{
m_brain->RunProgram(m_brain->GetProgram(m_selScript));
m_programmable->RunProgram(m_programmable->GetProgram(m_selScript));
}
UpdateInterface();
}
err = ERR_OK;
if ( !m_brain->IsProgram() )
if ( !m_programmable->IsProgram() )
{
if ( action == EVENT_OBJECT_HTAKE )
{
@ -644,13 +643,13 @@ bool CObjectInterface::EventProcess(const Event &event)
if ( action == EVENT_OBJECT_REC ) // registered?
{
if ( m_brain->IsTraceRecord() )
if ( m_programmable->IsTraceRecord() )
{
m_brain->TraceRecordStop();
m_programmable->TraceRecordStop();
}
else
{
m_brain->TraceRecordStart();
m_programmable->TraceRecordStart();
}
UpdateInterface();
pw = static_cast< CWindow* >(m_interface->SearchControl(EVENT_WINDOW0));
@ -661,9 +660,9 @@ bool CObjectInterface::EventProcess(const Event &event)
}
if ( action == EVENT_OBJECT_STOP ) // stops?
{
if ( m_brain->IsTraceRecord() )
if ( m_programmable->IsTraceRecord() )
{
m_brain->TraceRecordStop();
m_programmable->TraceRecordStop();
}
UpdateInterface();
pw = static_cast< CWindow* >(m_interface->SearchControl(EVENT_WINDOW0));
@ -756,7 +755,7 @@ void CObjectInterface::StopEditScript(bool bCancel)
if ( !m_studio->StopEditScript(bCancel) ) return;
m_studio.reset();
if ( !bCancel ) m_brain->SetActiveVirus(false);
if ( !bCancel ) m_programmable->SetActiveVirus(false);
CreateInterface(true); // puts the control buttons
}
@ -1657,7 +1656,7 @@ void CObjectInterface::UpdateInterface(float rTime)
pb = static_cast<CButton*>(pw->SearchControl(EVENT_OBJECT_REC));
if ( pb != 0 )
{
if ( m_brain->IsTraceRecord() && Math::Mod(m_time, 0.4f) >= 0.2f )
if ( m_programmable->IsTraceRecord() && Math::Mod(m_time, 0.4f) >= 0.2f )
{
pb->SetState(STATE_CHECK);
}
@ -1756,15 +1755,15 @@ void CObjectInterface::UpdateInterface()
type = m_object->GetType();
bEnable = ( !m_taskExecutor->IsForegroundTask() && !m_brain->IsProgram() ) && m_main->CanPlayerInteract();
bEnable = ( !m_taskExecutor->IsForegroundTask() && !m_programmable->IsProgram() ) && m_main->CanPlayerInteract();
EnableInterface(pw, EVENT_OBJECT_PROGEDIT, !m_brain->IsTraceRecord() && m_selScript < m_brain->GetProgramCount() && m_main->CanPlayerInteract());
EnableInterface(pw, EVENT_OBJECT_PROGLIST, bEnable && !m_brain->IsTraceRecord());
EnableInterface(pw, EVENT_OBJECT_PROGADD, !m_brain->IsProgram() && m_main->CanPlayerInteract());
EnableInterface(pw, EVENT_OBJECT_PROGREMOVE, !m_brain->IsProgram() && m_selScript < m_brain->GetProgramCount() && !m_brain->GetProgram(m_selScript)->readOnly && m_main->CanPlayerInteract());
EnableInterface(pw, EVENT_OBJECT_PROGCLONE, !m_brain->IsProgram() && m_selScript < m_brain->GetProgramCount() && m_brain->GetProgram(m_selScript)->runnable && m_main->CanPlayerInteract());
EnableInterface(pw, EVENT_OBJECT_PROGMOVEUP, !m_brain->IsProgram() && m_brain->GetProgramCount() >= 2 && m_selScript > 0 && m_main->CanPlayerInteract());
EnableInterface(pw, EVENT_OBJECT_PROGMOVEDOWN,!m_brain->IsProgram() && m_brain->GetProgramCount() >= 2 && m_selScript < m_brain->GetProgramCount()-1 && m_main->CanPlayerInteract());
EnableInterface(pw, EVENT_OBJECT_PROGEDIT, !m_programmable->IsTraceRecord() && m_selScript < m_programmable->GetProgramCount() && m_main->CanPlayerInteract());
EnableInterface(pw, EVENT_OBJECT_PROGLIST, bEnable && !m_programmable->IsTraceRecord());
EnableInterface(pw, EVENT_OBJECT_PROGADD, !m_programmable->IsProgram() && m_main->CanPlayerInteract());
EnableInterface(pw, EVENT_OBJECT_PROGREMOVE, !m_programmable->IsProgram() && m_selScript < m_programmable->GetProgramCount() && !m_programmable->GetProgram(m_selScript)->readOnly && m_main->CanPlayerInteract());
EnableInterface(pw, EVENT_OBJECT_PROGCLONE, !m_programmable->IsProgram() && m_selScript < m_programmable->GetProgramCount() && m_programmable->GetProgram(m_selScript)->runnable && m_main->CanPlayerInteract());
EnableInterface(pw, EVENT_OBJECT_PROGMOVEUP, !m_programmable->IsProgram() && m_programmable->GetProgramCount() >= 2 && m_selScript > 0 && m_main->CanPlayerInteract());
EnableInterface(pw, EVENT_OBJECT_PROGMOVEDOWN,!m_programmable->IsProgram() && m_programmable->GetProgramCount() >= 2 && m_selScript < m_programmable->GetProgramCount()-1 && m_main->CanPlayerInteract());
EnableInterface(pw, EVENT_OBJECT_LEFT, bEnable);
EnableInterface(pw, EVENT_OBJECT_RIGHT, bEnable);
EnableInterface(pw, EVENT_OBJECT_UP, bEnable);
@ -1832,7 +1831,7 @@ void CObjectInterface::UpdateInterface()
if ( type == OBJECT_MOBILErs ) // shield?
{
if ( (!m_taskExecutor->IsBackgroundTask() || !m_taskExecutor->GetBackgroundTask()->IsBusy()) && !m_brain->IsProgram() )
if ( (!m_taskExecutor->IsBackgroundTask() || !m_taskExecutor->GetBackgroundTask()->IsBusy()) && !m_programmable->IsProgram() )
{
EnableInterface(pw, EVENT_OBJECT_BEGSHIELD, !m_taskExecutor->IsBackgroundTask() && m_main->CanPlayerInteract());
EnableInterface(pw, EVENT_OBJECT_ENDSHIELD, m_taskExecutor->IsBackgroundTask() && m_main->CanPlayerInteract());
@ -1910,11 +1909,11 @@ void CObjectInterface::UpdateInterface()
type == OBJECT_CONTROLLER) // vehicle?
{
bRun = false;
if ( m_selScript < m_brain->GetProgramCount() )
if ( m_selScript < m_programmable->GetProgramCount() )
{
if(m_brain->GetProgram(m_selScript)->runnable)
if(m_programmable->GetProgram(m_selScript)->runnable)
{
m_brain->GetProgram(m_selScript)->script->GetTitle(title);
m_programmable->GetProgram(m_selScript)->script->GetTitle(title);
if ( title[0] != 0 )
{
bRun = true;
@ -1925,23 +1924,23 @@ void CObjectInterface::UpdateInterface()
bRun = false;
}
}
if ( !bEnable && !m_brain->IsProgram() ) bRun = false;
if ( m_brain->IsTraceRecord() ) bRun = false;
if ( !bEnable && !m_programmable->IsProgram() ) bRun = false;
if ( m_programmable->IsTraceRecord() ) bRun = false;
EnableInterface(pw, EVENT_OBJECT_PROGRUN, bRun && m_main->CanPlayerInteract());
pb = static_cast< CButton* >(pw->SearchControl(EVENT_OBJECT_PROGRUN));
if ( pb != 0 )
{
pb->SetIcon(!m_brain->IsProgram() ? 21 : 8); // run/stop
pb->SetIcon(!m_programmable->IsProgram() ? 21 : 8); // run/stop
}
//? pb = (CButton*)pw->SearchControl(EVENT_OBJECT_PROGEDIT);
//? if ( pb != 0 )
//? {
//? pb->SetIcon(!m_brain->IsProgram() ? 22 : 40); // edit/debug
//? pb->SetIcon(!m_programmable->IsProgram() ? 22 : 40); // edit/debug
//? }
BlinkScript(m_brain->IsProgram()); // blinks if script execution
BlinkScript(m_programmable->IsProgram()); // blinks if script execution
}
if ( type == OBJECT_MOBILEfa ||
@ -2068,14 +2067,14 @@ void CObjectInterface::UpdateScript(CWindow *pw)
if ( pl == 0 ) return;
pl->Flush();
for ( int i = 0 ; i < m_brain->GetProgramCount() ; i++ )
for ( int i = 0 ; i < m_programmable->GetProgramCount() ; i++ )
{
sprintf(name, "%d", i+1);
m_brain->GetProgram(i)->script->GetTitle(title);
m_programmable->GetProgram(i)->script->GetTitle(title);
if ( title[0] != 0 )
{
if(!m_brain->GetProgram(i)->readOnly)
if(!m_programmable->GetProgram(i)->readOnly)
{
sprintf(name, "%d: %s", i+1, title);
}

View File

@ -23,12 +23,12 @@
class COldObject;
class CTaskExecutorObject;
class CProgrammableObject;
class CPhysics;
class CMotion;
class CRobotMain;
class CSoundInterface;
class CLevelParserLine;
class CBrain;
struct Program;
namespace Gfx
@ -87,12 +87,12 @@ protected:
Gfx::CCamera* m_camera;
Gfx::CParticle* m_particle;
CRobotMain* m_main;
Ui::CInterface* m_interface;
CInterface* m_interface;
CSoundInterface* m_sound;
COldObject* m_object;
CTaskExecutorObject* m_taskExecutor;
CBrain* m_brain;
CProgrammableObject* m_programmable;
CPhysics* m_physics;
CMotion* m_motion;

View File

@ -34,10 +34,11 @@
#include "graphics/engine/camera.h"
#include "graphics/engine/engine.h"
#include "object/brain.h"
#include "object/object.h"
#include "object/player_profile.h"
#include "object/interface/programmable_object.h"
#include "script/cbottoken.h"
#include "script/script.h"