Moved common interface implementations to separate classes

Additionaly, merged all "inappropariate bot" errors into one and renamed ERR_GENERIC -> ERR_UNKNOWN
master
krzys-h 2015-08-12 16:54:44 +02:00
parent 63d83185b5
commit f7d2f501bb
34 changed files with 1114 additions and 855 deletions

View File

@ -1400,9 +1400,6 @@ msgstr ""
msgid "Unknown command" msgid "Unknown command"
msgstr "" msgstr ""
msgid "Inappropriate bot"
msgstr ""
msgid "Impossible when flying" msgid "Impossible when flying"
msgstr "" msgstr ""
@ -1597,6 +1594,9 @@ msgstr ""
msgid "Do not use in this exercise" msgid "Do not use in this exercise"
msgstr "" msgstr ""
msgid "Inappropriate bot"
msgstr ""
msgid "Building completed" msgid "Building completed"
msgstr "" msgstr ""

View File

@ -150,6 +150,9 @@ set(BASE_SOURCES
object/auto/autopowerstation.cpp object/auto/autopowerstation.cpp
object/auto/autotower.cpp object/auto/autotower.cpp
object/drive_type.cpp object/drive_type.cpp
object/implementation/power_container_impl.cpp
object/implementation/programmable_impl.cpp
object/implementation/task_executor_impl.cpp
object/level/parser.cpp object/level/parser.cpp
object/level/parserexceptions.cpp object/level/parserexceptions.cpp
object/level/parserline.cpp object/level/parserline.cpp

View File

@ -32,11 +32,10 @@
enum Error enum Error
{ {
ERR_OK = 0, //! < ok ERR_OK = 0, //! < ok
ERR_GENERIC = 1, //! < any error ERR_UNKNOWN = 1, //! < any error
ERR_CONTINUE = 2, //! < continues ERR_CONTINUE = 2, //! < continues
ERR_STOP = 3, //! < stops ERR_STOP = 3, //! < stops
ERR_CMD = 4, //! < unknown command ERR_CMD = 4, //! < unknown command
ERR_MANIP_VEH = 100, //! < inappropriate vehicle
ERR_MANIP_FLY = 101, //! < impossible in flight ERR_MANIP_FLY = 101, //! < impossible in flight
ERR_MANIP_BUSY = 102, //! < taking: hands already occupied ERR_MANIP_BUSY = 102, //! < taking: hands already occupied
ERR_MANIP_NIL = 103, //! < taking: nothing has to take ERR_MANIP_NIL = 103, //! < taking: nothing has to take
@ -61,21 +60,16 @@ enum Error
ERR_BUILD_DISABLED = 132, //! < built: can not produce this object in this mission ERR_BUILD_DISABLED = 132, //! < built: can not produce this object in this mission
ERR_BUILD_RESEARCH = 133, //! < built: can not produce not researched object ERR_BUILD_RESEARCH = 133, //! < built: can not produce not researched object
ERR_SEARCH_FLY = 140, //! < not possible in flight ERR_SEARCH_FLY = 140, //! < not possible in flight
ERR_SEARCH_VEH = 141, //! < inappropriate vehicle
ERR_SEARCH_MOTOR = 142, //! < impossible in movement ERR_SEARCH_MOTOR = 142, //! < impossible in movement
ERR_TERRA_VEH = 150, //! < inappropriate vehicle
ERR_TERRA_ENERGY = 151, //! < not enough energy ERR_TERRA_ENERGY = 151, //! < not enough energy
ERR_TERRA_FLOOR = 152, //! < inappropriate ground ERR_TERRA_FLOOR = 152, //! < inappropriate ground
ERR_TERRA_BUILDING = 153, //! < building too close ERR_TERRA_BUILDING = 153, //! < building too close
ERR_TERRA_OBJECT = 154, //! < object too close ERR_TERRA_OBJECT = 154, //! < object too close
ERR_FIRE_VEH = 160, //! < inappropriate vehicle
ERR_FIRE_ENERGY = 161, //! < not enough energy ERR_FIRE_ENERGY = 161, //! < not enough energy
ERR_FIRE_FLY = 162, //! < not possible in flight ERR_FIRE_FLY = 162, //! < not possible in flight
ERR_RECOVER_VEH = 170, //! < inappropriate vehicle
ERR_RECOVER_ENERGY = 171, //! < not enough energy ERR_RECOVER_ENERGY = 171, //! < not enough energy
ERR_RECOVER_NULL = 172, //! < lack of ruin ERR_RECOVER_NULL = 172, //! < lack of ruin
ERR_CONVERT_EMPTY = 180, //! < no stone was transformed ERR_CONVERT_EMPTY = 180, //! < no stone was transformed
ERR_SHIELD_VEH = 190, //! < inappropriate vehicle
ERR_SHIELD_ENERGY = 191, //! < not enough energy ERR_SHIELD_ENERGY = 191, //! < not enough energy
ERR_MOVE_IMPOSSIBLE = 200, //! < move impossible ERR_MOVE_IMPOSSIBLE = 200, //! < move impossible
ERR_FIND_IMPOSSIBLE = 201, //! < find impossible ERR_FIND_IMPOSSIBLE = 201, //! < find impossible
@ -128,6 +122,7 @@ enum Error
ERR_OBLIGATORYTOKEN = 800, //! < compulsory instruction missing ERR_OBLIGATORYTOKEN = 800, //! < compulsory instruction missing
ERR_PROHIBITEDTOKEN = 801, //! < instruction prohibited ERR_PROHIBITEDTOKEN = 801, //! < instruction prohibited
ERR_AIM_IMPOSSIBLE = 900, //! < cannot aim at specified angle(s) ERR_AIM_IMPOSSIBLE = 900, //! < cannot aim at specified angle(s)
ERR_WRONG_BOT = 910, //! < inappropriate bot
INFO_FIRST = 10000, //! < first information INFO_FIRST = 10000, //! < first information
INFO_BUILD = 10001, //! < construction builded INFO_BUILD = 10001, //! < construction builded

View File

@ -581,9 +581,8 @@ void InitializeRestext()
stringsErr[ERR_GENERIC] = TR("Internal error - tell the developers"); stringsErr[ERR_UNKNOWN] = TR("Internal error - tell the developers");
stringsErr[ERR_CMD] = TR("Unknown command"); stringsErr[ERR_CMD] = TR("Unknown command");
stringsErr[ERR_MANIP_VEH] = TR("Inappropriate bot");
stringsErr[ERR_MANIP_FLY] = TR("Impossible when flying"); stringsErr[ERR_MANIP_FLY] = TR("Impossible when flying");
stringsErr[ERR_MANIP_BUSY] = TR("Already carrying something"); stringsErr[ERR_MANIP_BUSY] = TR("Already carrying something");
stringsErr[ERR_MANIP_NIL] = TR("Nothing to grab"); stringsErr[ERR_MANIP_NIL] = TR("Nothing to grab");
@ -608,24 +607,19 @@ void InitializeRestext()
stringsErr[ERR_SEARCH_FLY] = TR("Impossible when flying"); stringsErr[ERR_SEARCH_FLY] = TR("Impossible when flying");
stringsErr[ERR_BUILD_DISABLED] = TR("Can not produce this object in this mission"); stringsErr[ERR_BUILD_DISABLED] = TR("Can not produce this object in this mission");
stringsErr[ERR_BUILD_RESEARCH] = TR("Can not produce not researched object"); stringsErr[ERR_BUILD_RESEARCH] = TR("Can not produce not researched object");
stringsErr[ERR_SEARCH_VEH] = TR("Inappropriate bot");
stringsErr[ERR_SEARCH_MOTOR] = TR("Impossible when moving"); stringsErr[ERR_SEARCH_MOTOR] = TR("Impossible when moving");
stringsErr[ERR_TERRA_VEH] = TR("Inappropriate bot");
stringsErr[ERR_TERRA_ENERGY] = TR("Not enough energy"); stringsErr[ERR_TERRA_ENERGY] = TR("Not enough energy");
stringsErr[ERR_TERRA_FLOOR] = TR("Ground inappropriate"); stringsErr[ERR_TERRA_FLOOR] = TR("Ground inappropriate");
stringsErr[ERR_TERRA_BUILDING] = TR("Building too close"); stringsErr[ERR_TERRA_BUILDING] = TR("Building too close");
stringsErr[ERR_TERRA_OBJECT] = TR("Object too close"); stringsErr[ERR_TERRA_OBJECT] = TR("Object too close");
stringsErr[ERR_RECOVER_VEH] = TR("Inappropriate bot");
stringsErr[ERR_RECOVER_ENERGY] = TR("Not enough energy"); stringsErr[ERR_RECOVER_ENERGY] = TR("Not enough energy");
stringsErr[ERR_RECOVER_NULL] = TR("Nothing to recycle"); stringsErr[ERR_RECOVER_NULL] = TR("Nothing to recycle");
stringsErr[ERR_SHIELD_VEH] = TR("Inappropriate bot");
stringsErr[ERR_SHIELD_ENERGY] = TR("No more energy"); stringsErr[ERR_SHIELD_ENERGY] = TR("No more energy");
stringsErr[ERR_MOVE_IMPOSSIBLE] = TR("Error in instruction move"); stringsErr[ERR_MOVE_IMPOSSIBLE] = TR("Error in instruction move");
stringsErr[ERR_FIND_IMPOSSIBLE] = TR("Object not found"); stringsErr[ERR_FIND_IMPOSSIBLE] = TR("Object not found");
stringsErr[ERR_GOTO_IMPOSSIBLE] = TR("Goto: inaccessible destination"); stringsErr[ERR_GOTO_IMPOSSIBLE] = TR("Goto: inaccessible destination");
stringsErr[ERR_GOTO_ITER] = TR("Goto: inaccessible destination"); stringsErr[ERR_GOTO_ITER] = TR("Goto: inaccessible destination");
stringsErr[ERR_GOTO_BUSY] = TR("Goto: destination occupied"); stringsErr[ERR_GOTO_BUSY] = TR("Goto: destination occupied");
stringsErr[ERR_FIRE_VEH] = TR("Inappropriate bot");
stringsErr[ERR_FIRE_ENERGY] = TR("Not enough energy"); stringsErr[ERR_FIRE_ENERGY] = TR("Not enough energy");
stringsErr[ERR_FIRE_FLY] = TR("Impossible when flying"); stringsErr[ERR_FIRE_FLY] = TR("Impossible when flying");
stringsErr[ERR_CONVERT_EMPTY] = TR("No titanium ore to convert"); stringsErr[ERR_CONVERT_EMPTY] = TR("No titanium ore to convert");
@ -674,6 +668,7 @@ void InitializeRestext()
stringsErr[ERR_ENEMY_OBJECT] = TR("Unable to control enemy objects"); stringsErr[ERR_ENEMY_OBJECT] = TR("Unable to control enemy objects");
stringsErr[ERR_OBLIGATORYTOKEN] = TR("\"%s\" missing in this exercise"); stringsErr[ERR_OBLIGATORYTOKEN] = TR("\"%s\" missing in this exercise");
stringsErr[ERR_PROHIBITEDTOKEN] = TR("Do not use in this exercise"); stringsErr[ERR_PROHIBITEDTOKEN] = TR("Do not use in this exercise");
stringsErr[ERR_WRONG_BOT] = TR("Inappropriate bot");
stringsErr[INFO_BUILD] = TR("Building completed"); stringsErr[INFO_BUILD] = TR("Building completed");
stringsErr[INFO_CONVERT] = TR("Titanium available"); stringsErr[INFO_CONVERT] = TR("Titanium available");

View File

@ -107,7 +107,7 @@ void CAuto::Start(int param)
Error CAuto::StartAction(int param) Error CAuto::StartAction(int param)
{ {
return ERR_GENERIC; return ERR_UNKNOWN;
} }
// Gete a type. // Gete a type.

View File

@ -103,7 +103,7 @@ Error CAutoDestroyer::StartAction(int param)
m_bExplo = false; m_bExplo = false;
} }
else else
return ERR_GENERIC; return ERR_UNKNOWN;
} }
return ERR_OK; return ERR_OK;
} }

