diff --git a/po/colobot.pot b/po/colobot.pot index ecfc905a..770aca01 100644 --- a/po/colobot.pot +++ b/po/colobot.pot @@ -1400,9 +1400,6 @@ msgstr "" msgid "Unknown command" msgstr "" -msgid "Inappropriate bot" -msgstr "" - msgid "Impossible when flying" msgstr "" @@ -1597,6 +1594,9 @@ msgstr "" msgid "Do not use in this exercise" msgstr "" +msgid "Inappropriate bot" +msgstr "" + msgid "Building completed" msgstr "" diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index f939533f..c41139fe 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -150,6 +150,9 @@ set(BASE_SOURCES object/auto/autopowerstation.cpp object/auto/autotower.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/parserexceptions.cpp object/level/parserline.cpp diff --git a/src/common/global.h b/src/common/global.h index 3d5998c8..17d6f143 100644 --- a/src/common/global.h +++ b/src/common/global.h @@ -32,11 +32,10 @@ enum Error { ERR_OK = 0, //! < ok - ERR_GENERIC = 1, //! < any error + ERR_UNKNOWN = 1, //! < any error ERR_CONTINUE = 2, //! < continues ERR_STOP = 3, //! < stops ERR_CMD = 4, //! < unknown command - ERR_MANIP_VEH = 100, //! < inappropriate vehicle ERR_MANIP_FLY = 101, //! < impossible in flight ERR_MANIP_BUSY = 102, //! < taking: hands already occupied 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_RESEARCH = 133, //! < built: can not produce not researched object ERR_SEARCH_FLY = 140, //! < not possible in flight - ERR_SEARCH_VEH = 141, //! < inappropriate vehicle ERR_SEARCH_MOTOR = 142, //! < impossible in movement - ERR_TERRA_VEH = 150, //! < inappropriate vehicle ERR_TERRA_ENERGY = 151, //! < not enough energy ERR_TERRA_FLOOR = 152, //! < inappropriate ground ERR_TERRA_BUILDING = 153, //! < building too close ERR_TERRA_OBJECT = 154, //! < object too close - ERR_FIRE_VEH = 160, //! < inappropriate vehicle ERR_FIRE_ENERGY = 161, //! < not enough energy ERR_FIRE_FLY = 162, //! < not possible in flight - ERR_RECOVER_VEH = 170, //! < inappropriate vehicle ERR_RECOVER_ENERGY = 171, //! < not enough energy ERR_RECOVER_NULL = 172, //! < lack of ruin ERR_CONVERT_EMPTY = 180, //! < no stone was transformed - ERR_SHIELD_VEH = 190, //! < inappropriate vehicle ERR_SHIELD_ENERGY = 191, //! < not enough energy ERR_MOVE_IMPOSSIBLE = 200, //! < move impossible ERR_FIND_IMPOSSIBLE = 201, //! < find impossible @@ -128,6 +122,7 @@ enum Error ERR_OBLIGATORYTOKEN = 800, //! < compulsory instruction missing ERR_PROHIBITEDTOKEN = 801, //! < instruction prohibited ERR_AIM_IMPOSSIBLE = 900, //! < cannot aim at specified angle(s) + ERR_WRONG_BOT = 910, //! < inappropriate bot INFO_FIRST = 10000, //! < first information INFO_BUILD = 10001, //! < construction builded diff --git a/src/common/restext.cpp b/src/common/restext.cpp index f2291f7c..7b64995b 100644 --- a/src/common/restext.cpp +++ b/src/common/restext.cpp @@ -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_MANIP_VEH] = TR("Inappropriate bot"); stringsErr[ERR_MANIP_FLY] = TR("Impossible when flying"); stringsErr[ERR_MANIP_BUSY] = TR("Already carrying something"); stringsErr[ERR_MANIP_NIL] = TR("Nothing to grab"); @@ -608,24 +607,19 @@ void InitializeRestext() stringsErr[ERR_SEARCH_FLY] = TR("Impossible when flying"); 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_SEARCH_VEH] = TR("Inappropriate bot"); 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_FLOOR] = TR("Ground inappropriate"); stringsErr[ERR_TERRA_BUILDING] = TR("Building 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_NULL] = TR("Nothing to recycle"); - stringsErr[ERR_SHIELD_VEH] = TR("Inappropriate bot"); stringsErr[ERR_SHIELD_ENERGY] = TR("No more energy"); stringsErr[ERR_MOVE_IMPOSSIBLE] = TR("Error in instruction move"); stringsErr[ERR_FIND_IMPOSSIBLE] = TR("Object not found"); stringsErr[ERR_GOTO_IMPOSSIBLE] = TR("Goto: inaccessible destination"); stringsErr[ERR_GOTO_ITER] = TR("Goto: inaccessible destination"); 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_FLY] = TR("Impossible when flying"); 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_OBLIGATORYTOKEN] = TR("\"%s\" missing 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_CONVERT] = TR("Titanium available"); diff --git a/src/object/auto/auto.cpp b/src/object/auto/auto.cpp index e1ed9ea9..9c611229 100644 --- a/src/object/auto/auto.cpp +++ b/src/object/auto/auto.cpp @@ -107,7 +107,7 @@ void CAuto::Start(int param) Error CAuto::StartAction(int param) { - return ERR_GENERIC; + return ERR_UNKNOWN; } // Gete a type. diff --git a/src/object/auto/autodestroyer.cpp b/src/object/auto/autodestroyer.cpp index dcafffff..bd6bb6f6 100644 --- a/src/object/auto/autodestroyer.cpp +++ b/src/object/auto/autodestroyer.cpp @@ -103,7 +103,7 @@ Error CAutoDestroyer::StartAction(int param) m_bExplo = false; } else - return ERR_GENERIC; + return ERR_UNKNOWN; } return ERR_OK; } diff --git a/src/object/auto/autofactory.cpp b/src/object/auto/autofactory.cpp index 55ed0f94..2c4b862d 100644 --- a/src/object/auto/autofactory.cpp +++ b/src/object/auto/autofactory.cpp @@ -153,7 +153,7 @@ Error CAutoFactory::StartAction(int param) m_speed = 1.0f/3.0f; return ERR_OK; } - return ERR_GENERIC; + return ERR_UNKNOWN; } @@ -219,10 +219,10 @@ bool CAutoFactory::EventProcess(const Event &event) type = ObjectTypeFromFactoryButton(event.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); - if( err != ERR_GENERIC ) + if( err != ERR_UNKNOWN ) return false; } diff --git a/src/object/auto/autolabo.cpp b/src/object/auto/autolabo.cpp index 64d2f19b..9601358f 100644 --- a/src/object/auto/autolabo.cpp +++ b/src/object/auto/autolabo.cpp @@ -120,7 +120,7 @@ Error CAutoLabo::StartAction(int param) { if ( m_phase != ALAP_WAIT ) { - return ERR_GENERIC; + return ERR_UNKNOWN; } m_research = static_cast<ResearchType>(param); @@ -175,14 +175,14 @@ bool CAutoLabo::EventProcess(const Event &event) 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_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); - if( err != ERR_GENERIC ) + if( err != ERR_UNKNOWN ) return false; } diff --git a/src/object/auto/autoresearch.cpp b/src/object/auto/autoresearch.cpp index eaf0d8fa..8db14f17 100644 --- a/src/object/auto/autoresearch.cpp +++ b/src/object/auto/autoresearch.cpp @@ -101,7 +101,7 @@ Error CAutoResearch::StartAction(int param) { if ( m_phase != ALP_WAIT ) { - return ERR_GENERIC; + return ERR_UNKNOWN; } m_research = static_cast<ResearchType>(param); @@ -167,7 +167,7 @@ bool CAutoResearch::EventProcess(const Event &event) 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_RFLY ) err = StartAction(RESEARCH_FLY); 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_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); - if( err != ERR_GENERIC ) + if( err != ERR_UNKNOWN ) return false; } diff --git a/src/object/implementation/power_container_impl.cpp b/src/object/implementation/power_container_impl.cpp new file mode 100644 index 00000000..a8add3eb --- /dev/null +++ b/src/object/implementation/power_container_impl.cpp @@ -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; +} diff --git a/src/object/implementation/power_container_impl.h b/src/object/implementation/power_container_impl.h new file mode 100644 index 00000000..c7a537a6 --- /dev/null +++ b/src/object/implementation/power_container_impl.h @@ -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; +}; diff --git a/src/object/implementation/programmable_impl.cpp b/src/object/implementation/programmable_impl.cpp new file mode 100644 index 00000000..01b51bd6 --- /dev/null +++ b/src/object/implementation/programmable_impl.cpp @@ -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; +} diff --git a/src/object/implementation/programmable_impl.h b/src/object/implementation/programmable_impl.h new file mode 100644 index 00000000..f80af53a --- /dev/null +++ b/src/object/implementation/programmable_impl.h @@ -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; +}; diff --git a/src/object/implementation/task_executor_impl.cpp b/src/object/implementation/task_executor_impl.cpp new file mode 100644 index 00000000..11d3a2d5 --- /dev/null +++ b/src/object/implementation/task_executor_impl.cpp @@ -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; +} diff --git a/src/object/implementation/task_executor_impl.h b/src/object/implementation/task_executor_impl.h new file mode 100644 index 00000000..2c206c94 --- /dev/null +++ b/src/object/implementation/task_executor_impl.h @@ -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; +}; diff --git a/src/object/interface/programmable_object.h b/src/object/interface/programmable_object.h index a2d0fceb..63c339e0 100644 --- a/src/object/interface/programmable_object.h +++ b/src/object/interface/programmable_object.h @@ -61,13 +61,13 @@ public: virtual void SetScriptRun(Program* rank) = 0; virtual Program* GetScriptRun() = 0; - virtual void SetSoluceName(char *name) = 0; - virtual char* GetSoluceName() = 0; + virtual void SetSoluceName(const std::string& name) = 0; + virtual const std::string& GetSoluceName() = 0; - virtual bool ReadSoluce(char* filename) = 0; - virtual bool ReadProgram(Program* program, const char* filename) = 0; + virtual bool ReadSoluce(const std::string& filename) = 0; + virtual bool ReadProgram(Program* program, const std::string& filename) = 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 WriteStack(FILE *file) = 0; diff --git a/src/object/object.h b/src/object/object.h index ab7dd59d..8ded4949 100644 --- a/src/object/object.h +++ b/src/object/object.h @@ -83,6 +83,9 @@ public: //! Reads object properties from line in level file virtual void Read(CLevelParserLine* line) = 0; + //! Updates all interface controls + virtual void UpdateInterface() {}; + //! Check if object implements the given type of interface inline bool Implements(ObjectInterfaceType type) const { diff --git a/src/object/old_object.cpp b/src/object/old_object.cpp index 4b13d29e..78f27fb8 100644 --- a/src/object/old_object.cpp +++ b/src/object/old_object.cpp @@ -86,8 +86,6 @@ static float debug_arm2 = 0.0f; static float debug_arm3 = 0.0f; #endif -const int MAXTRACERECORD = 1000; - // Object's constructor. @@ -95,14 +93,14 @@ COldObject::COldObject(int id) : CObject(id, OBJECT_NULL) , CInteractiveObject(m_implementedInterfaces) , CTransportableObject(m_implementedInterfaces) - , CTaskExecutorObject(m_implementedInterfaces) - , CProgrammableObject(m_implementedInterfaces) + , CTaskExecutorObjectImpl(m_implementedInterfaces, this) + , CProgrammableObjectImpl(m_implementedInterfaces, this) , CJostleableObject(m_implementedInterfaces) , CCarrierObject(m_implementedInterfaces) , CPoweredObject(m_implementedInterfaces) , CMovableObject(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() m_implementedInterfaces[static_cast<int>(ObjectInterfaceType::Programmable)] = false; @@ -132,7 +130,6 @@ COldObject::COldObject(int id) m_cargo = 0; m_transporter = 0; m_transporterLink = 0; - m_energy = 1.0f; m_shield = 1.0f; m_range = 0.0f; m_transparency = 0.0f; @@ -185,22 +182,11 @@ COldObject::COldObject(int id) m_partiSel[i] = -1; } - m_cmdLine.clear(); - - 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(); } @@ -806,7 +792,7 @@ void COldObject::Write(CLevelParserLine* line) // Sets the parameters of the command line. CLevelParserParamVec cmdline; - for(float value : m_cmdLine) + for(float value : GetCmdLine()) { cmdline.push_back(MakeUnique<CLevelParserParam>(value)); } @@ -820,7 +806,7 @@ void COldObject::Write(CLevelParserLine* line) if ( Implements(ObjectInterfaceType::Programmable) ) { - line->AddParam("bVirusActive", MakeUnique<CLevelParserParam>(m_bActiveVirus)); + line->AddParam("bVirusActive", MakeUnique<CLevelParserParam>(GetActiveVirus())); } if ( Implements(ObjectInterfaceType::TaskExecutor) ) @@ -891,7 +877,7 @@ void COldObject::Read(CLevelParserLine* line) if (Implements(ObjectInterfaceType::Programmable)) { - m_bActiveVirus = line->GetParam("bVirusActive")->AsBool(false); + SetActiveVirus(line->GetParam("bVirusActive")->AsBool(false)); } if (Implements(ObjectInterfaceType::TaskExecutor)) @@ -1382,29 +1368,6 @@ float COldObject::GetInfoReturn() 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. @@ -1735,10 +1698,10 @@ void COldObject::FlatParent() void COldObject::UpdateEnergyMapping() { - if (Math::IsEqual(m_energy, m_lastEnergy, 0.01f)) + if (Math::IsEqual(GetEnergyLevel(), m_lastEnergy, 0.01f)) return; - m_lastEnergy = m_energy; + m_lastEnergy = GetEnergyLevel(); Gfx::Material mat; 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) } - float i = 0.50f+0.25f*m_energy; // origin + float i = 0.50f+0.25f*GetEnergyLevel(); // origin float s = i+0.25f; // width float au = (s-i)/(b-a); @@ -1822,15 +1785,8 @@ bool COldObject::EventProcess(const Event &event) #endif } - if ( m_foregroundTask != nullptr ) - { - m_foregroundTask->EventProcess(event); - } - - if ( m_backgroundTask != nullptr ) - { - m_backgroundTask->EventProcess(event); - } + // NOTE: This should be called befoce CProgrammableObjectImpl::EventProcess, see the other note inside this function + if (!CTaskExecutorObjectImpl::EventProcess(event)) return true; 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) { bool deselectedStop = !GetSelect(); @@ -1990,6 +1938,8 @@ bool COldObject::EventProcess(const Event &event) if (!m_motion->EventProcess(event)) return false; } + if (!CProgrammableObjectImpl::EventProcess(event)) return true; + if ( event.type == EVENT_FRAME ) { return EventFrame(event); @@ -2025,28 +1975,6 @@ bool COldObject::EventFrame(const Event &event) UpdateTransformObject(); 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; } @@ -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() { return m_type == OBJECT_ATOMIC ? 10.0f : 1.0f; @@ -3310,603 +3219,25 @@ Error COldObject::StartTaskGunGoal(float dirV, float dirH) 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() { if (m_objectInterface != nullptr && GetSelect()) { m_objectInterface->UpdateInterface(); } + + CreateSelectParticle(); + m_main->UpdateShortcuts(); } - - -// 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; + CProgrammableObjectImpl::StopProgram(); + //TODO: I don't want CProgrammableObjectImpl to depend on motion and physics, refactor this somehow 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(); } diff --git a/src/object/old_object.h b/src/object/old_object.h index 59039d9b..23bd193b 100644 --- a/src/object/old_object.h +++ b/src/object/old_object.h @@ -37,6 +37,10 @@ #include "object/interface/task_executor_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! const int OBJECTMAXPART = 40; @@ -58,21 +62,6 @@ 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; @@ -82,14 +71,14 @@ class CObjectInterface; class COldObject : public CObject, public CInteractiveObject, public CTransportableObject, - public CTaskExecutorObject, - public CProgrammableObject, + public CTaskExecutorObjectImpl, + public CProgrammableObjectImpl, public CJostleableObject, public CCarrierObject, public CPoweredObject, public CMovableObject, public CControllableObject, - public CPowerContainerObject + public CPowerContainerObjectImpl { friend class CObjectFactory; friend class CObjectManager; @@ -185,9 +174,6 @@ public: CObject* GetTransporter() 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* GetWorldMatrix(int part) override; @@ -199,9 +185,6 @@ public: float GetAbsTime(); - void SetEnergyLevel(float level) override; - float GetEnergyLevel() override; - float GetCapacity() override; bool IsRechargeable() override; @@ -238,9 +221,6 @@ public: void SetSelectable(bool bMode); bool GetSelectable() override; - void SetActivity(bool activity) override; - bool GetActivity() override; - void SetVisible(bool bVisible); void SetCheckToken(bool bMode); @@ -318,54 +298,10 @@ public: Error StartTaskShield(TaskShieldMode mode, float delay = 1000.0f) override; Error StartTaskGunGoal(float dirV, float dirH) override; - bool IsForegroundTask() override; - bool IsBackgroundTask() override; - CTaskManager* GetForegroundTask() override; - CTaskManager* GetBackgroundTask() override; - void StopForegroundTask() override; - void StopBackgroundTask() override; + void UpdateInterface() override; - 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); @@ -382,13 +318,6 @@ 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; @@ -417,7 +346,6 @@ protected: CObject* m_cargo; // object transported CObject* m_transporter; // object with the latter int m_transporterLink; // part - float m_energy; // energy contained (if battery) float m_lastEnergy; float m_shield; // shield float m_range; // flight range @@ -462,30 +390,8 @@ protected: 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; 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; }; diff --git a/src/object/robotmain.cpp b/src/object/robotmain.cpp index b18d7d99..d6a521e8 100644 --- a/src/object/robotmain.cpp +++ b/src/object/robotmain.cpp @@ -3710,7 +3710,7 @@ void CRobotMain::CreateScene(bool soluce, bool fixScene, bool resetObject) if (soluce && oldObj->Implements(ObjectInterfaceType::Programmable) && line->GetParam("soluce")->IsDefined()) 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)) oldObj->SetAnimateOnReset(true); @@ -4717,8 +4717,8 @@ void CRobotMain::CompileScript(bool soluce) if (soluce) { - char* name = programmable->GetSoluceName(); - if (name[0] != 0) + std::string name = programmable->GetSoluceName(); + if (!name.empty()) { programmable->ReadSoluce(name); // load solution } diff --git a/src/object/task/taskbuild.cpp b/src/object/task/taskbuild.cpp index 9270805b..b19efc3b 100644 --- a/src/object/task/taskbuild.cpp +++ b/src/object/task/taskbuild.cpp @@ -646,7 +646,7 @@ Error CTaskBuild::FlatFloor() if ( m_type == OBJECT_PARA ) radius = 20.0f; if ( m_type == OBJECT_INFO ) radius = 5.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(); angle = m_terrain->GetFineSlope(center); diff --git a/src/object/task/taskfire.cpp b/src/object/task/taskfire.cpp index 35542852..58fc5a9e 100644 --- a/src/object/task/taskfire.cpp +++ b/src/object/task/taskfire.cpp @@ -287,7 +287,7 @@ Error CTaskFire::Start(float delay) type != OBJECT_MOBILEti && type != OBJECT_MOBILEwi && 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; diff --git a/src/object/task/taskfireant.cpp b/src/object/task/taskfireant.cpp index 57ecd4e4..a52064e0 100644 --- a/src/object/task/taskfireant.cpp +++ b/src/object/task/taskfireant.cpp @@ -92,13 +92,13 @@ Error CTaskFireAnt::Start(Math::Vector impact) m_impact = impact; 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(); - if ( type != OBJECT_ANT ) return ERR_FIRE_VEH; + if ( type != OBJECT_ANT ) return ERR_WRONG_BOT; // 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)); diff --git a/src/object/task/taskgoto.cpp b/src/object/task/taskgoto.cpp index 2b2d2e56..b9ae9374 100644 --- a/src/object/task/taskgoto.cpp +++ b/src/object/task/taskgoto.cpp @@ -936,7 +936,7 @@ Error CTaskGoto::IsEnded() { m_physics->SetMotorSpeedX(0.0f); // stops the advance m_physics->SetMotorSpeedZ(0.0f); // stops the rotation - m_error = ERR_GENERIC; + m_error = ERR_UNKNOWN; return m_error; } if ( m_time >= 1.0f ) diff --git a/src/object/task/taskmanager.cpp b/src/object/task/taskmanager.cpp index 7357e975..311a0737 100644 --- a/src/object/task/taskmanager.cpp +++ b/src/object/task/taskmanager.cpp @@ -183,7 +183,7 @@ Error CTaskManager::StartTaskShield(TaskShieldMode mode, float delay) { return (static_cast<CTaskShield*>(m_task))->Start(mode, delay); } - return ERR_GENERIC; + return ERR_UNKNOWN; } // Shoots. @@ -233,7 +233,7 @@ bool CTaskManager::EventProcess(const Event &event) Error CTaskManager::IsEnded() { - if ( m_task == 0 ) return ERR_GENERIC; + if ( m_task == 0 ) return ERR_UNKNOWN; return m_task->IsEnded(); } diff --git a/src/object/task/taskmanip.cpp b/src/object/task/taskmanip.cpp index fe7ab92b..e3681760 100644 --- a/src/object/task/taskmanip.cpp +++ b/src/object/task/taskmanip.cpp @@ -308,7 +308,7 @@ Error CTaskManip::Start(TaskManipOrder order, TaskManipArm arm) if ( m_arm != TMA_FFRONT && m_arm != TMA_FBACK && 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)); @@ -374,7 +374,7 @@ Error CTaskManip::Start(TaskManipOrder order, TaskManipArm arm) type != OBJECT_MOBILEta && type != OBJECT_MOBILEwa && type != OBJECT_MOBILEia && - type != OBJECT_MOBILEsa ) return ERR_MANIP_VEH; + type != OBJECT_MOBILEsa ) return ERR_WRONG_BOT; if ( m_bSubm ) // submarine? { diff --git a/src/object/task/taskpen.cpp b/src/object/task/taskpen.cpp index a6b57664..7e9311b8 100644 --- a/src/object/task/taskpen.cpp +++ b/src/object/task/taskpen.cpp @@ -139,7 +139,7 @@ Error CTaskPen::Start(bool bDown, TraceColor color) m_bError = true; // operation impossible type = m_object->GetType(); - if ( type != OBJECT_MOBILEdr ) return ERR_FIRE_VEH; + if ( type != OBJECT_MOBILEdr ) return ERR_WRONG_BOT; m_bError = false; // ok diff --git a/src/object/task/taskrecover.cpp b/src/object/task/taskrecover.cpp index 956b1ec2..b712b8b0 100644 --- a/src/object/task/taskrecover.cpp +++ b/src/object/task/taskrecover.cpp @@ -180,10 +180,10 @@ bool CTaskRecover::EventProcess(const Event &event) Error CTaskRecover::Start() { 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(); - if ( type != OBJECT_MOBILErr ) return ERR_RECOVER_VEH; + if ( type != OBJECT_MOBILErr ) return ERR_WRONG_BOT; assert(m_object->Implements(ObjectInterfaceType::Powered)); CObject* power = dynamic_cast<CPoweredObject*>(m_object)->GetPower(); diff --git a/src/object/task/tasksearch.cpp b/src/object/task/tasksearch.cpp index 35b78dab..968e1085 100644 --- a/src/object/task/tasksearch.cpp +++ b/src/object/task/tasksearch.cpp @@ -140,7 +140,7 @@ Error CTaskSearch::Start() if ( type != OBJECT_MOBILEfs && type != OBJECT_MOBILEts && type != OBJECT_MOBILEws && - type != OBJECT_MOBILEis ) return ERR_SEARCH_VEH; + type != OBJECT_MOBILEis ) return ERR_WRONG_BOT; m_hand = TSH_DOWN; m_phase = TSP_DOWN; diff --git a/src/object/task/taskshield.cpp b/src/object/task/taskshield.cpp index 946ed23f..bc94adf2 100644 --- a/src/object/task/taskshield.cpp +++ b/src/object/task/taskshield.cpp @@ -287,10 +287,10 @@ Error CTaskShield::Start(TaskShieldMode mode, float delay) } 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 - if ( !m_physics->GetLand() ) return ERR_SHIELD_VEH; + if ( !m_physics->GetLand() ) return ERR_WRONG_BOT; CObject* power = m_object->GetPower(); if (power == nullptr || !power->Implements(ObjectInterfaceType::PowerContainer)) return ERR_SHIELD_ENERGY; diff --git a/src/object/task/tasktake.cpp b/src/object/task/tasktake.cpp index 2ba350c4..c2a40842 100644 --- a/src/object/task/tasktake.cpp +++ b/src/object/task/tasktake.cpp @@ -110,7 +110,7 @@ Error CTaskTake::Start() ObjectType type = m_object->GetType(); 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)); diff --git a/src/object/task/taskterraform.cpp b/src/object/task/taskterraform.cpp index a439ade0..df3e7f1b 100644 --- a/src/object/task/taskterraform.cpp +++ b/src/object/task/taskterraform.cpp @@ -203,10 +203,10 @@ Error CTaskTerraform::Start() ObjectType type; 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(); - if ( type != OBJECT_MOBILErt ) return ERR_TERRA_VEH; + if ( type != OBJECT_MOBILErt ) return ERR_WRONG_BOT; power = m_object->GetPower(); if ( power == nullptr || !power->Implements(ObjectInterfaceType::PowerContainer) ) return ERR_TERRA_ENERGY; diff --git a/src/script/script.cpp b/src/script/script.cpp index e66f8365..f3b783ab 100644 --- a/src/script/script.cpp +++ b/src/script/script.cpp @@ -487,6 +487,8 @@ void CScript::Stop() { if ( !m_bRun ) return; + m_taskExecutor->StopForegroundTask(); + if( m_botProg != 0 ) { m_botProg->Stop(); diff --git a/src/script/scriptfunc.cpp b/src/script/scriptfunc.cpp index 54a2fe52..21e388cc 100644 --- a/src/script/scriptfunc.cpp +++ b/src/script/scriptfunc.cpp @@ -718,8 +718,8 @@ bool CScriptFunctions::rFactory(CBotVar* thisclass, CBotVar* var, CBotVar* resul CObject* factory = static_cast<CObject*>(thisclass->GetUserPtr()); if (factory == nullptr) { - exception = ERR_GENERIC; - result->SetValInt(ERR_GENERIC); + exception = ERR_UNKNOWN; + result->SetValInt(ERR_UNKNOWN); GetLogger()->Error("in object.factory() - factory is nullptr"); return false; } @@ -736,8 +736,8 @@ bool CScriptFunctions::rFactory(CBotVar* thisclass, CBotVar* var, CBotVar* resul CAutoFactory* automat = static_cast<CAutoFactory*>(factory->GetAuto()); if (automat == nullptr) { - exception = ERR_GENERIC; - result->SetValInt(ERR_GENERIC); + exception = ERR_UNKNOWN; + result->SetValInt(ERR_UNKNOWN); GetLogger()->Error("in object.factory() - automat is nullptr"); return false; } @@ -752,7 +752,7 @@ bool CScriptFunctions::rFactory(CBotVar* thisclass, CBotVar* var, CBotVar* resul if ( err == ERR_OK ) automat->SetProgram(program); } else - err = ERR_GENERIC; + err = ERR_UNKNOWN; } } else @@ -824,7 +824,7 @@ bool CScriptFunctions::rResearch(CBotVar* thisclass, CBotVar* var, CBotVar* resu err = automat->StartAction(type); } else - err = ERR_GENERIC; + err = ERR_UNKNOWN; } else err = ERR_BUILD_DISABLED; @@ -1417,7 +1417,7 @@ bool CScriptFunctions::rBuild(CBotVar* var, CBotVar* result, int& exception, voi oType != OBJECT_HUMAN && oType != OBJECT_TECH ) { - err = ERR_MANIP_VEH; // Wrong object + err = ERR_WRONG_BOT; // Wrong object } else { @@ -2475,10 +2475,10 @@ bool CScriptFunctions::rShield(CBotVar* var, CBotVar* result, int& exception, vo // only shielder can use shield() 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) { - exception = ERR_MANIP_VEH; + exception = ERR_WRONG_BOT; return false; } return true;