View File

@ -153,7 +153,7 @@ Error CAutoFactory::StartAction(int param)
m_speed = 1.0f/3.0f; m_speed = 1.0f/3.0f;
return ERR_OK; return ERR_OK;
} }
return ERR_GENERIC; return ERR_UNKNOWN;
} }
@ -219,10 +219,10 @@ bool CAutoFactory::EventProcess(const Event &event)
type = ObjectTypeFromFactoryButton(event.type); type = ObjectTypeFromFactoryButton(event.type);
Error err = StartAction(type); Error err = StartAction(type);
if( err != ERR_OK && err != ERR_GENERIC ) if( err != ERR_OK && err != ERR_UNKNOWN )
m_main->DisplayError(err, m_object); m_main->DisplayError(err, m_object);
if( err != ERR_GENERIC ) if( err != ERR_UNKNOWN )
return false; return false;
} }

View File

@ -120,7 +120,7 @@ Error CAutoLabo::StartAction(int param)
{ {
if ( m_phase != ALAP_WAIT ) if ( m_phase != ALAP_WAIT )
{ {
return ERR_GENERIC; return ERR_UNKNOWN;
} }
m_research = static_cast<ResearchType>(param); m_research = static_cast<ResearchType>(param);
@ -175,14 +175,14 @@ bool CAutoLabo::EventProcess(const Event &event)
if ( m_object->GetSelect() ) // center selected? if ( m_object->GetSelect() ) // center selected?
{ {
Error err = ERR_GENERIC; Error err = ERR_UNKNOWN;
if ( event.type == EVENT_OBJECT_RiPAW ) err = StartAction(RESEARCH_iPAW); if ( event.type == EVENT_OBJECT_RiPAW ) err = StartAction(RESEARCH_iPAW);
if ( event.type == EVENT_OBJECT_RiGUN ) err = StartAction(RESEARCH_iGUN); if ( event.type == EVENT_OBJECT_RiGUN ) err = StartAction(RESEARCH_iGUN);
if( err != ERR_OK && err != ERR_GENERIC ) if( err != ERR_OK && err != ERR_UNKNOWN )
m_main->DisplayError(err, m_object); m_main->DisplayError(err, m_object);
if( err != ERR_GENERIC ) if( err != ERR_UNKNOWN )
return false; return false;
} }

View File

@ -101,7 +101,7 @@ Error CAutoResearch::StartAction(int param)
{ {
if ( m_phase != ALP_WAIT ) if ( m_phase != ALP_WAIT )
{ {
return ERR_GENERIC; return ERR_UNKNOWN;
} }
m_research = static_cast<ResearchType>(param); m_research = static_cast<ResearchType>(param);
@ -167,7 +167,7 @@ bool CAutoResearch::EventProcess(const Event &event)
if ( m_object->GetSelect() ) // center selected? if ( m_object->GetSelect() ) // center selected?
{ {
Error err = ERR_GENERIC; Error err = ERR_UNKNOWN;
if ( event.type == EVENT_OBJECT_RTANK ) err = StartAction(RESEARCH_TANK); if ( event.type == EVENT_OBJECT_RTANK ) err = StartAction(RESEARCH_TANK);
if ( event.type == EVENT_OBJECT_RFLY ) err = StartAction(RESEARCH_FLY); if ( event.type == EVENT_OBJECT_RFLY ) err = StartAction(RESEARCH_FLY);
if ( event.type == EVENT_OBJECT_RTHUMP ) err = StartAction(RESEARCH_THUMP); if ( event.type == EVENT_OBJECT_RTHUMP ) err = StartAction(RESEARCH_THUMP);
@ -177,10 +177,10 @@ bool CAutoResearch::EventProcess(const Event &event)
if ( event.type == EVENT_OBJECT_RSHIELD ) err = StartAction(RESEARCH_SHIELD); if ( event.type == EVENT_OBJECT_RSHIELD ) err = StartAction(RESEARCH_SHIELD);
if ( event.type == EVENT_OBJECT_RATOMIC ) err = StartAction(RESEARCH_ATOMIC); if ( event.type == EVENT_OBJECT_RATOMIC ) err = StartAction(RESEARCH_ATOMIC);
if( err != ERR_OK && err != ERR_GENERIC ) if( err != ERR_OK && err != ERR_UNKNOWN )
m_main->DisplayError(err, m_object); m_main->DisplayError(err, m_object);
if( err != ERR_GENERIC ) if( err != ERR_UNKNOWN )
return false; return false;
} }

View File

@ -0,0 +1,38 @@
/*
* This file is part of the Colobot: Gold Edition source code
* Copyright (C) 2001-2015, 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/implementation/power_container_impl.h"
CPowerContainerObjectImpl::CPowerContainerObjectImpl(ObjectInterfaceTypes& types, CObject* object)
: CPowerContainerObject(types)
, m_energyLevel(1.0f)
{}
CPowerContainerObjectImpl::~CPowerContainerObjectImpl()
{}
void CPowerContainerObjectImpl::SetEnergyLevel(float level)
{
m_energyLevel = level;
}
float CPowerContainerObjectImpl::GetEnergyLevel()
{
return m_energyLevel;
}

View File

@ -0,0 +1,37 @@
/*
* This file is part of the Colobot: Gold Edition source code
* Copyright (C) 2001-2015, 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
*/
#pragma once
#include "object/interface/power_container_object.h"
class CObject;
class CPowerContainerObjectImpl : public CPowerContainerObject
{
public:
explicit CPowerContainerObjectImpl(ObjectInterfaceTypes& types, CObject* object);
virtual ~CPowerContainerObjectImpl();
void SetEnergyLevel(float level) override;
float GetEnergyLevel() override;
private:
float m_energyLevel;
};

View File

@ -0,0 +1,622 @@
/*
* This file is part of the Colobot: Gold Edition source code
* Copyright (C) 2001-2015, 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/implementation/programmable_impl.h"
#include "math/all.h"
#include "object/object.h"
#include "object/old_object.h"
#include "object/robotmain.h"
#include "object/interface/controllable_object.h"
#include "object/interface/task_executor_object.h"
#include "object/motion/motion.h"
#include "object/motion/motionvehicle.h"
#include "physics/physics.h"
#include "script/script.h"
#include "ui/controls/edit.h"
#include <algorithm>
#include <iomanip>
CProgrammableObjectImpl::CProgrammableObjectImpl(ObjectInterfaceTypes& types, CObject* object)
: CProgrammableObject(types)
, m_object(object)
, m_activity(true)
, m_cmdLine()
, m_program()
, m_currentProgram(nullptr)
, m_activeVirus(false)
, m_scriptRun(nullptr)
, m_soluceName("")
, m_traceRecord(false)
{
assert(m_object != nullptr);
assert(m_object->Implements(ObjectInterfaceType::TaskExecutor));
}
CProgrammableObjectImpl::~CProgrammableObjectImpl()
{}
bool CProgrammableObjectImpl::EventProcess(const Event &event)
{
if (event.type == EVENT_FRAME)
{
if ( m_object->GetRuin() && IsProgram() )
{
StopProgram();
}
if ( GetActivity() )
{
if ( IsProgram() ) // current program?
{
if ( m_currentProgram->script->Continue() )
{
StopProgram();
}
}
if ( m_traceRecord ) // registration of the design in progress?
{
TraceRecordFrame();
}
}
}
return true;
}
void CProgrammableObjectImpl::SetActivity(bool activity)
{
m_activity = activity;
}
bool CProgrammableObjectImpl::GetActivity()
{
return m_activity;
}
void CProgrammableObjectImpl::RunProgram(Program* program)
{
if ( program->script->Run() )
{
m_currentProgram = program; // start new program
m_object->UpdateInterface();
if (m_object->Implements(ObjectInterfaceType::Controllable) && dynamic_cast<CControllableObject*>(m_object)->GetTrainer())
CRobotMain::GetInstancePointer()->StartMissionTimer();
}
}
void CProgrammableObjectImpl::StopProgram()
{
if ( m_currentProgram != nullptr )
{
m_currentProgram->script->Stop();
}
m_currentProgram = nullptr;
m_object->UpdateInterface();
}
bool CProgrammableObjectImpl::IsProgram()
{
return m_currentProgram != nullptr;
}
// Introduces a virus into a program.
// Returns true if it was inserted.
bool CProgrammableObjectImpl::IntroduceVirus()
{
if(m_program.size() == 0) return false;
for ( int i=0 ; i<50 ; i++ )
{
int programIndex = rand() % m_program.size();
if ( m_program[programIndex]->script->IntroduceVirus() ) // tries to introduce
{
m_activeVirus = 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 CProgrammableObjectImpl::SetActiveVirus(bool bActive)
{
m_activeVirus = bActive;
if ( !m_activeVirus ) // virus disabled?
{
m_object->SetVirusMode(false); // chtites (??? - Programerus) letters also
}
}
bool CProgrammableObjectImpl::GetActiveVirus()
{
return m_activeVirus;
}
Program* CProgrammableObjectImpl::AddProgram()
{
assert(m_object->Implements(ObjectInterfaceType::Old)); //TODO
auto program = MakeUnique<Program>();
program->script = MakeUnique<CScript>(dynamic_cast<COldObject*>(this));
program->readOnly = false;
program->runnable = true;
Program* prog = program.get();
AddProgram(std::move(program));
return prog;
}
void CProgrammableObjectImpl::AddProgram(std::unique_ptr<Program> program)
{
m_program.push_back(std::move(program));
m_object->UpdateInterface();
}
void CProgrammableObjectImpl::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());
m_object->UpdateInterface();
}
Program* CProgrammableObjectImpl::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>>& CProgrammableObjectImpl::GetPrograms()
{
return m_program;
}
int CProgrammableObjectImpl::GetProgramCount()
{
return static_cast<int>(m_program.size());
}
int CProgrammableObjectImpl::GetProgramIndex(Program* program)
{
for(unsigned int i = 0; i < m_program.size(); i++)
{
if(m_program[i].get() == program)
{
return i;
}
}
return -1;
}
int CProgrammableObjectImpl::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;
}
Program* CProgrammableObjectImpl::GetProgram(int index)
{
if(index < 0 || index >= static_cast<int>(m_program.size()))
return nullptr;
return m_program[index].get();
}
Program* CProgrammableObjectImpl::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();
}
// Name management scripts to load.
void CProgrammableObjectImpl::SetScriptRun(Program* program)
{
m_scriptRun = program;
}
Program* CProgrammableObjectImpl::GetScriptRun()
{
return m_scriptRun;
}
void CProgrammableObjectImpl::SetSoluceName(const std::string& name)
{
m_soluceName = name;
}
const std::string& CProgrammableObjectImpl::GetSoluceName()
{
return m_soluceName;
}
// Load a script solution, in the first free script.
// If there is already an identical script, nothing is loaded.
bool CProgrammableObjectImpl::ReadSoluce(const std::string& 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 CProgrammableObjectImpl::ReadProgram(Program* program, const std::string& filename)
{
if ( program->script->ReadScript(filename.c_str()) ) return true;
return false;
}
// Indicates whether a program is compiled correctly.
bool CProgrammableObjectImpl::GetCompile(Program* program)
{
return program->script->GetCompile();
}
// Saves a script in a text file.
bool CProgrammableObjectImpl::WriteProgram(Program* program, const std::string& filename)
{
if ( program->script->WriteScript(filename.c_str()) ) return true;
return false;
}
// Load a stack of script implementation from a file.
bool CProgrammableObjectImpl::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: m_selScript = op;
if ( !m_program[op]->script->ReadStack(file) ) return false;
}
}
return true;
}
// Save the script implementation stack of a file.
bool CProgrammableObjectImpl::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;
}
const int MAXTRACERECORD = 1000;
// Start of registration of the design.
void CProgrammableObjectImpl::TraceRecordStart()
{
if (m_traceRecord)
{
TraceRecordStop();
}
assert(m_object->Implements(ObjectInterfaceType::Old)); // TODO
CMotionVehicle* motionVehicle = dynamic_cast<CMotionVehicle*>(dynamic_cast<COldObjectInterface*>(m_object)->GetMotion());
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 CProgrammableObjectImpl::TraceRecordFrame()
{
TraceOper oper = TO_STOP;
Math::Vector pos;
float angle, len, speed;
assert(m_object->Implements(ObjectInterfaceType::Old)); // TODO
CMotionVehicle* motionVehicle = dynamic_cast<CMotionVehicle*>(dynamic_cast<COldObjectInterface*>(m_object)->GetMotion());
assert(motionVehicle != nullptr);
CPhysics* physics = dynamic_cast<COldObjectInterface*>(m_object)->GetPhysics();
speed = physics->GetLinMotionX(MO_REASPEED);
if ( speed > 0.0f ) oper = TO_ADVANCE;
if ( speed < 0.0f ) oper = TO_RECEDE;
speed = 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 CProgrammableObjectImpl::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 CProgrammableObjectImpl::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 CProgrammableObjectImpl::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 CProgrammableObjectImpl::IsTraceRecord()
{
return m_traceRecord;
}
void CProgrammableObjectImpl::SetCmdLine(unsigned int rank, float value)
{
if (rank == m_cmdLine.size())
{
m_cmdLine.push_back(value);
}
else if (rank < m_cmdLine.size())
{
m_cmdLine[rank] = value;
}
else
{
// should never happen
assert(false);
}
}
float CProgrammableObjectImpl::GetCmdLine(unsigned int rank)
{
if ( rank >= m_cmdLine.size() ) return 0.0f;
return m_cmdLine[rank];
}
std::vector<float>& CProgrammableObjectImpl::GetCmdLine()
{
return m_cmdLine;
}

View File

@ -0,0 +1,130 @@
/*
* This file is part of the Colobot: Gold Edition source code
* Copyright (C) 2001-2015, 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
*/
#pragma once
#include "object/interface/interactive_object.h"
#include "object/interface/programmable_object.h"
#include "object/trace_color.h"
#include "math/vector.h"
#include <sstream>
class CObject;
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;
};
class CProgrammableObjectImpl : public CProgrammableObject
{
public:
explicit CProgrammableObjectImpl(ObjectInterfaceTypes& types, CObject* object);
virtual ~CProgrammableObjectImpl();
bool EventProcess(const Event& event);
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(const std::string& name) override;
const std::string& GetSoluceName() override;
bool ReadSoluce(const std::string& filename) override;
bool ReadProgram(Program* program, const std::string& filename) override;
bool GetCompile(Program* program) override;
bool WriteProgram(Program* program, const std::string& 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;
void TraceRecordStart() override;
void TraceRecordStop() override;
bool IsTraceRecord() override;
void SetActivity(bool bMode) override;
bool GetActivity() override;
void SetCmdLine(unsigned int rank, float value);
float GetCmdLine(unsigned int rank) override;
std::vector<float>& GetCmdLine();
private:
//! 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);
private:
CObject* m_object;
private:
bool m_activity;
std::vector<float> m_cmdLine;
std::vector<std::unique_ptr<Program>> m_program;
Program* m_currentProgram;
bool m_activeVirus;
Program* m_scriptRun;
std::string m_soluceName;
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

@ -0,0 +1,120 @@
/*
* This file is part of the Colobot: Gold Edition source code
* Copyright (C) 2001-2015, 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/implementation/task_executor_impl.h"
#include "object/object.h"
#include "object/task/taskmanager.h"
CTaskExecutorObjectImpl::CTaskExecutorObjectImpl(ObjectInterfaceTypes& types, CObject* object)
: CTaskExecutorObject(types)
, m_object(object)
{}
CTaskExecutorObjectImpl::~CTaskExecutorObjectImpl()
{}
bool CTaskExecutorObjectImpl::EventProcess(const Event &event)
{
// NOTE: This function CAN'T BE CALLED BETWEEN CTaskManager::EventProcess AND CScriptFunctions::Process, otherwise weird stuff may happen to scripts (they'll be stuck executing the same task over and over again)
EndedTask();
if ( m_foregroundTask != nullptr )
{
m_foregroundTask->EventProcess(event);
}
if ( m_backgroundTask != nullptr )
{
m_backgroundTask->EventProcess(event);
}
return true;
}
bool CTaskExecutorObjectImpl::IsForegroundTask()
{
return m_foregroundTask != nullptr;
}
bool CTaskExecutorObjectImpl::IsBackgroundTask()
{
return m_backgroundTask != nullptr;
}
CTaskManager* CTaskExecutorObjectImpl::GetForegroundTask()
{
return m_foregroundTask.get();
}
CTaskManager* CTaskExecutorObjectImpl::GetBackgroundTask()
{
return m_backgroundTask.get();
}
// Stops the current task.
void CTaskExecutorObjectImpl::StopForegroundTask()
{
if (m_foregroundTask != nullptr)
{
m_foregroundTask->Abort();
m_foregroundTask.reset();
}
}
// Stops the current secondary task.
void CTaskExecutorObjectImpl::StopBackgroundTask()
{
if (m_backgroundTask != nullptr)
{
m_backgroundTask->Abort();
m_backgroundTask.reset();
}
}
// Completes the task when the time came.
Error CTaskExecutorObjectImpl::EndedTask()
{
if (m_backgroundTask != nullptr) // current task?
{
Error err = m_backgroundTask->IsEnded();
if ( err != ERR_CONTINUE ) // job ended?
{
m_backgroundTask.reset();
m_object->UpdateInterface();
}
}
if (m_foregroundTask != nullptr) // current task?
{
Error err = m_foregroundTask->IsEnded();
if ( err != ERR_CONTINUE ) // job ended?
{
m_foregroundTask.reset();
m_object->UpdateInterface();
}
return err;
}
return ERR_STOP;
}

View File

@ -0,0 +1,77 @@
/*
* This file is part of the Colobot: Gold Edition source code
* Copyright (C) 2001-2015, 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
*/
#pragma once
#include "object/interface/task_executor_object.h"
#include <memory>
class CObject;
class CTaskManager;
class CTaskExecutorObjectImpl : public CTaskExecutorObject
{
public:
explicit CTaskExecutorObjectImpl(ObjectInterfaceTypes& types, CObject* object);
virtual ~CTaskExecutorObjectImpl();
bool EventProcess(const Event& event);
bool IsForegroundTask() override;
bool IsBackgroundTask() override;
CTaskManager* GetForegroundTask() override;
CTaskManager* GetBackgroundTask() override;
void StopForegroundTask() override;
void StopBackgroundTask() override;
Error StartTaskTake() { return ERR_WRONG_BOT; }
Error StartTaskManip(TaskManipOrder order, TaskManipArm arm) { return ERR_WRONG_BOT; }
Error StartTaskFlag(TaskFlagOrder order, int rank) { return ERR_WRONG_BOT; }
Error StartTaskBuild(ObjectType type) { return ERR_WRONG_BOT; }
Error StartTaskSearch() { return ERR_WRONG_BOT; }
Error StartTaskDeleteMark() { return ERR_WRONG_BOT; }
Error StartTaskTerraform() { return ERR_WRONG_BOT; }
Error StartTaskRecover() { return ERR_WRONG_BOT; }
Error StartTaskFire(float delay) { return ERR_WRONG_BOT; }
Error StartTaskFireAnt(Math::Vector impact) { return ERR_WRONG_BOT; }
Error StartTaskSpiderExplo() { return ERR_WRONG_BOT; }
Error StartTaskPen(bool down, TraceColor color = TraceColor::Default) { return ERR_WRONG_BOT; }
Error StartTaskWait(float time) { return ERR_UNKNOWN; }
Error StartTaskAdvance(float length) { return ERR_UNKNOWN; }
Error StartTaskTurn(float angle) { return ERR_UNKNOWN; }
Error StartTaskGoto(Math::Vector pos, float altitude, TaskGotoGoal goalMode, TaskGotoCrash crashMode) { return ERR_UNKNOWN; }
Error StartTaskInfo(const char *name, float value, float power, bool bSend) { return ERR_UNKNOWN; }
Error StartTaskShield(TaskShieldMode mode, float delay = 1000.0f) { return ERR_WRONG_BOT; }
Error StartTaskGunGoal(float dirV, float dirH) { return ERR_WRONG_BOT; }
private:
Error EndedTask();
protected:
std::unique_ptr<CTaskManager> m_foregroundTask;
std::unique_ptr<CTaskManager> m_backgroundTask;
private:
CObject* m_object;
};

View File

@ -61,13 +61,13 @@ public:
virtual void SetScriptRun(Program* rank) = 0; virtual void SetScriptRun(Program* rank) = 0;
virtual Program* GetScriptRun() = 0; virtual Program* GetScriptRun() = 0;
virtual void SetSoluceName(char *name) = 0; virtual void SetSoluceName(const std::string& name) = 0;
virtual char* GetSoluceName() = 0; virtual const std::string& GetSoluceName() = 0;
virtual bool ReadSoluce(char* filename) = 0; virtual bool ReadSoluce(const std::string& filename) = 0;
virtual bool ReadProgram(Program* program, const char* filename) = 0; virtual bool ReadProgram(Program* program, const std::string& filename) = 0;
virtual bool GetCompile(Program* program) = 0; virtual bool GetCompile(Program* program) = 0;
virtual bool WriteProgram(Program* program, const char* filename) = 0; virtual bool WriteProgram(Program* program, const std::string& filename) = 0;
virtual bool ReadStack(FILE *file) = 0; virtual bool ReadStack(FILE *file) = 0;
virtual bool WriteStack(FILE *file) = 0; virtual bool WriteStack(FILE *file) = 0;

View File

@ -83,6 +83,9 @@ public:
//! Reads object properties from line in level file //! Reads object properties from line in level file
virtual void Read(CLevelParserLine* line) = 0; virtual void Read(CLevelParserLine* line) = 0;
//! Updates all interface controls
virtual void UpdateInterface() {};
//! Check if object implements the given type of interface //! Check if object implements the given type of interface
inline bool Implements(ObjectInterfaceType type) const inline bool Implements(ObjectInterfaceType type) const
{ {

View File

@ -86,8 +86,6 @@ static float debug_arm2 = 0.0f;
static float debug_arm3 = 0.0f; static float debug_arm3 = 0.0f;
#endif #endif
const int MAXTRACERECORD = 1000;
// Object's constructor. // Object's constructor.
@ -95,14 +93,14 @@ COldObject::COldObject(int id)
: CObject(id, OBJECT_NULL) : CObject(id, OBJECT_NULL)
, CInteractiveObject(m_implementedInterfaces) , CInteractiveObject(m_implementedInterfaces)
, CTransportableObject(m_implementedInterfaces) , CTransportableObject(m_implementedInterfaces)
, CTaskExecutorObject(m_implementedInterfaces) , CTaskExecutorObjectImpl(m_implementedInterfaces, this)
, CProgrammableObject(m_implementedInterfaces) , CProgrammableObjectImpl(m_implementedInterfaces, this)
, CJostleableObject(m_implementedInterfaces) , CJostleableObject(m_implementedInterfaces)
, CCarrierObject(m_implementedInterfaces) , CCarrierObject(m_implementedInterfaces)
, CPoweredObject(m_implementedInterfaces) , CPoweredObject(m_implementedInterfaces)
, CMovableObject(m_implementedInterfaces) , CMovableObject(m_implementedInterfaces)
, CControllableObject(m_implementedInterfaces) , CControllableObject(m_implementedInterfaces)
, CPowerContainerObject(m_implementedInterfaces) , CPowerContainerObjectImpl(m_implementedInterfaces, this)
{ {
// A bit of a hack since we don't have subclasses yet, set externally in SetProgrammable() // A bit of a hack since we don't have subclasses yet, set externally in SetProgrammable()
m_implementedInterfaces[static_cast<int>(ObjectInterfaceType::Programmable)] = false; m_implementedInterfaces[static_cast<int>(ObjectInterfaceType::Programmable)] = false;
@ -132,7 +130,6 @@ COldObject::COldObject(int id)
m_cargo = 0; m_cargo = 0;
m_transporter = 0; m_transporter = 0;
m_transporterLink = 0; m_transporterLink = 0;
m_energy = 1.0f;
m_shield = 1.0f; m_shield = 1.0f;
m_range = 0.0f; m_range = 0.0f;
m_transparency = 0.0f; m_transparency = 0.0f;
@ -185,22 +182,11 @@ COldObject::COldObject(int id)
m_partiSel[i] = -1; m_partiSel[i] = -1;
} }
m_cmdLine.clear();
m_activity = true;
m_currentProgram = nullptr;
m_bActiveVirus = false;
m_time = 0.0f; m_time = 0.0f;
m_burnTime = 0.0f; m_burnTime = 0.0f;
m_buttonAxe = EVENT_NULL; m_buttonAxe = EVENT_NULL;
m_scriptRun = nullptr;
m_soluceName[0] = 0;
m_traceRecord = false;
DeleteAllCrashSpheres(); DeleteAllCrashSpheres();
} }
@ -806,7 +792,7 @@ void COldObject::Write(CLevelParserLine* line)
// Sets the parameters of the command line. // Sets the parameters of the command line.
CLevelParserParamVec cmdline; CLevelParserParamVec cmdline;
for(float value : m_cmdLine) for(float value : GetCmdLine())
{ {
cmdline.push_back(MakeUnique<CLevelParserParam>(value)); cmdline.push_back(MakeUnique<CLevelParserParam>(value));
} }
@ -820,7 +806,7 @@ void COldObject::Write(CLevelParserLine* line)
if ( Implements(ObjectInterfaceType::Programmable) ) if ( Implements(ObjectInterfaceType::Programmable) )
{ {
line->AddParam("bVirusActive", MakeUnique<CLevelParserParam>(m_bActiveVirus)); line->AddParam("bVirusActive", MakeUnique<CLevelParserParam>(GetActiveVirus()));
} }
if ( Implements(ObjectInterfaceType::TaskExecutor) ) if ( Implements(ObjectInterfaceType::TaskExecutor) )
@ -891,7 +877,7 @@ void COldObject::Read(CLevelParserLine* line)
if (Implements(ObjectInterfaceType::Programmable)) if (Implements(ObjectInterfaceType::Programmable))
{ {
m_bActiveVirus = line->GetParam("bVirusActive")->AsBool(false); SetActiveVirus(line->GetParam("bVirusActive")->AsBool(false));
} }
if (Implements(ObjectInterfaceType::TaskExecutor)) if (Implements(ObjectInterfaceType::TaskExecutor))
@ -1382,29 +1368,6 @@ float COldObject::GetInfoReturn()
return m_infoReturn; return m_infoReturn;
} }
void COldObject::SetCmdLine(unsigned int rank, float value)
{
if (rank == m_cmdLine.size())
{
m_cmdLine.push_back(value);
}
else if (rank < m_cmdLine.size())
{
m_cmdLine[rank] = value;
}
else
{
// should never happen
assert(false);
}
}
float COldObject::GetCmdLine(unsigned int rank)
{
if ( rank >= m_cmdLine.size() ) return 0.0f;
return m_cmdLine[rank];
}
// Returns matrices of an object portion. // Returns matrices of an object portion.
@ -1735,10 +1698,10 @@ void COldObject::FlatParent()
void COldObject::UpdateEnergyMapping() void COldObject::UpdateEnergyMapping()
{ {
if (Math::IsEqual(m_energy, m_lastEnergy, 0.01f)) if (Math::IsEqual(GetEnergyLevel(), m_lastEnergy, 0.01f))
return; return;
m_lastEnergy = m_energy; m_lastEnergy = GetEnergyLevel();
Gfx::Material mat; Gfx::Material mat;
mat.diffuse = Gfx::Color(1.0f, 1.0f, 1.0f); // white mat.diffuse = Gfx::Color(1.0f, 1.0f, 1.0f); // white
@ -1763,7 +1726,7 @@ void COldObject::UpdateEnergyMapping()
b = 3.0f; // dimensions of the battery (according to y) b = 3.0f; // dimensions of the battery (according to y)
} }
float i = 0.50f+0.25f*m_energy; // origin float i = 0.50f+0.25f*GetEnergyLevel(); // origin
float s = i+0.25f; // width float s = i+0.25f; // width
float au = (s-i)/(b-a); float au = (s-i)/(b-a);
@ -1822,15 +1785,8 @@ bool COldObject::EventProcess(const Event &event)
#endif #endif
} }
if ( m_foregroundTask != nullptr ) // NOTE: This should be called befoce CProgrammableObjectImpl::EventProcess, see the other note inside this function
{ if (!CTaskExecutorObjectImpl::EventProcess(event)) return true;
m_foregroundTask->EventProcess(event);
}
if ( m_backgroundTask != nullptr )
{
m_backgroundTask->EventProcess(event);
}
if ( m_physics != nullptr ) if ( m_physics != nullptr )
{ {
@ -1848,14 +1804,6 @@ bool COldObject::EventProcess(const Event &event)
} }
} }
if (Implements(ObjectInterfaceType::Programmable))
{
if ( GetRuin() && m_currentProgram != nullptr )
{
StopProgram();
}
}
if (Implements(ObjectInterfaceType::Movable) && m_physics != nullptr) if (Implements(ObjectInterfaceType::Movable) && m_physics != nullptr)
{ {
bool deselectedStop = !GetSelect(); bool deselectedStop = !GetSelect();
@ -1990,6 +1938,8 @@ bool COldObject::EventProcess(const Event &event)
if (!m_motion->EventProcess(event)) return false; if (!m_motion->EventProcess(event)) return false;
} }
if (!CProgrammableObjectImpl::EventProcess(event)) return true;
if ( event.type == EVENT_FRAME ) if ( event.type == EVENT_FRAME )
{ {
return EventFrame(event); return EventFrame(event);
@ -2025,28 +1975,6 @@ bool COldObject::EventFrame(const Event &event)
UpdateTransformObject(); UpdateTransformObject();
UpdateSelectParticle(); UpdateSelectParticle();
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();
return true; return true;
} }
@ -2292,25 +2220,6 @@ float COldObject::GetAbsTime()
} }
// Management of energy contained in a battery.
// Single subject possesses the battery energy, but not the vehicle that carries the battery!
void COldObject::SetEnergyLevel(float level)
{
if ( level < 0.0f ) level = 0.0f;
if ( level > 1.0f ) level = 1.0f;
m_energy = level;
}
float COldObject::GetEnergyLevel()
{
if ( m_type != OBJECT_POWER &&
m_type != OBJECT_ATOMIC &&
m_type != OBJECT_STATION &&
m_type != OBJECT_ENERGY ) return 0.0f;
return m_energy;
}
float COldObject::GetCapacity() float COldObject::GetCapacity()
{ {
return m_type == OBJECT_ATOMIC ? 10.0f : 1.0f; return m_type == OBJECT_ATOMIC ? 10.0f : 1.0f;
@ -3310,603 +3219,25 @@ Error COldObject::StartTaskGunGoal(float dirV, float dirH)
return err; return err;
} }
// Indicates whether the object is busy with a task.
bool COldObject::IsForegroundTask()
{
return (m_foregroundTask.get() != nullptr);
}
bool COldObject::IsBackgroundTask()
{
return (m_backgroundTask.get() != nullptr);
}
CTaskManager* COldObject::GetForegroundTask()
{
return m_foregroundTask.get();
}
CTaskManager* COldObject::GetBackgroundTask()
{
return m_backgroundTask.get();
}
// Stops the current task.
void COldObject::StopForegroundTask()
{
if (m_foregroundTask != nullptr)
{
m_foregroundTask->Abort();
m_foregroundTask.reset();
}
}
// Stops the current secondary task.
void COldObject::StopBackgroundTask()
{
if (m_backgroundTask != nullptr)
{
m_backgroundTask->Abort();
m_backgroundTask.reset();
}
}
// Completes the task when the time came.
Error COldObject::EndedTask()
{
if (m_backgroundTask.get() != nullptr) // current task?
{
Error err = m_backgroundTask->IsEnded();
if ( err != ERR_CONTINUE ) // job ended?
{
m_backgroundTask.reset();
UpdateInterface();
}
}
if (m_foregroundTask.get() != nullptr) // current task?
{
Error err = m_foregroundTask->IsEnded();
if ( err != ERR_CONTINUE ) // job ended?
{
m_foregroundTask.reset();
UpdateInterface();
}
return err;
}
return ERR_STOP;
}
// Management of the activity of an object.
void COldObject::SetActivity(bool activity)
{
m_activity = activity;
}
bool COldObject::GetActivity()
{
return m_activity;
}
void COldObject::UpdateInterface() void COldObject::UpdateInterface()
{ {
if (m_objectInterface != nullptr && GetSelect()) if (m_objectInterface != nullptr && GetSelect())
{ {
m_objectInterface->UpdateInterface(); m_objectInterface->UpdateInterface();
} }
CreateSelectParticle();
m_main->UpdateShortcuts();
} }
// Stops the running program.
void COldObject::StopProgram() void COldObject::StopProgram()
{ {
StopForegroundTask(); CProgrammableObjectImpl::StopProgram();
if ( m_type == OBJECT_HUMAN ||
m_type == OBJECT_TECH ) return;
if ( m_currentProgram != nullptr )
{
m_currentProgram->script->Stop();
}
m_currentProgram = nullptr;
//TODO: I don't want CProgrammableObjectImpl to depend on motion and physics, refactor this somehow
m_physics->SetMotorSpeedX(0.0f); m_physics->SetMotorSpeedX(0.0f);
m_physics->SetMotorSpeedY(0.0f); m_physics->SetMotorSpeedY(0.0f);
m_physics->SetMotorSpeedZ(0.0f); m_physics->SetMotorSpeedZ(0.0f);
m_motion->SetAction(-1); 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

@ -37,6 +37,10 @@
#include "object/interface/task_executor_object.h" #include "object/interface/task_executor_object.h"
#include "object/interface/transportable_object.h" #include "object/interface/transportable_object.h"
#include "object/implementation/power_container_impl.h"
#include "object/implementation/programmable_impl.h"
#include "object/implementation/task_executor_impl.h"
// The father of all parts must always be the part number zero! // The father of all parts must always be the part number zero!
const int OBJECTMAXPART = 40; const int OBJECTMAXPART = 40;
@ -58,21 +62,6 @@ struct ObjectPart
Math::Matrix matWorld; 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 namespace Ui
{ {
class CObjectInterface; class CObjectInterface;
@ -82,14 +71,14 @@ class CObjectInterface;
class COldObject : public CObject, class COldObject : public CObject,
public CInteractiveObject, public CInteractiveObject,
public CTransportableObject, public CTransportableObject,
public CTaskExecutorObject, public CTaskExecutorObjectImpl,
public CProgrammableObject, public CProgrammableObjectImpl,
public CJostleableObject, public CJostleableObject,
public CCarrierObject, public CCarrierObject,
public CPoweredObject, public CPoweredObject,
public CMovableObject, public CMovableObject,
public CControllableObject, public CControllableObject,
public CPowerContainerObject public CPowerContainerObjectImpl
{ {
friend class CObjectFactory; friend class CObjectFactory;
friend class CObjectManager; friend class CObjectManager;
@ -185,9 +174,6 @@ public:
CObject* GetTransporter() override; CObject* GetTransporter() override;
void SetTransporterPart(int part) override; void SetTransporterPart(int part) override;
void SetCmdLine(unsigned int rank, float value);
float GetCmdLine(unsigned int rank) override;
Math::Matrix* GetRotateMatrix(int part); Math::Matrix* GetRotateMatrix(int part);
Math::Matrix* GetWorldMatrix(int part) override; Math::Matrix* GetWorldMatrix(int part) override;
@ -199,9 +185,6 @@ public:
float GetAbsTime(); float GetAbsTime();
void SetEnergyLevel(float level) override;
float GetEnergyLevel() override;
float GetCapacity() override; float GetCapacity() override;
bool IsRechargeable() override; bool IsRechargeable() override;
@ -238,9 +221,6 @@ public:
void SetSelectable(bool bMode); void SetSelectable(bool bMode);
bool GetSelectable() override; bool GetSelectable() override;
void SetActivity(bool activity) override;
bool GetActivity() override;
void SetVisible(bool bVisible); void SetVisible(bool bVisible);
void SetCheckToken(bool bMode); void SetCheckToken(bool bMode);
@ -318,54 +298,10 @@ public:
Error StartTaskShield(TaskShieldMode mode, float delay = 1000.0f) override; Error StartTaskShield(TaskShieldMode mode, float delay = 1000.0f) override;
Error StartTaskGunGoal(float dirV, float dirH) override; Error StartTaskGunGoal(float dirV, float dirH) override;
bool IsForegroundTask() override; void UpdateInterface() override;
bool IsBackgroundTask() override;
CTaskManager* GetForegroundTask() override;
CTaskManager* GetBackgroundTask() override;
void StopForegroundTask() override;
void StopBackgroundTask() override;
void UpdateInterface();
bool IsProgram() override;
void RunProgram(Program* program) override;
int GetProgram() override;
void StopProgram() 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: protected:
bool EventFrame(const Event &event); bool EventFrame(const Event &event);
void VirusFrame(float rTime); void VirusFrame(float rTime);
@ -382,13 +318,6 @@ protected:
Error EndedTask(); 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: protected:
Gfx::CEngine* m_engine; Gfx::CEngine* m_engine;
Gfx::CLightManager* m_lightMan; Gfx::CLightManager* m_lightMan;
@ -417,7 +346,6 @@ protected:
CObject* m_cargo; // object transported CObject* m_cargo; // object transported
CObject* m_transporter; // object with the latter CObject* m_transporter; // object with the latter
int m_transporterLink; // part int m_transporterLink; // part
float m_energy; // energy contained (if battery)
float m_lastEnergy; float m_lastEnergy;
float m_shield; // shield float m_shield; // shield
float m_range; // flight range float m_range; // flight range
@ -462,30 +390,8 @@ protected:
float m_infoReturn; float m_infoReturn;
std::vector<float> m_cmdLine;
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; EventType m_buttonAxe;
float m_time; float m_time;
float m_burnTime; 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

@ -3710,7 +3710,7 @@ void CRobotMain::CreateScene(bool soluce, bool fixScene, bool resetObject)
if (soluce && oldObj->Implements(ObjectInterfaceType::Programmable) && line->GetParam("soluce")->IsDefined()) if (soluce && oldObj->Implements(ObjectInterfaceType::Programmable) && line->GetParam("soluce")->IsDefined())
dynamic_cast<CProgrammableObject*>(oldObj) dynamic_cast<CProgrammableObject*>(oldObj)
->SetSoluceName(const_cast<char*>(line->GetParam("soluce")->AsPath("ai").c_str())); ->SetSoluceName(line->GetParam("soluce")->AsPath("ai"));
if (line->GetParam("reset")->AsBool(false)) if (line->GetParam("reset")->AsBool(false))
oldObj->SetAnimateOnReset(true); oldObj->SetAnimateOnReset(true);
@ -4717,8 +4717,8 @@ void CRobotMain::CompileScript(bool soluce)
if (soluce) if (soluce)
{ {
char* name = programmable->GetSoluceName(); std::string name = programmable->GetSoluceName();
if (name[0] != 0) if (!name.empty())
{ {
programmable->ReadSoluce(name); // load solution programmable->ReadSoluce(name); // load solution
} }

View File

@ -646,7 +646,7 @@ Error CTaskBuild::FlatFloor()
if ( m_type == OBJECT_PARA ) radius = 20.0f; if ( m_type == OBJECT_PARA ) radius = 20.0f;
if ( m_type == OBJECT_INFO ) radius = 5.0f; if ( m_type == OBJECT_INFO ) radius = 5.0f;
if ( m_type == OBJECT_DESTROYER) radius = 20.0f; if ( m_type == OBJECT_DESTROYER) radius = 20.0f;
//if ( radius == 0.0f ) return ERR_GENERIC; //if ( radius == 0.0f ) return ERR_UNKNOWN;
center = m_metal->GetPosition(); center = m_metal->GetPosition();
angle = m_terrain->GetFineSlope(center); angle = m_terrain->GetFineSlope(center);

View File

@ -287,7 +287,7 @@ Error CTaskFire::Start(float delay)
type != OBJECT_MOBILEti && type != OBJECT_MOBILEti &&
type != OBJECT_MOBILEwi && type != OBJECT_MOBILEwi &&
type != OBJECT_MOBILEii && type != OBJECT_MOBILEii &&
type != OBJECT_MOBILErc ) return ERR_FIRE_VEH; type != OBJECT_MOBILErc ) return ERR_WRONG_BOT;
//? if ( !m_physics->GetLand() ) return ERR_FIRE_FLY; //? if ( !m_physics->GetLand() ) return ERR_FIRE_FLY;

View File

@ -92,13 +92,13 @@ Error CTaskFireAnt::Start(Math::Vector impact)
m_impact = impact; m_impact = impact;
m_bError = true; // operation impossible m_bError = true; // operation impossible
if ( !m_physics->GetLand() ) return ERR_FIRE_VEH; if ( !m_physics->GetLand() ) return ERR_WRONG_BOT;
type = m_object->GetType(); type = m_object->GetType();
if ( type != OBJECT_ANT ) return ERR_FIRE_VEH; if ( type != OBJECT_ANT ) return ERR_WRONG_BOT;
// Insect on its back? // Insect on its back?
if ( m_object->GetFixed() ) return ERR_FIRE_VEH; if ( m_object->GetFixed() ) return ERR_WRONG_BOT;
m_physics->SetMotorSpeed(Math::Vector(0.0f, 0.0f, 0.0f)); m_physics->SetMotorSpeed(Math::Vector(0.0f, 0.0f, 0.0f));

View File

@ -936,7 +936,7 @@ Error CTaskGoto::IsEnded()
{ {
m_physics->SetMotorSpeedX(0.0f); // stops the advance m_physics->SetMotorSpeedX(0.0f); // stops the advance
m_physics->SetMotorSpeedZ(0.0f); // stops the rotation m_physics->SetMotorSpeedZ(0.0f); // stops the rotation
m_error = ERR_GENERIC; m_error = ERR_UNKNOWN;
return m_error; return m_error;
} }
if ( m_time >= 1.0f ) if ( m_time >= 1.0f )

View File

@ -183,7 +183,7 @@ Error CTaskManager::StartTaskShield(TaskShieldMode mode, float delay)
{ {
return (static_cast<CTaskShield*>(m_task))->Start(mode, delay); return (static_cast<CTaskShield*>(m_task))->Start(mode, delay);
} }
return ERR_GENERIC; return ERR_UNKNOWN;
} }
// Shoots. // Shoots.
@ -233,7 +233,7 @@ bool CTaskManager::EventProcess(const Event &event)
Error CTaskManager::IsEnded() Error CTaskManager::IsEnded()
{ {
if ( m_task == 0 ) return ERR_GENERIC; if ( m_task == 0 ) return ERR_UNKNOWN;
return m_task->IsEnded(); return m_task->IsEnded();
} }

View File

@ -308,7 +308,7 @@ Error CTaskManip::Start(TaskManipOrder order, TaskManipArm arm)
if ( m_arm != TMA_FFRONT && if ( m_arm != TMA_FFRONT &&
m_arm != TMA_FBACK && m_arm != TMA_FBACK &&
m_arm != TMA_POWER && m_arm != TMA_POWER &&
m_arm != TMA_GRAB ) return ERR_MANIP_VEH; m_arm != TMA_GRAB ) return ERR_WRONG_BOT;
m_physics->SetMotorSpeed(Math::Vector(0.0f, 0.0f, 0.0f)); m_physics->SetMotorSpeed(Math::Vector(0.0f, 0.0f, 0.0f));
@ -374,7 +374,7 @@ Error CTaskManip::Start(TaskManipOrder order, TaskManipArm arm)
type != OBJECT_MOBILEta && type != OBJECT_MOBILEta &&
type != OBJECT_MOBILEwa && type != OBJECT_MOBILEwa &&
type != OBJECT_MOBILEia && type != OBJECT_MOBILEia &&
type != OBJECT_MOBILEsa ) return ERR_MANIP_VEH; type != OBJECT_MOBILEsa ) return ERR_WRONG_BOT;
if ( m_bSubm ) // submarine? if ( m_bSubm ) // submarine?
{ {

View File

@ -139,7 +139,7 @@ Error CTaskPen::Start(bool bDown, TraceColor color)
m_bError = true; // operation impossible m_bError = true; // operation impossible
type = m_object->GetType(); type = m_object->GetType();
if ( type != OBJECT_MOBILEdr ) return ERR_FIRE_VEH; if ( type != OBJECT_MOBILEdr ) return ERR_WRONG_BOT;
m_bError = false; // ok m_bError = false; // ok

View File

@ -180,10 +180,10 @@ bool CTaskRecover::EventProcess(const Event &event)
Error CTaskRecover::Start() Error CTaskRecover::Start()
{ {
m_bError = true; // operation impossible m_bError = true; // operation impossible
if ( !m_physics->GetLand() ) return ERR_RECOVER_VEH; if ( !m_physics->GetLand() ) return ERR_WRONG_BOT;
ObjectType type = m_object->GetType(); ObjectType type = m_object->GetType();
if ( type != OBJECT_MOBILErr ) return ERR_RECOVER_VEH; if ( type != OBJECT_MOBILErr ) return ERR_WRONG_BOT;
assert(m_object->Implements(ObjectInterfaceType::Powered)); assert(m_object->Implements(ObjectInterfaceType::Powered));
CObject* power = dynamic_cast<CPoweredObject*>(m_object)->GetPower(); CObject* power = dynamic_cast<CPoweredObject*>(m_object)->GetPower();

View File

@ -140,7 +140,7 @@ Error CTaskSearch::Start()
if ( type != OBJECT_MOBILEfs && if ( type != OBJECT_MOBILEfs &&
type != OBJECT_MOBILEts && type != OBJECT_MOBILEts &&
type != OBJECT_MOBILEws && type != OBJECT_MOBILEws &&
type != OBJECT_MOBILEis ) return ERR_SEARCH_VEH; type != OBJECT_MOBILEis ) return ERR_WRONG_BOT;
m_hand = TSH_DOWN; m_hand = TSH_DOWN;
m_phase = TSP_DOWN; m_phase = TSP_DOWN;

View File

@ -287,10 +287,10 @@ Error CTaskShield::Start(TaskShieldMode mode, float delay)
} }
ObjectType type = m_object->GetType(); ObjectType type = m_object->GetType();
if ( type != OBJECT_MOBILErs ) return ERR_SHIELD_VEH; if ( type != OBJECT_MOBILErs ) return ERR_WRONG_BOT;
m_bError = true; // operation impossible m_bError = true; // operation impossible
if ( !m_physics->GetLand() ) return ERR_SHIELD_VEH; if ( !m_physics->GetLand() ) return ERR_WRONG_BOT;
CObject* power = m_object->GetPower(); CObject* power = m_object->GetPower();
if (power == nullptr || !power->Implements(ObjectInterfaceType::PowerContainer)) return ERR_SHIELD_ENERGY; if (power == nullptr || !power->Implements(ObjectInterfaceType::PowerContainer)) return ERR_SHIELD_ENERGY;

View File

@ -110,7 +110,7 @@ Error CTaskTake::Start()
ObjectType type = m_object->GetType(); ObjectType type = m_object->GetType();
if ( type != OBJECT_HUMAN && if ( type != OBJECT_HUMAN &&
type != OBJECT_TECH ) return ERR_MANIP_VEH; type != OBJECT_TECH ) return ERR_WRONG_BOT;
m_physics->SetMotorSpeed(Math::Vector(0.0f, 0.0f, 0.0f)); m_physics->SetMotorSpeed(Math::Vector(0.0f, 0.0f, 0.0f));

View File

@ -203,10 +203,10 @@ Error CTaskTerraform::Start()
ObjectType type; ObjectType type;
m_bError = true; // operation impossible m_bError = true; // operation impossible
if ( !m_physics->GetLand() ) return ERR_TERRA_VEH; if ( !m_physics->GetLand() ) return ERR_WRONG_BOT;
type = m_object->GetType(); type = m_object->GetType();
if ( type != OBJECT_MOBILErt ) return ERR_TERRA_VEH; if ( type != OBJECT_MOBILErt ) return ERR_WRONG_BOT;
power = m_object->GetPower(); power = m_object->GetPower();
if ( power == nullptr || !power->Implements(ObjectInterfaceType::PowerContainer) ) return ERR_TERRA_ENERGY; if ( power == nullptr || !power->Implements(ObjectInterfaceType::PowerContainer) ) return ERR_TERRA_ENERGY;

View File

@ -487,6 +487,8 @@ void CScript::Stop()
{ {
if ( !m_bRun ) return; if ( !m_bRun ) return;
m_taskExecutor->StopForegroundTask();
if( m_botProg != 0 ) if( m_botProg != 0 )
{ {
m_botProg->Stop(); m_botProg->Stop();

View File

@ -718,8 +718,8 @@ bool CScriptFunctions::rFactory(CBotVar* thisclass, CBotVar* var, CBotVar* resul
CObject* factory = static_cast<CObject*>(thisclass->GetUserPtr()); CObject* factory = static_cast<CObject*>(thisclass->GetUserPtr());
if (factory == nullptr) if (factory == nullptr)
{ {
exception = ERR_GENERIC; exception = ERR_UNKNOWN;
result->SetValInt(ERR_GENERIC); result->SetValInt(ERR_UNKNOWN);
GetLogger()->Error("in object.factory() - factory is nullptr"); GetLogger()->Error("in object.factory() - factory is nullptr");
return false; return false;
} }
@ -736,8 +736,8 @@ bool CScriptFunctions::rFactory(CBotVar* thisclass, CBotVar* var, CBotVar* resul
CAutoFactory* automat = static_cast<CAutoFactory*>(factory->GetAuto()); CAutoFactory* automat = static_cast<CAutoFactory*>(factory->GetAuto());
if (automat == nullptr) if (automat == nullptr)
{ {
exception = ERR_GENERIC; exception = ERR_UNKNOWN;
result->SetValInt(ERR_GENERIC); result->SetValInt(ERR_UNKNOWN);
GetLogger()->Error("in object.factory() - automat is nullptr"); GetLogger()->Error("in object.factory() - automat is nullptr");
return false; return false;
} }
@ -752,7 +752,7 @@ bool CScriptFunctions::rFactory(CBotVar* thisclass, CBotVar* var, CBotVar* resul
if ( err == ERR_OK ) automat->SetProgram(program); if ( err == ERR_OK ) automat->SetProgram(program);
} }
else else
err = ERR_GENERIC; err = ERR_UNKNOWN;
} }
} }
else else
@ -824,7 +824,7 @@ bool CScriptFunctions::rResearch(CBotVar* thisclass, CBotVar* var, CBotVar* resu
err = automat->StartAction(type); err = automat->StartAction(type);
} }
else else
err = ERR_GENERIC; err = ERR_UNKNOWN;
} }
else else
err = ERR_BUILD_DISABLED; err = ERR_BUILD_DISABLED;
@ -1417,7 +1417,7 @@ bool CScriptFunctions::rBuild(CBotVar* var, CBotVar* result, int& exception, voi
oType != OBJECT_HUMAN && oType != OBJECT_HUMAN &&
oType != OBJECT_TECH ) oType != OBJECT_TECH )
{ {
err = ERR_MANIP_VEH; // Wrong object err = ERR_WRONG_BOT; // Wrong object
} }
else else
{ {
@ -2475,10 +2475,10 @@ bool CScriptFunctions::rShield(CBotVar* var, CBotVar* result, int& exception, vo
// only shielder can use shield() // only shielder can use shield()
if (pThis->GetType() != OBJECT_MOBILErs) if (pThis->GetType() != OBJECT_MOBILErs)
{ {
result->SetValInt(ERR_MANIP_VEH); // return error result->SetValInt(ERR_WRONG_BOT); // return error
if (script->m_errMode == ERM_STOP) if (script->m_errMode == ERM_STOP)
{ {
exception = ERR_MANIP_VEH; exception = ERR_WRONG_BOT;
return false; return false;
} }
return true; return true;