Create CExchangePost subclass

master
Piotr Dziwinski 2015-06-27 23:22:55 +02:00
parent 1ccb807091
commit f871ba4729
20 changed files with 1032 additions and 959 deletions

View File

@ -87,6 +87,7 @@ set(BASE_SOURCES
common/misc.cpp
common/pathman.cpp
common/profile.cpp
common/regex_utils.cpp
common/resources/inputstream.cpp
common/resources/inputstreambuffer.cpp
common/resources/outputstream.cpp
@ -127,7 +128,6 @@ set(BASE_SOURCES
object/auto/autofactory.cpp
object/auto/autoflag.cpp
object/auto/autohuston.cpp
object/auto/autoinfo.cpp
object/auto/autojostle.cpp
object/auto/autokid.cpp
object/auto/autolabo.cpp
@ -187,6 +187,7 @@ set(BASE_SOURCES
object/task/taskturn.cpp
object/task/taskwait.cpp
object/tool_type.cpp
object/subclass/exchange_post.cpp
physics/physics.cpp
script/cbottoken.cpp
script/cmdtoken.cpp

View File

@ -0,0 +1,46 @@
/*
* 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 "common/regex_utils.h"
std::string FormatAssertRegexMatchError(const std::string& text,
const std::string& pattern)
{
return "Text \"" + text + "\" did not match regex \"" + pattern + "\"";
}
RegexUtils::AssertRegexMatchError::AssertRegexMatchError(
const std::string& text, const std::string& pattern) NOEXCEPT
: std::runtime_error(FormatAssertRegexMatchError(text, pattern))
{
}
boost::smatch RegexUtils::AssertRegexMatch(const std::string& text, const std::string& pattern)
{
boost::regex regex(pattern);
boost::smatch matches;
bool ok = boost::regex_match(text, matches, regex);
if (!ok)
throw AssertRegexMatchError(text, pattern);
return matches;
}
/*
boost::cmatch matches;*/

38
src/common/regex_utils.h Normal file
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
*/
#pragma once
#include <stdexcept>
#include <boost/regex.hpp>
namespace RegexUtils {
class AssertRegexMatchError : public std::runtime_error
{
public:
explicit AssertRegexMatchError(const std::string& text,
const std::string& pattern) NOEXCEPT;
};
//! Match string with regex and return list of matches; throw exception on mismatch
boost::smatch AssertRegexMatch(const std::string& text, const std::string& pattern);
} // namespace RegexUtils

View File

@ -1,511 +0,0 @@
/*
* This file is part of the Colobot: Gold Edition source code
* Copyright (C) 2001-2014, Daniel Roux, EPSITEC SA & TerranovaTeam
* http://epsiteс.ch; http://colobot.info; http://github.com/colobot
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see http://gnu.org/licenses
*/
#include "object/auto/autoinfo.h"
#include "object/level/parserline.h"
#include "object/level/parserparam.h"
#include "script/cmdtoken.h"
#include "ui/interface.h"
#include "ui/list.h"
#include "ui/window.h"
#include <stdio.h>
#include <string.h>
// Object's constructor.
CAutoInfo::CAutoInfo(CObject* object) : CAuto(object)
{
Init();
}
// Object's destructor.
CAutoInfo::~CAutoInfo()
{
}
// Destroys the object.
void CAutoInfo::DeleteObject(bool bAll)
{
CAuto::DeleteObject(bAll);
}
// Initialize the object.
void CAutoInfo::Init()
{
m_phase = AIP_WAIT;
m_time = 0.0f;
m_timeVirus = 0.0f;
m_bLastVirus = false;
CAuto::Init();
}
// Start a emission.
void CAutoInfo::Start(int param)
{
Math::Vector pos, speed;
Math::Point dim;
if ( param == 0 ) // instruction "receive" ?
{
m_phase = AIP_EMETTE;
m_progress = 0.0f;
m_speed = 1.0f/2.0f;
}
else if ( param == 2 ) // instruction "send" ?
{
m_phase = AIP_RECEIVE;
m_progress = 0.0f;
m_speed = 1.0f/2.0f;
}
else
{
m_phase = AIP_ERROR;
m_progress = 0.0f;
m_speed = 1.0f/2.0f;
}
m_lastParticle = 0;
m_goal = m_object->GetPosition(0);
if ( m_phase == AIP_EMETTE )
{
pos = m_goal;
pos.y += 9.5f;
speed = Math::Vector(0.0f, 0.0f, 0.0f);
dim.x = 30.0f;
dim.y = dim.x;
m_particle->CreateParticle(pos, speed, dim, Gfx::PARTISPHERE4, 1.5f, 0.0f, 0.0f);
m_sound->Play(SOUND_LABO, pos, 1.0f, 2.0f);
}
if ( m_phase == AIP_RECEIVE )
{
pos = m_goal;
pos.y += 9.5f;
speed = Math::Vector(0.0f, 0.0f, 0.0f);
dim.x = 50.0f;
dim.y = dim.x;
m_particle->CreateParticle(pos, speed, dim, Gfx::PARTISPHERE6, 1.5f, 0.0f, 0.0f);
m_sound->Play(SOUND_LABO, pos, 1.0f, 2.0f);
}
if ( m_phase == AIP_ERROR )
{
m_sound->Play(SOUND_GGG, pos, 1.0f, 0.5f);
}
}
// Management of an event.
bool CAutoInfo::EventProcess(const Event &event)
{
Math::Vector pos, speed;
Math::Point dim;
float duration, angle, rTime;
int i;
CAuto::EventProcess(event);
if ( m_engine->GetPause() ) return true;
if ( event.type != EVENT_FRAME ) return true;
m_timeVirus -= event.rTime;
if ( m_object->GetVirusMode() ) // contaminated by a virus?
{
if ( m_timeVirus <= 0.0f )
{
m_timeVirus = 0.1f+Math::Rand()*0.3f;
angle = m_object->GetAngleY(1);
angle += Math::Rand()*0.3f;
m_object->SetAngleY(1, angle);
m_object->SetAngleX(2, (Math::Rand()-0.5f)*0.3f);
m_object->SetAngleX(4, (Math::Rand()-0.5f)*0.3f);
m_object->SetAngleX(6, (Math::Rand()-0.5f)*0.3f);
m_object->SetAngleZ(2, (Math::Rand()-0.5f)*0.3f);
m_object->SetAngleZ(4, (Math::Rand()-0.5f)*0.3f);
m_object->SetAngleZ(6, (Math::Rand()-0.5f)*0.3f);
UpdateListVirus();
}
m_bLastVirus = true;
return true;
}
else
{
if ( m_bLastVirus )
{
m_bLastVirus = false;
UpdateList(); // normally returns the list
}
else
{
if ( m_object->GetInfoUpdate() )
{
UpdateList(); // updates the list
}
}
}
UpdateInterface(event.rTime);
rTime = event.rTime;
if ( m_phase == AIP_EMETTE ) // instruction "receive" ?
{
if ( m_progress < 0.5f &&
m_lastParticle+m_engine->ParticleAdapt(0.05f) <= m_time )
{
m_lastParticle = m_time;
for ( i=0 ; i<4 ; i++ )
{
pos = m_goal;
pos.y += 9.5f;
speed.x = (Math::Rand()-0.5f)*50.0f;
speed.z = (Math::Rand()-0.5f)*50.0f;
speed.y = (Math::Rand()-0.5f)*50.0f;
speed *= 0.5f+m_progress*0.5f;
dim.x = 0.6f;
dim.y = dim.x;
duration = Math::Rand()*0.5f+0.5f;
m_particle->CreateTrack(pos, speed, dim, Gfx::PARTITRACK6,
duration, 0.0f,
duration*0.9f, 0.7f);
}
}
if ( m_progress < 1.0f )
{
m_progress += rTime*m_speed;
m_object->SetAngleZ(2, m_progress*2.0f*Math::PI);
m_object->SetAngleZ(4, m_progress*2.0f*Math::PI);
m_object->SetAngleZ(6, m_progress*2.0f*Math::PI);
}
else
{
m_phase = AIP_WAIT;
m_object->SetAngleX(2, 0.0f);
m_object->SetAngleX(4, 0.0f);
m_object->SetAngleX(6, 0.0f);
m_object->SetAngleZ(2, 0.0f);
m_object->SetAngleZ(4, 0.0f);
m_object->SetAngleZ(6, 0.0f);
}
}
if ( m_phase == AIP_RECEIVE ) // instruction "send" ?
{
if ( m_progress < 0.5f &&
m_lastParticle+m_engine->ParticleAdapt(0.05f) <= m_time )
{
m_lastParticle = m_time;
for ( i=0 ; i<4 ; i++ )
{
pos = m_goal;
pos.y += 9.5f;
speed = pos;
pos.x += (Math::Rand()-0.5f)*40.0f;
pos.y += (Math::Rand()-0.5f)*40.0f;
pos.z += (Math::Rand()-0.5f)*40.0f;
speed = (speed-pos)*1.0f;
//? speed *= 0.5f+m_progress*0.5f;
dim.x = 0.6f;
dim.y = dim.x;
duration = Math::Rand()*0.5f+0.5f;
m_particle->CreateTrack(pos, speed, dim, Gfx::PARTITRACK6,
duration, 0.0f,
duration*0.9f, 0.7f);
}
}
if ( m_progress < 1.0f )
{
m_progress += rTime*m_speed;
m_object->SetAngleZ(2, m_progress*2.0f*Math::PI);
m_object->SetAngleZ(4, m_progress*2.0f*Math::PI);
m_object->SetAngleZ(6, m_progress*2.0f*Math::PI);
}
else
{
m_phase = AIP_WAIT;
m_object->SetAngleX(2, 0.0f);
m_object->SetAngleX(4, 0.0f);
m_object->SetAngleX(6, 0.0f);
m_object->SetAngleZ(2, 0.0f);
m_object->SetAngleZ(4, 0.0f);
m_object->SetAngleZ(6, 0.0f);
}
}
if ( m_phase == AIP_ERROR )
{
if ( m_progress < 0.5f &&
m_lastParticle+m_engine->ParticleAdapt(0.05f) <= m_time )
{
m_lastParticle = m_time;
pos = m_goal;
speed.x = (Math::Rand()-0.5f)*5.0f;
speed.z = (Math::Rand()-0.5f)*5.0f;
speed.y = 5.0f+Math::Rand()*5.0f;
dim.x = 5.0f+Math::Rand()*5.0f;
dim.y = dim.x;
duration = Math::Rand()*0.5f+0.5f;
m_particle->CreateParticle(pos, speed, dim, Gfx::PARTISMOKE1, 4.0f);
}
if ( m_progress < 1.0f )
{
m_progress += rTime*m_speed;
rTime = 0.0f; // stops the rotation
if ( m_progress < 0.5f )
{
angle = m_progress/0.5f;
}
else
{
angle = 1.0f-(m_progress-0.5f)/0.5f;
}
m_object->SetAngleX(2, angle*0.5f);
m_object->SetAngleX(4, angle*0.5f);
m_object->SetAngleX(6, angle*0.5f);
m_object->SetAngleZ(2, (Math::Rand()-0.5f)*0.2f);
m_object->SetAngleZ(4, (Math::Rand()-0.5f)*0.2f);
m_object->SetAngleZ(6, (Math::Rand()-0.5f)*0.2f);
}
else
{
m_phase = AIP_WAIT;
m_object->SetAngleX(2, 0.0f);
m_object->SetAngleX(4, 0.0f);
m_object->SetAngleX(6, 0.0f);
m_object->SetAngleZ(2, 0.0f);
m_object->SetAngleZ(4, 0.0f);
m_object->SetAngleZ(6, 0.0f);
}
}
angle = m_object->GetAngleY(1);
angle += rTime*0.5f;
m_object->SetAngleY(1, angle);
m_object->SetAngleX(3, sinf(m_time*6.0f+Math::PI*0.0f/3.0f)*0.3f);
m_object->SetAngleX(5, sinf(m_time*6.0f+Math::PI*2.0f/3.0f)*0.3f);
m_object->SetAngleX(7, sinf(m_time*6.0f+Math::PI*4.0f/3.0f)*0.3f);
return true;
}
// Returns an error due the state of the automation.
Error CAutoInfo::GetError()
{
if ( m_object->GetVirusMode() )
{
return ERR_BAT_VIRUS;
}
return ERR_OK;
}
// Creates all the interface when the object is selected.
bool CAutoInfo::CreateInterface(bool bSelect)
{
Ui::CWindow* pw;
Ui::CList* pl;
Math::Point pos, ddim;
float ox, oy, sx, sy;
CAuto::CreateInterface(bSelect);
if ( !bSelect ) return true;
pw = static_cast< Ui::CWindow* >(m_interface->SearchControl(EVENT_WINDOW0));
if ( pw == 0 ) return false;
ox = 3.0f/640.0f;
oy = 3.0f/480.0f;
sx = 33.0f/640.0f;
sy = 33.0f/480.0f;
pos.x = ox+sx*7.0f;
pos.y = oy+sy*0.0f;
ddim.x = 160.0f/640.0f;
ddim.y = 66.0f/480.0f;
pl = pw->CreateList(pos, ddim, 1, EVENT_OBJECT_GINFO, 1.10f);
pl->SetSelectCap(false);
pos.x = ox+sx*0.0f;
pos.y = oy+sy*0;
ddim.x = 66.0f/640.0f;
ddim.y = 66.0f/480.0f;
pw->CreateGroup(pos, ddim, 112, EVENT_OBJECT_TYPE);
UpdateList();
return true;
}
// Updates the state of all buttons on the interface,
// following the time that elapses ...
void CAutoInfo::UpdateInterface(float rTime)
{
CAuto::UpdateInterface(rTime);
}
// Updates the contents of the list.
void CAutoInfo::UpdateList()
{
Ui::CWindow* pw;
Ui::CList* pl;
Info info;
int total, i;
char text[100];
pw = static_cast< Ui::CWindow* >(m_interface->SearchControl(EVENT_WINDOW0));
if ( pw == nullptr ) return;
pl = static_cast< Ui::CList* >(pw->SearchControl(EVENT_OBJECT_GINFO));
if ( pl == nullptr ) return;
pl->Flush();
total = m_object->GetInfoTotal();
if ( total == 0 )
{
pl->ClearState(Ui::STATE_ENABLE);
}
else
{
pl->SetState(Ui::STATE_ENABLE);
for ( i=0 ; i<total ; i++ )
{
info = m_object->GetInfo(i);
sprintf(text, "%s = %.2f", info.name, info.value);
pl->SetItemName(i, text);
}
}
m_object->SetInfoUpdate(false);
}
// Updates the content of contaminating the list.
void CAutoInfo::UpdateListVirus()
{
Ui::CWindow* pw;
Ui::CList* pl;
int i, j, max;
char text[100];
pw = static_cast< Ui::CWindow* >(m_interface->SearchControl(EVENT_WINDOW0));
if ( pw == 0 ) return;
pl = static_cast< Ui::CList* >(pw->SearchControl(EVENT_OBJECT_GINFO));
if ( pl == 0 ) return;
pl->SetState(Ui::STATE_ENABLE);
pl->Flush();
for ( i=0 ; i<4 ; i++ )
{
max = static_cast< int >(2.0f+Math::Rand()*10.0f);
for ( j=0 ; j<max ; j++ )
{
do
{
text[j] = ' '+static_cast< int >(Math::Rand()*94.0f);
}
while ( text[j] == '\\' );
}
text[j] = 0;
pl->SetItemName(i, text);
}
}
// Saves all parameters of the controller.
bool CAutoInfo::Write(CLevelParserLine* line)
{
if ( m_phase == AIP_WAIT ) return false;
line->AddParam("aExist", CLevelParserParamUPtr{new CLevelParserParam(true)});
CAuto::Write(line);
line->AddParam("aPhase", CLevelParserParamUPtr{new CLevelParserParam(static_cast<int>(m_phase))});
line->AddParam("aProgress", CLevelParserParamUPtr{new CLevelParserParam(m_progress)});
line->AddParam("aSpeed", CLevelParserParamUPtr{new CLevelParserParam(m_speed)});
return true;
}
// Restores all parameters of the controller.
bool CAutoInfo::Read(CLevelParserLine* line)
{
if ( !line->GetParam("aExist")->AsBool(false) ) return false;
CAuto::Read(line);
m_phase = static_cast< AutoInfoPhase >(line->GetParam("aPhase")->AsInt(AIP_WAIT));
m_progress = line->GetParam("aProgress")->AsFloat(0.0f);
m_speed = line->GetParam("aSpeed")->AsFloat(1.0f);
m_lastParticle = 0.0f;
return true;
}

View File

@ -1,71 +0,0 @@
/*
* This file is part of the Colobot: Gold Edition source code
* Copyright (C) 2001-2014, Daniel Roux, EPSITEC SA & TerranovaTeam
* http://epsiteс.ch; http://colobot.info; http://github.com/colobot
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see http://gnu.org/licenses
*/
// autoinfo.h
#pragma once
#include "object/auto/auto.h"
enum AutoInfoPhase
{
AIP_WAIT = 1,
AIP_EMETTE = 2,
AIP_RECEIVE = 3,
AIP_ERROR = 4,
};
class CAutoInfo : public CAuto
{
public:
CAutoInfo(CObject* object);
~CAutoInfo();
void DeleteObject(bool bAll=false);
void Init();
void Start(int param);
bool EventProcess(const Event &event);
Error GetError();
bool CreateInterface(bool bSelect);
bool Write(CLevelParserLine* line);
bool Read(CLevelParserLine* line);
protected:
void UpdateInterface(float rTime);
void UpdateList();
void UpdateListVirus();
protected:
AutoInfoPhase m_phase;
float m_progress;
float m_speed;
float m_timeVirus;
float m_lastParticle;
Math::Vector m_goal;
bool m_bLastVirus;
};

View File

@ -23,17 +23,8 @@
#include <boost/lexical_cast.hpp>
CLevelParserException::CLevelParserException(std::string message) NOEXCEPT
: m_message(message)
{
}
const char* CLevelParserException::what() const NOEXCEPT
{
return m_message.c_str();
}
std::string formatMissingParamError(CLevelParserParam* thisParam) NOEXCEPT
std::string FormatMissingParamError(CLevelParserParam* thisParam) NOEXCEPT
{
auto paramName = thisParam->GetName();
auto lineNumber = boost::lexical_cast<std::string>(thisParam->GetLine()->GetLineNumber());
@ -42,11 +33,11 @@ std::string formatMissingParamError(CLevelParserParam* thisParam) NOEXCEPT
}
CLevelParserExceptionMissingParam::CLevelParserExceptionMissingParam(CLevelParserParam* thisParam) NOEXCEPT
: CLevelParserException(formatMissingParamError(thisParam))
: CLevelParserException(FormatMissingParamError(thisParam))
{
}
std::string formatBadParamError(CLevelParserParam* thisParam, std::string requestedType) NOEXCEPT
std::string FormatBadParamError(CLevelParserParam* thisParam, std::string requestedType) NOEXCEPT
{
auto paramName = thisParam->GetName();
auto paramValue = thisParam->GetValue();
@ -56,6 +47,6 @@ std::string formatBadParamError(CLevelParserParam* thisParam, std::string reques
}
CLevelParserExceptionBadParam::CLevelParserExceptionBadParam(CLevelParserParam* thisParam, std::string requestedType) NOEXCEPT
: CLevelParserException(formatBadParamError(thisParam, requestedType))
: CLevelParserException(FormatBadParamError(thisParam, requestedType))
{
}

View File

@ -24,20 +24,16 @@
#pragma once
#include <exception>
#include <stdexcept>
#include <string>
class CLevelParserParam;
class CLevelParserException : public std::exception
class CLevelParserException : public std::runtime_error
{
public:
CLevelParserException(std::string message) NOEXCEPT;
virtual ~CLevelParserException() NOEXCEPT {}
const char* what() const NOEXCEPT;
protected:
std::string m_message;
CLevelParserException(const std::string& message) NOEXCEPT
: std::runtime_error(message) {}
};
class CLevelParserExceptionMissingParam : public CLevelParserException

View File

@ -251,6 +251,7 @@ CObject::CObject(int id)
m_magnifyDamage = 1.0f;
m_proxyDistance = 60.0f;
m_param = 0.0f;
m_infoReturn = NAN;
m_team = 0;
memset(&m_character, 0, sizeof(m_character));
@ -269,10 +270,6 @@ CObject::CObject(int id)
m_cameraDist = 50.0f;
m_bCameraLock = false;
m_infoTotal = 0;
m_infoReturn = NAN;
m_bInfoUpdate = false;
for (int i=0 ; i<OBJECTMAXPART ; i++ )
{
m_objectPart[i].bUsed = false;
@ -906,10 +903,9 @@ int CObject::GetID()
// Saves all the parameters of the object.
bool CObject::Write(CLevelParserLine* line)
void CObject::Write(CLevelParserLine* line)
{
Math::Vector pos;
Info info;
float value;
int i;
@ -980,15 +976,6 @@ bool CObject::Write(CLevelParserLine* line)
if ( m_virusTime != 0.0f )
line->AddParam("virusTime", CLevelParserParamUPtr{new CLevelParserParam(m_virusTime)});
// Puts information in terminal (OBJECT_INFO).
for ( i=0 ; i<m_infoTotal ; i++ )
{
info = GetInfo(i);
if ( info.name[0] == 0 ) break;
line->AddParam("info"+boost::lexical_cast<std::string>(i+1), CLevelParserParamUPtr{new CLevelParserParam(std::string(info.name)+"="+boost::lexical_cast<std::string>(info.value))});
}
// Sets the parameters of the command line.
CLevelParserParamVec cmdline;
for ( i=0 ; i<OBJECTMAXCMDLINE ; i++ )
@ -1020,19 +1007,15 @@ bool CObject::Write(CLevelParserLine* line)
{
m_auto->Write(line);
}
return true;
}
// Returns all parameters of the object.
bool CObject::Read(CLevelParserLine* line)
void CObject::Read(CLevelParserLine* line)
{
Math::Vector pos, dir;
Gfx::CameraType cType;
int i;
cType = line->GetParam("camera")->AsCameraType(Gfx::CAM_TYPE_NULL);
Gfx::CameraType cType = line->GetParam("camera")->AsCameraType(Gfx::CAM_TYPE_NULL);
if ( cType != Gfx::CAM_TYPE_NULL )
{
SetCameraType(cType);
@ -1064,34 +1047,10 @@ bool CObject::Read(CLevelParserLine* line)
m_bVirusMode = line->GetParam("virusMode")->AsBool(false);
m_virusTime = line->GetParam("virusTime")->AsFloat(0.0f);
// Puts information in terminal (OBJECT_INFO).
for ( i=0 ; i<OBJECTMAXINFO ; i++ )
{
std::string op = std::string("info")+boost::lexical_cast<std::string>(i+1);
if (!line->GetParam(op)->IsDefined()) break;
std::string text = line->GetParam(op)->AsString();
std::size_t p = text.find_first_of("=");
if (p == std::string::npos)
throw CLevelParserExceptionBadParam(line->GetParam(op), "info");
Info info;
strcpy(info.name, text.substr(0, p).c_str());
try
{
info.value = boost::lexical_cast<float>(text.substr(p+1).c_str());
}
catch (...)
{
throw CLevelParserExceptionBadParam(line->GetParam(op), "info.value (float)");
}
SetInfo(i, info);
}
// Sets the parameters of the command line.
i = 0;
if (line->GetParam("cmdline")->IsDefined())
{
int i = 0;
for (auto& p : line->GetParam("cmdline")->AsArray())
{
if (i >= OBJECTMAXCMDLINE) break;
@ -1119,8 +1078,6 @@ bool CObject::Read(CLevelParserLine* line)
{
m_auto->Read(line);
}
return true;
}
@ -1809,42 +1766,6 @@ void CObject::SetTruckPart(int part)
m_truckLink = part;
}
// Management of user information.
void CObject::DeleteInfo(int rank)
{
int i;
if ( rank < 0 || rank >= m_infoTotal ) return;
for ( i=rank ; i<m_infoTotal-1 ; i++ )
{
m_info[i] = m_info[i+1];
}
m_infoTotal --;
m_bInfoUpdate = true;
}
void CObject::SetInfo(int rank, Info info)
{
if ( rank < 0 || rank >= OBJECTMAXINFO ) return;
m_info[rank] = info;
if ( rank+1 > m_infoTotal ) m_infoTotal = rank+1;
m_bInfoUpdate = true;
}
Info CObject::GetInfo(int rank)
{
if ( rank < 0 || rank >= OBJECTMAXINFO ) rank = 0;
return m_info[rank];
}
int CObject::GetInfoTotal()
{
return m_infoTotal;
}
void CObject::SetInfoReturn(float value)
{
m_infoReturn = value;
@ -1855,17 +1776,6 @@ float CObject::GetInfoReturn()
return m_infoReturn;
}
void CObject::SetInfoUpdate(bool bUpdate)
{
m_bInfoUpdate = bUpdate;
}
bool CObject::GetInfoUpdate()
{
return m_bInfoUpdate;
}
bool CObject::SetCmdLine(int rank, float value)
{
if ( rank < 0 || rank >= OBJECTMAXCMDLINE ) return false;

View File

@ -50,7 +50,6 @@ struct Program;
const int OBJECTMAXPART = 40;
const int MAXCRASHSPHERE = 40;
const int OBJECTMAXDESELLIST = 10;
const int OBJECTMAXINFO = 10;
const int OBJECTMAXCMDLINE = 20;
struct ObjectPart
@ -81,12 +80,6 @@ struct Character
Math::Vector posPower; // position of the battery
};
struct Info
{
char name[20]; // name of the information
float value; // value of the information
};
enum class ExplosionType
{
Bang = 1,
@ -127,7 +120,7 @@ public:
CObject(const CObject&) = delete;
CObject& operator=(const CObject&) = delete;
~CObject();
virtual ~CObject();
void Simplify();
bool ExplodeObject(ExplosionType type, float force, float decay=1.0f);
@ -147,8 +140,8 @@ public:
int GetID();
bool Write(CLevelParserLine* line);
bool Read(CLevelParserLine* line);
virtual void Write(CLevelParserLine* line);
virtual void Read(CLevelParserLine* line);
void SetDrawWorld(bool bDraw);
void SetDrawFront(bool bDraw);
@ -235,15 +228,6 @@ public:
CObject* GetTruck();
void SetTruckPart(int part);
void DeleteInfo(int rank);
void SetInfo(int rank, Info info);
Info GetInfo(int rank);
int GetInfoTotal();
void SetInfoReturn(float value);
float GetInfoReturn();
void SetInfoUpdate(bool bUpdate);
bool GetInfoUpdate();
bool SetCmdLine(int rank, float value);
float GetCmdLine(int rank);
@ -375,6 +359,12 @@ public:
void FlatParent();
// TODO: move to more appropriate place
//! Set value to be returned by receive() CBOT function
void SetInfoReturn(float value);
//! Return value to be returned by receive() CBOT function
float GetInfoReturn();
bool GetTraceDown();
void SetTraceDown(bool bDown);
int GetTraceColor();
@ -498,10 +488,7 @@ protected:
Math::Vector m_resetAngle;
Program* m_resetRun;
int m_infoTotal;
Info m_info[OBJECTMAXINFO];
float m_infoReturn;
bool m_bInfoUpdate;
float m_infoReturn;
float m_cmdLine[OBJECTMAXCMDLINE];
};

View File

@ -0,0 +1,38 @@
/*
* This file is part of the Colobot: Gold Edition source code
* Copyright (C) 2001-2014, Daniel Roux, EPSITEC SA & TerranovaTeam
* http://epsiteс.ch; http://colobot.info; http://github.com/colobot
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see http://gnu.org/licenses
*/
#pragma once
#include "math/vector.h"
#include "object/object_type.h"
struct ObjectCreateParams
{
Math::Vector pos;
float angle;
ObjectType type;
float power;
float zoom;
float height;
bool trainer;
bool toy;
int option;
int id;
};

View File

@ -25,6 +25,7 @@
#include "graphics/engine/lightning.h"
#include "object/brain.h"
#include "object/object_create_params.h"
#include "object/robotmain.h"
#include "object/auto/autobase.h"
#include "object/auto/autoconvert.h"
@ -35,7 +36,6 @@
#include "object/auto/autofactory.h"
#include "object/auto/autoflag.h"
#include "object/auto/autohuston.h"
#include "object/auto/autoinfo.h"
#include "object/auto/autojostle.h"
#include "object/auto/autokid.h"
#include "object/auto/autolabo.h"
@ -60,6 +60,7 @@
#include "object/motion/motiontoto.h"
#include "object/motion/motionvehicle.h"
#include "object/motion/motionworm.h"
#include "object/subclass/exchange_post.h"
#include "math/geometry.h"
@ -84,6 +85,9 @@ CObjectUPtr CObjectFactory::CreateObject(const ObjectCreateParams& params)
case OBJECT_NULL:
return nullptr;
case OBJECT_INFO:
return CExchangePost::Create(params, m_modelManager, m_engine);
case OBJECT_PORTICO:
case OBJECT_BASE:
case OBJECT_DERRICK:
@ -96,7 +100,6 @@ CObjectUPtr CObjectFactory::CreateObject(const ObjectCreateParams& params)
case OBJECT_NEST:
case OBJECT_RESEARCH:
case OBJECT_RADAR:
case OBJECT_INFO:
case OBJECT_ENERGY:
case OBJECT_LABO:
case OBJECT_NUCLEAR:
@ -604,46 +607,6 @@ CObjectUPtr CObjectFactory::CreateBuilding(const ObjectCreateParams& params)
obj->CreateShadowCircle(8.0f, 1.0f);
}
if ( type == OBJECT_INFO )
{
m_modelManager->AddModelReference("info1.mod", false, rank);
obj->SetPosition(0, pos);
obj->SetAngleY(0, angle);
obj->SetFloorHeight(0.0f);
rank = m_engine->CreateObject();
m_engine->SetObjectType(rank, Gfx::ENG_OBJTYPE_DESCENDANT);
obj->SetObjectRank(1, rank);
obj->SetObjectParent(1, 0);
m_modelManager->AddModelReference("info2.mod", false, rank);
obj->SetPosition(1, Math::Vector(0.0f, 5.0f, 0.0f));
for (int i=0 ; i<3 ; i++ )
{
rank = m_engine->CreateObject();
m_engine->SetObjectType(rank, Gfx::ENG_OBJTYPE_DESCENDANT);
obj->SetObjectRank(2+i*2, rank);
obj->SetObjectParent(2+i*2, 1);
m_modelManager->AddModelReference("info3.mod", false, rank);
obj->SetPosition(2+i*2, Math::Vector(0.0f, 4.5f, 0.0f));
rank = m_engine->CreateObject();
m_engine->SetObjectType(rank, Gfx::ENG_OBJTYPE_DESCENDANT);
obj->SetObjectRank(3+i*2, rank);
obj->SetObjectParent(3+i*2, 2+i*2);
m_modelManager->AddModelReference("radar4.mod", false, rank);
obj->SetPosition(3+i*2, Math::Vector(0.0f, 0.0f, -4.0f));
obj->SetAngleY(2+i*2, 2.0f*Math::PI/3.0f*i);
}
obj->CreateCrashSphere(Math::Vector(0.0f, 3.0f, 0.0f), 6.0f, SOUND_BOUMm, 0.45f);
obj->CreateCrashSphere(Math::Vector(0.0f, 11.0f, 0.0f), 6.0f, SOUND_BOUMm, 0.45f);
obj->SetGlobalSphere(Math::Vector(0.0f, 5.0f, 0.0f), 6.0f);
obj->CreateShadowCircle(8.0f, 1.0f);
}
if ( type == OBJECT_ENERGY )
{
m_modelManager->AddModelCopy("energy.mod", false, rank);
@ -3672,10 +3635,6 @@ void CObjectFactory::AddObjectAuto(CObject* obj)
{
objAuto.reset(new CAutoRadar(obj));
}
if ( type == OBJECT_INFO )
{
objAuto.reset(new CAutoInfo(obj));
}
if ( type == OBJECT_ENERGY )
{
objAuto.reset(new CAutoEnergy(obj));

View File

@ -39,23 +39,10 @@ class CTerrain;
class CObject;
class CRobotMain;
struct ObjectCreateParams;
using CObjectUPtr = std::unique_ptr<CObject>;
struct ObjectCreateParams
{
Math::Vector pos;
float angle;
ObjectType type;
float power;
float zoom;
float height;
bool trainer;
bool toy;
int option;
int id;
};
class CObjectFactory
{
public:

View File

@ -23,6 +23,7 @@
#include "math/all.h"
#include "object/object.h"
#include "object/object_create_params.h"
#include "object/object_factory.h"
#include "object/auto/auto.h"

View File

@ -68,6 +68,7 @@
#include "object/task/taskbuild.h"
#include "object/task/taskmanip.h"
#include "object/level/parser.h"
#include "object/subclass/exchange_post.h"
#include "physics/physics.h"
@ -3545,26 +3546,10 @@ void CRobotMain::CreateScene(bool soluce, bool fixScene, bool resetObject)
m_engine->GetPyroManager()->Create(pType, obj);
}
// Puts information in terminal (OBJECT_INFO).
for (int i = 0; i < OBJECTMAXINFO; i++)
if (type == OBJECT_INFO)
{
std::string op = "info" + boost::lexical_cast<std::string>(i+1);
if (!line->GetParam(op)->IsDefined()) break;
std::string text = line->GetParam(op)->AsString();
std::size_t p = text.find_first_of("=");
if (p == std::string::npos)
throw CLevelParserExceptionBadParam(line->GetParam(op), "info");
Info info;
strcpy(info.name, text.substr(0, p).c_str());
try
{
info.value = boost::lexical_cast<float>(text.substr(p+1).c_str());
}
catch (...)
{
throw CLevelParserExceptionBadParam(line->GetParam(op), "info.value (float)");
}
obj->SetInfo(i, info);
CExchangePost* exchangePost = static_cast<CExchangePost*>(obj);
exchangePost->ReadInfo(line.get());
}
// Sets the parameters of the command line.

View File

@ -0,0 +1,681 @@
/*
* 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/subclass/exchange_post.h"
#include "common/regex_utils.h"
#include "graphics/engine/modelmanager.h"
#include "object/object_create_params.h"
#include "object/level/parserline.h"
#include "object/level/parserparam.h"
#include "object/level/parserexceptions.h"
#include "script/cmdtoken.h"
#include "ui/interface.h"
#include "ui/list.h"
#include "ui/window.h"
#include <boost/lexical_cast.hpp>
CExchangePost::CExchangePost(int id)
: CObject(id)
, m_infoUpdate(false)
{
m_type = OBJECT_INFO;
}
std::unique_ptr<CExchangePost> CExchangePost::Create(
const ObjectCreateParams& params,
Gfx::CModelManager* modelManager,
Gfx::CEngine* engine)
{
std::unique_ptr<CExchangePost> obj{new CExchangePost(params.id)};
int rank = engine->CreateObject();
engine->SetObjectType(rank, Gfx::ENG_OBJTYPE_FIX); // it is a stationary object
obj->SetObjectRank(0, rank);
modelManager->AddModelReference("info1.mod", false, rank);
obj->SetPosition(0, params.pos);
obj->SetAngleY(0, params.angle);
obj->SetFloorHeight(0.0f);
rank = engine->CreateObject();
engine->SetObjectType(rank, Gfx::ENG_OBJTYPE_DESCENDANT);
obj->SetObjectRank(1, rank);
obj->SetObjectParent(1, 0);
modelManager->AddModelReference("info2.mod", false, rank);
obj->SetPosition(1, Math::Vector(0.0f, 5.0f, 0.0f));
for (int i = 0; i < 3; ++i)
{
rank = engine->CreateObject();
engine->SetObjectType(rank, Gfx::ENG_OBJTYPE_DESCENDANT);
obj->SetObjectRank(2+i*2, rank);
obj->SetObjectParent(2+i*2, 1);
modelManager->AddModelReference("info3.mod", false, rank);
obj->SetPosition(2+i*2, Math::Vector(0.0f, 4.5f, 0.0f));
rank = engine->CreateObject();
engine->SetObjectType(rank, Gfx::ENG_OBJTYPE_DESCENDANT);
obj->SetObjectRank(3+i*2, rank);
obj->SetObjectParent(3+i*2, 2+i*2);
modelManager->AddModelReference("radar4.mod", false, rank);
obj->SetPosition(3+i*2, Math::Vector(0.0f, 0.0f, -4.0f));
obj->SetAngleY(2+i*2, 2.0f*Math::PI/3.0f*i);
}
obj->CreateCrashSphere(Math::Vector(0.0f, 3.0f, 0.0f), 6.0f, SOUND_BOUMm, 0.45f);
obj->CreateCrashSphere(Math::Vector(0.0f, 11.0f, 0.0f), 6.0f, SOUND_BOUMm, 0.45f);
obj->SetGlobalSphere(Math::Vector(0.0f, 5.0f, 0.0f), 6.0f);
obj->CreateShadowCircle(8.0f, 1.0f);
Math::Vector pos = obj->GetPosition(0);
pos.y += params.height;
obj->SetPosition(0, pos); // to display the shadows immediately
std::unique_ptr<CAutoInfo> objAuto{new CAutoInfo(obj.get())};
objAuto->Init();
obj->SetAuto(std::move(objAuto));
engine->LoadAllTextures();
return obj;
}
int CExchangePost::GetMaximumInfoListSize()
{
return 10;
}
bool CExchangePost::SetInfo(const std::string& name, float value)
{
for (auto& info : m_infoList)
{
if (info.name == name)
{
info.value = value;
return true;
}
}
if (static_cast<int>(m_infoList.size()) == GetMaximumInfoListSize())
{
return false;
}
ExchangePostInfo info;
info.name = name;
info.value = value;
m_infoList.push_back(info);
return true;
}
const std::vector<ExchangePostInfo>& CExchangePost::GetInfoList()
{
return m_infoList;
}
boost::optional<float> CExchangePost::GetInfoValue(const std::string& name)
{
for (auto& info : m_infoList)
{
if (info.name == name)
{
return info.value;
}
}
return boost::none;
}
bool CExchangePost::HasInfo(const std::string& name)
{
for (auto& info : m_infoList)
{
if (info.name == name)
{
return true;
}
}
return false;
}
bool CExchangePost::DeleteInfo(const std::string& name)
{
for (auto it = m_infoList.begin(); it != m_infoList.end(); ++it)
{
if (it->name == name)
{
m_infoList.erase(it);
return true;
}
}
return false;
}
bool CExchangePost::GetInfoUpdate()
{
return m_infoUpdate;
}
void CExchangePost::SetInfoUpdate(bool update)
{
m_infoUpdate = update;
}
void CExchangePost::Write(CLevelParserLine* line)
{
CObject::Write(line);
int i = 0;
for (const auto& info : m_infoList)
{
++i;
if (info.name.empty())
{
auto key = "info" + boost::lexical_cast<std::string>(i);
auto paramValue = info.name + "=" + boost::lexical_cast<std::string>(info.value);
line->AddParam(key, CLevelParserParamUPtr{new CLevelParserParam(paramValue)});
}
}
}
void CExchangePost::Read(CLevelParserLine* line)
{
CObject::Read(line);
ReadInfo(line);
}
void CExchangePost::ReadInfo(CLevelParserLine* line)
{
for (int i = 1; i <= GetMaximumInfoListSize(); i++)
{
std::string op = std::string("info") + boost::lexical_cast<std::string>(i);
if (!line->GetParam(op)->IsDefined())
break;
std::string text = line->GetParam(op)->AsString();
ExchangePostInfo info;
try
{
auto matches = RegexUtils::AssertRegexMatch(text, "([^=]+)=(.*)");
info.name = matches[1];
info.value = boost::lexical_cast<float>(matches[2]);
}
catch (...)
{
throw CLevelParserExceptionBadParam(line->GetParam(op), op);
}
m_infoList.push_back(info);
}
}
//////////////////
enum class CAutoInfo::Phase : unsigned int
{
Wait = 1,
Send = 2,
Receive = 3,
Error = 4,
};
// Object's constructor.
CAutoInfo::CAutoInfo(CExchangePost* object)
: CAuto(object)
, m_exchangePost(object)
{
Init();
}
CAutoInfo::~CAutoInfo()
{
}
void CAutoInfo::DeleteObject(bool all)
{
CAuto::DeleteObject(all);
}
void CAutoInfo::Init()
{
m_phase = Phase::Wait;
m_time = 0.0f;
m_timeVirus = 0.0f;
m_lastVirus = false;
CAuto::Init();
}
void CAutoInfo::Start(int param)
{
if (param == 0) // instruction "receive" ?
{
m_phase = Phase::Send;
m_progress = 0.0f;
m_speed = 1.0f/2.0f;
}
else if (param == 2) // instruction "send" ?
{
m_phase = Phase::Receive;
m_progress = 0.0f;
m_speed = 1.0f/2.0f;
}
else
{
m_phase = Phase::Error;
m_progress = 0.0f;
m_speed = 1.0f/2.0f;
}
m_lastParticle = 0;
m_goal = m_object->GetPosition(0);
Math::Vector pos, speed;
Math::Point dim;
if (m_phase == Phase::Send)
{
pos = m_goal;
pos.y += 9.5f;
speed = Math::Vector(0.0f, 0.0f, 0.0f);
dim.x = 30.0f;
dim.y = dim.x;
m_particle->CreateParticle(pos, speed, dim, Gfx::PARTISPHERE4, 1.5f, 0.0f, 0.0f);
m_sound->Play(SOUND_LABO, pos, 1.0f, 2.0f);
}
if (m_phase == Phase::Receive)
{
pos = m_goal;
pos.y += 9.5f;
speed = Math::Vector(0.0f, 0.0f, 0.0f);
dim.x = 50.0f;
dim.y = dim.x;
m_particle->CreateParticle(pos, speed, dim, Gfx::PARTISPHERE6, 1.5f, 0.0f, 0.0f);
m_sound->Play(SOUND_LABO, pos, 1.0f, 2.0f);
}
if (m_phase == Phase::Error)
{
m_sound->Play(SOUND_GGG, pos, 1.0f, 0.5f);
}
}
bool CAutoInfo::EventProcess(const Event &event)
{
CAuto::EventProcess(event);
if (m_engine->GetPause()) return true;
if (event.type != EVENT_FRAME) return true;
m_timeVirus -= event.rTime;
if (m_exchangePost->GetVirusMode()) // contaminated by a virus?
{
if (m_timeVirus <= 0.0f)
{
m_timeVirus = 0.1f+Math::Rand()*0.3f;
float angle = m_exchangePost->GetAngleY(1);
angle += Math::Rand()*0.3f;
m_exchangePost->SetAngleY(1, angle);
m_exchangePost->SetAngleX(2, (Math::Rand()-0.5f)*0.3f);
m_exchangePost->SetAngleX(4, (Math::Rand()-0.5f)*0.3f);
m_exchangePost->SetAngleX(6, (Math::Rand()-0.5f)*0.3f);
m_exchangePost->SetAngleZ(2, (Math::Rand()-0.5f)*0.3f);
m_exchangePost->SetAngleZ(4, (Math::Rand()-0.5f)*0.3f);
m_exchangePost->SetAngleZ(6, (Math::Rand()-0.5f)*0.3f);
UpdateListVirus();
}
m_lastVirus = true;
return true;
}
else
{
if (m_lastVirus)
{
m_lastVirus = false;
UpdateList(); // normally returns the list
}
else
{
if (m_exchangePost->GetInfoUpdate())
{
UpdateList(); // updates the list
}
}
}
UpdateInterface(event.rTime);
float rTime = event.rTime;
if (m_phase == Phase::Send) // instruction "receive" ?
{
if (m_progress < 0.5f &&
m_lastParticle+m_engine->ParticleAdapt(0.05f) <= m_time)
{
m_lastParticle = m_time;
for (int i = 0; i < 4; i++)
{
Math::Vector pos = m_goal;
pos.y += 9.5f;
Math::Vector speed;
speed.x = (Math::Rand()-0.5f)*50.0f;
speed.z = (Math::Rand()-0.5f)*50.0f;
speed.y = (Math::Rand()-0.5f)*50.0f;
speed *= 0.5f+m_progress*0.5f;
Math::Point dim(0.6f, 0.6f);
float duration = Math::Rand()*0.5f+0.5f;
m_particle->CreateTrack(pos, speed, dim, Gfx::PARTITRACK6,
duration, 0.0f,
duration*0.9f, 0.7f);
}
}
if (m_progress < 1.0f)
{
m_progress += rTime*m_speed;
m_exchangePost->SetAngleZ(2, m_progress*2.0f*Math::PI);
m_exchangePost->SetAngleZ(4, m_progress*2.0f*Math::PI);
m_exchangePost->SetAngleZ(6, m_progress*2.0f*Math::PI);
}
else
{
m_phase = Phase::Wait;
m_exchangePost->SetAngleX(2, 0.0f);
m_exchangePost->SetAngleX(4, 0.0f);
m_exchangePost->SetAngleX(6, 0.0f);
m_exchangePost->SetAngleZ(2, 0.0f);
m_exchangePost->SetAngleZ(4, 0.0f);
m_exchangePost->SetAngleZ(6, 0.0f);
}
}
if (m_phase == Phase::Receive) // instruction "send" ?
{
if (m_progress < 0.5f &&
m_lastParticle+m_engine->ParticleAdapt(0.05f) <= m_time)
{
m_lastParticle = m_time;
for (int i = 0; i < 4; i++)
{
Math::Vector pos = m_goal;
pos.y += 9.5f;
Math::Vector speed = pos;
pos.x += (Math::Rand()-0.5f)*40.0f;
pos.y += (Math::Rand()-0.5f)*40.0f;
pos.z += (Math::Rand()-0.5f)*40.0f;
speed = (speed-pos)*1.0f;
//? speed *= 0.5f+m_progress*0.5f;
Math::Point dim(0.6f, 0.6f);
float duration = Math::Rand()*0.5f+0.5f;
m_particle->CreateTrack(pos, speed, dim, Gfx::PARTITRACK6,
duration, 0.0f,
duration*0.9f, 0.7f);
}
}
if (m_progress < 1.0f)
{
m_progress += rTime*m_speed;
m_exchangePost->SetAngleZ(2, m_progress*2.0f*Math::PI);
m_exchangePost->SetAngleZ(4, m_progress*2.0f*Math::PI);
m_exchangePost->SetAngleZ(6, m_progress*2.0f*Math::PI);
}
else
{
m_phase = Phase::Wait;
m_exchangePost->SetAngleX(2, 0.0f);
m_exchangePost->SetAngleX(4, 0.0f);
m_exchangePost->SetAngleX(6, 0.0f);
m_exchangePost->SetAngleZ(2, 0.0f);
m_exchangePost->SetAngleZ(4, 0.0f);
m_exchangePost->SetAngleZ(6, 0.0f);
}
}
if ( m_phase == Phase::Error )
{
if (m_progress < 0.5f &&
m_lastParticle+m_engine->ParticleAdapt(0.05f) <= m_time)
{
m_lastParticle = m_time;
Math::Vector pos = m_goal;
Math::Vector speed;
speed.x = (Math::Rand()-0.5f)*5.0f;
speed.z = (Math::Rand()-0.5f)*5.0f;
speed.y = 5.0f+Math::Rand()*5.0f;
Math::Point dim;
dim.x = 5.0f+Math::Rand()*5.0f;
dim.y = dim.x;
float duration = 4.0f;
m_particle->CreateParticle(pos, speed, dim, Gfx::PARTISMOKE1, duration);
}
if (m_progress < 1.0f)
{
m_progress += rTime*m_speed;
rTime = 0.0f; // stops the rotation
float angle = 0.0f;
if ( m_progress < 0.5f )
{
angle = m_progress/0.5f;
}
else
{
angle = 1.0f-(m_progress-0.5f)/0.5f;
}
m_exchangePost->SetAngleX(2, angle*0.5f);
m_exchangePost->SetAngleX(4, angle*0.5f);
m_exchangePost->SetAngleX(6, angle*0.5f);
m_exchangePost->SetAngleZ(2, (Math::Rand()-0.5f)*0.2f);
m_exchangePost->SetAngleZ(4, (Math::Rand()-0.5f)*0.2f);
m_exchangePost->SetAngleZ(6, (Math::Rand()-0.5f)*0.2f);
}
else
{
m_phase = Phase::Wait;
m_exchangePost->SetAngleX(2, 0.0f);
m_exchangePost->SetAngleX(4, 0.0f);
m_exchangePost->SetAngleX(6, 0.0f);
m_exchangePost->SetAngleZ(2, 0.0f);
m_exchangePost->SetAngleZ(4, 0.0f);
m_exchangePost->SetAngleZ(6, 0.0f);
}
}
float angle = m_exchangePost->GetAngleY(1);
angle += rTime*0.5f;
m_exchangePost->SetAngleY(1, angle);
m_exchangePost->SetAngleX(3, sinf(m_time*6.0f+Math::PI*0.0f/3.0f)*0.3f);
m_exchangePost->SetAngleX(5, sinf(m_time*6.0f+Math::PI*2.0f/3.0f)*0.3f);
m_exchangePost->SetAngleX(7, sinf(m_time*6.0f+Math::PI*4.0f/3.0f)*0.3f);
return true;
}
Error CAutoInfo::GetError()
{
if (m_object->GetVirusMode())
{
return ERR_BAT_VIRUS;
}
return ERR_OK;
}
bool CAutoInfo::CreateInterface(bool select)
{
CAuto::CreateInterface(select);
if (!select) return true;
Ui::CWindow* pw = static_cast< Ui::CWindow* >(m_interface->SearchControl(EVENT_WINDOW0));
if (pw == nullptr) return false;
float ox = 3.0f/640.0f;
float oy = 3.0f/480.0f;
float sx = 33.0f/640.0f;
float sy = 33.0f/480.0f;
Math::Point pos, ddim;
pos.x = ox+sx*7.0f;
pos.y = oy+sy*0.0f;
ddim.x = 160.0f/640.0f;
ddim.y = 66.0f/480.0f;
Ui::CList* pl = pw->CreateList(pos, ddim, 1, EVENT_OBJECT_GINFO, 1.10f);
pl->SetSelectCap(false);
pos.x = ox+sx*0.0f;
pos.y = oy+sy*0;
ddim.x = 66.0f/640.0f;
ddim.y = 66.0f/480.0f;
pw->CreateGroup(pos, ddim, 112, EVENT_OBJECT_TYPE);
UpdateList();
return true;
}
void CAutoInfo::UpdateInterface(float rTime)
{
CAuto::UpdateInterface(rTime);
}
void CAutoInfo::UpdateList()
{
CExchangePost* object = static_cast<CExchangePost*>(m_object);
Ui::CWindow* pw = static_cast< Ui::CWindow* >(m_interface->SearchControl(EVENT_WINDOW0));
if (pw == nullptr) return;
Ui::CList* pl = static_cast< Ui::CList* >(pw->SearchControl(EVENT_OBJECT_GINFO));
if (pl == nullptr) return;
pl->Flush();
const auto& infoList = object->GetInfoList();
if (infoList.empty())
{
pl->ClearState(Ui::STATE_ENABLE);
}
else
{
pl->SetState(Ui::STATE_ENABLE);
for (int i = 0; i < static_cast<int>(infoList.size()); i++)
{
char text[100];
sprintf(text, "%s = %.2f", infoList[i].name.c_str(), infoList[i].value);
pl->SetItemName(i, text);
}
}
object->SetInfoUpdate(false);
}
void CAutoInfo::UpdateListVirus()
{
Ui::CWindow* pw = static_cast< Ui::CWindow* >(m_interface->SearchControl(EVENT_WINDOW0));
if (pw == nullptr) return;
Ui::CList* pl = static_cast< Ui::CList* >(pw->SearchControl(EVENT_OBJECT_GINFO));
if (pl == nullptr) return;
pl->SetState(Ui::STATE_ENABLE);
pl->Flush();
for (int i = 0; i < 4; ++i)
{
char text[100];
int max = static_cast< int >(2.0f+Math::Rand()*10.0f);
for (int j = 0; j < max; ++j)
{
do
{
text[j] = ' '+static_cast<int>(Math::Rand()*94.0f);
}
while (text[j] == '\\');
}
text[max] = 0;
pl->SetItemName(i, text);
}
}
bool CAutoInfo::Write(CLevelParserLine* line)
{
if (m_phase == Phase::Wait)
return false;
line->AddParam("aExist", CLevelParserParamUPtr{new CLevelParserParam(true)});
CAuto::Write(line);
line->AddParam("aPhase", CLevelParserParamUPtr{new CLevelParserParam(static_cast<int>(m_phase))});
line->AddParam("aProgress", CLevelParserParamUPtr{new CLevelParserParam(m_progress)});
line->AddParam("aSpeed", CLevelParserParamUPtr{new CLevelParserParam(m_speed)});
return true;
}
bool CAutoInfo::Read(CLevelParserLine* line)
{
if (!line->GetParam("aExist")->AsBool(false))
return false;
CAuto::Read(line);
m_phase = static_cast<Phase>(line->GetParam("aPhase")->AsInt(static_cast<int>(Phase::Wait)));
m_progress = line->GetParam("aProgress")->AsFloat(0.0f);
m_speed = line->GetParam("aSpeed")->AsFloat(1.0f);
m_lastParticle = 0.0f;
return true;
}

View File

@ -0,0 +1,110 @@
/*
* 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/object.h"
#include "object/auto/auto.h"
#include <string>
#include <vector>
#include <boost/optional.hpp>
struct ExchangePostInfo
{
std::string name; //!< name of the information
float value = 0.0f; //!< value of the information
};
struct ObjectCreateParams;
namespace Gfx {
class CModelManager;
class CEngine;
}
class CExchangePost : public CObject
{
public:
CExchangePost(int id);
static std::unique_ptr<CExchangePost> Create(
const ObjectCreateParams& params,
Gfx::CModelManager* modelManager,
Gfx::CEngine* engine);
static int GetMaximumInfoListSize();
bool SetInfo(const std::string& name, float value);
const std::vector<ExchangePostInfo>& GetInfoList();
boost::optional<float> GetInfoValue(const std::string& name);
bool HasInfo(const std::string& name);
bool DeleteInfo(const std::string& name);
void SetInfoUpdate(bool update);
bool GetInfoUpdate();
void Write(CLevelParserLine* line) override;
void Read(CLevelParserLine* line) override;
void ReadInfo(CLevelParserLine* line);
private:
std::vector<ExchangePostInfo> m_infoList;
float m_infoReturn;
bool m_infoUpdate;
};
// TODO: integrate this with CExchangePost
class CAutoInfo : public CAuto
{
public:
CAutoInfo(CExchangePost* object);
~CAutoInfo();
void DeleteObject(bool all=false) override;
void Init() override;
void Start(int param) override;
bool EventProcess(const Event &event) override;
Error GetError() override;
bool CreateInterface(bool select) override;
bool Write(CLevelParserLine* line) override;
bool Read(CLevelParserLine* line) override;
protected:
void UpdateInterface(float rTime);
void UpdateList();
void UpdateListVirus();
protected:
CExchangePost* m_exchangePost;
enum class Phase : unsigned int;
Phase m_phase;
float m_progress;
float m_speed;
float m_timeVirus;
float m_lastParticle;
Math::Vector m_goal;
bool m_lastVirus;
};

View File

@ -23,7 +23,7 @@
#include "graphics/engine/particle.h"
#include "object/object_manager.h"
#include "object/auto/autoinfo.h"
#include "object/subclass/exchange_post.h"
#include <string.h>
@ -32,6 +32,10 @@
// Object's constructor.
CTaskInfo::CTaskInfo(CObject* object) : CTask(object)
, m_progress(0.0f)
, m_speed(0.0f)
, m_time(0.0f)
, m_error(false)
{
}
@ -46,9 +50,9 @@ CTaskInfo::~CTaskInfo()
bool CTaskInfo::EventProcess(const Event &event)
{
if ( m_engine->GetPause() ) return true;
if ( event.type != EVENT_FRAME ) return true;
if ( m_bError ) return false;
if (m_engine->GetPause()) return true;
if (event.type != EVENT_FRAME) return true;
if (m_error) return false;
m_progress += event.rTime*m_speed; // other advance
m_time += event.rTime;
@ -59,89 +63,50 @@ bool CTaskInfo::EventProcess(const Event &event)
// Assigns the goal was achieved.
Error CTaskInfo::Start(const char *name, float value, float power, bool bSend)
Error CTaskInfo::Start(const char *name, float value, float power, bool send)
{
CObject* pInfo;
CAutoInfo* pAuto;
Math::Vector pos, goal;
Info info;
int i, total, op;
m_bError = true;
m_error = true;
m_object->SetInfoReturn(NAN);
pInfo = SearchInfo(power); // seeks terminal
if ( pInfo == 0 )
CExchangePost* exchangePost = FindExchangePost(power);
if (exchangePost == nullptr)
{
return ERR_INFO_NULL;
}
pAuto = static_cast<CAutoInfo*>(pInfo->GetAuto());
if ( pAuto == 0 )
int op = 1; // transmission impossible
if (send) // send?
{
return ERR_INFO_NULL;
}
op = 1; // transmission impossible
if ( bSend ) // send?
{
total = pInfo->GetInfoTotal();
for ( i=0 ; i<total ; i++ )
{
info = pInfo->GetInfo(i);
if ( strcmp(info.name, name) == 0 )
{
info.value = value;
pInfo->SetInfo(i, info);
break;
}
}
if ( i == total )
{
if ( total < OBJECTMAXINFO )
{
strcpy(info.name, name);
info.value = value;
pInfo->SetInfo(total, info);
op = 2; // start of reception (for terminal)
}
}
else
bool infoValueSet = exchangePost->SetInfo(name, value);
if (infoValueSet)
{
op = 2; // start of reception (for terminal)
}
}
else // receive?
{
total = pInfo->GetInfoTotal();
for ( i=0 ; i<total ; i++ )
{
info = pInfo->GetInfo(i);
if ( strcmp(info.name, name) == 0 )
{
m_object->SetInfoReturn(info.value);
break;
}
}
if ( i < total )
auto infoValue = exchangePost->GetInfoValue(name);
if (infoValue != boost::none)
{
m_object->SetInfoReturn(*infoValue);
op = 0; // beginning of transmission (for terminal)
}
}
pAuto->Start(op);
exchangePost->GetAuto()->Start(op);
if ( op == 0 ) // transmission?
Math::Vector pos, goal;
if (op == 0) // transmission?
{
pos = pInfo->GetPosition(0);
pos = exchangePost->GetPosition(0);
pos.y += 9.5f;
goal = m_object->GetPosition(0);
goal.y += 4.0f;
m_particle->CreateRay(pos, goal, Gfx::PARTIRAY3, Math::Point(2.0f, 2.0f), 1.0f);
}
if ( op == 2 ) // reception?
if (op == 2) // reception?
{
goal = pInfo->GetPosition(0);
goal = exchangePost->GetPosition(0);
goal.y += 9.5f;
pos = m_object->GetPosition(0);
pos.y += 4.0f;
@ -149,10 +114,10 @@ Error CTaskInfo::Start(const char *name, float value, float power, bool bSend)
}
m_progress = 0.0f;
m_speed = 1.0f/1.0f;
m_speed = 1.0f;
m_time = 0.0f;
m_bError = false; // ok
m_error = false; // ok
return ERR_OK;
}
@ -161,10 +126,10 @@ Error CTaskInfo::Start(const char *name, float value, float power, bool bSend)
Error CTaskInfo::IsEnded()
{
if ( m_engine->GetPause() ) return ERR_CONTINUE;
if ( m_bError ) return ERR_STOP;
if (m_engine->GetPause()) return ERR_CONTINUE;
if (m_error) return ERR_STOP;
if ( m_progress < 1.0f ) return ERR_CONTINUE;
if (m_progress < 1.0f) return ERR_CONTINUE;
m_progress = 0.0f;
Abort();
@ -181,8 +146,9 @@ bool CTaskInfo::Abort()
// Seeks the nearest information terminal.
CObject* CTaskInfo::SearchInfo(float power)
CExchangePost* CTaskInfo::FindExchangePost(float power)
{
return CObjectManager::GetInstancePointer()->FindNearest(m_object, OBJECT_INFO, power/g_unit);
return dynamic_cast<CExchangePost*>(
CObjectManager::GetInstancePointer()->FindNearest(m_object, OBJECT_INFO, power/g_unit));
}

View File

@ -24,7 +24,7 @@
#include "object/task/task.h"
class CExchangePost;
class CTaskInfo : public CTask
{
@ -32,19 +32,19 @@ public:
CTaskInfo(CObject* object);
~CTaskInfo();
bool EventProcess(const Event &event);
bool EventProcess(const Event &event) override;
Error Start(const char *name, float value, float power, bool bSend);
Error IsEnded();
bool Abort();
Error Start(const char *name, float value, float power, bool send);
Error IsEnded() override;
bool Abort() override;
protected:
CObject* SearchInfo(float power);
CExchangePost* FindExchangePost(float power);
protected:
float m_progress;
float m_speed;
float m_time;
bool m_bError;
bool m_error;
};

View File

@ -37,6 +37,7 @@
#include "object/object_manager.h"
#include "object/robotmain.h"
#include "object/task/taskmanager.h"
#include "object/subclass/exchange_post.h"
#include "object/auto/auto.h"
#include "object/auto/autofactory.h"
@ -2395,24 +2396,13 @@ bool CScriptFunctions::rSend(CBotVar* var, CBotVar* result, int& exception, void
// Seeks the nearest information terminal.
CObject* CScriptFunctions::SearchInfo(CScript* script, CObject* object, float power)
CExchangePost* CScriptFunctions::FindExchangePost(CObject* object, float power)
{
CObject *pBest;
Math::Vector iPos, oPos;
iPos = object->GetPosition(0);
pBest = CObjectManager::GetInstancePointer()->Radar(object, OBJECT_INFO);
if (pBest == nullptr)
return nullptr;
oPos = object->GetPosition(0);
if (Math::DistanceProjected(iPos, oPos) > power)
return nullptr;
return pBest;
CObject* exchangePost = CObjectManager::GetInstancePointer()->FindNearest(object, OBJECT_INFO, power/g_unit);
return dynamic_cast<CExchangePost*>(exchangePost);
}
// Compilation of the instruction "deleteinfo(nom, power)".
// Compilation of the instruction "deleteinfo(name, power)".
CBotTypResult CScriptFunctions::cDeleteInfo(CBotVar* &var, void* user)
{
@ -2420,59 +2410,43 @@ CBotTypResult CScriptFunctions::cDeleteInfo(CBotVar* &var, void* user)
if ( var->GetType() != CBotTypString ) return CBotTypResult(CBotErrBadString);
var = var->GetNext();
if ( var == 0 ) return CBotTypResult(CBotTypFloat);
if ( var == 0 ) return CBotTypResult(CBotTypBoolean);
if ( var->GetType() > CBotTypDouble ) return CBotTypResult(CBotErrBadNum);
var = var->GetNext();
if ( var != 0 ) return CBotTypResult(CBotErrOverParam);
return CBotTypResult(CBotTypFloat);
return CBotTypResult(CBotTypBoolean);
}
// Instruction "deleteinfo(nom, power)".
// Instruction "deleteinfo(name, power)".
bool CScriptFunctions::rDeleteInfo(CBotVar* var, CBotVar* result, int& exception, void* user)
{
CScript* script = (static_cast<CObject *>(user))->GetRunScript();
CObject* pThis = static_cast<CObject *>(user);
CObject* pInfo;
CBotString cbs;
Info info;
const char* p;
float power;
int i, total;
CObject* pThis = static_cast<CObject *>(user);
exception = 0;
cbs = var->GetValString();
p = cbs;
CBotString infoNameCbs = var->GetValString();
std::string infoName = std::string(static_cast<const char*>(infoNameCbs));
var = var->GetNext();
power = 10.0f*g_unit;
if ( var != 0 )
float power = 10.0f*g_unit;
if (var != nullptr)
{
power = var->GetValFloat()*g_unit;
var = var->GetNext();
}
pInfo = SearchInfo(script, pThis, power);
if ( pInfo == 0 )
CExchangePost* exchangePost = FindExchangePost(pThis, power);
if (exchangePost == nullptr)
{
result->SetValFloat(0.0f); // false
result->SetValInt(false);
return true;
}
total = pInfo->GetInfoTotal();
for ( i=0 ; i<total ; i++ )
{
info = pInfo->GetInfo(i);
if ( strcmp(info.name, p) == 0 )
{
pInfo->DeleteInfo(i);
result->SetValFloat(1.0f); // true
return true;
}
}
result->SetValFloat(0.0f); // false
bool infoDeleted = exchangePost->DeleteInfo(infoName);
result->SetValInt(infoDeleted);
return true;
}
@ -2492,50 +2466,34 @@ CBotTypResult CScriptFunctions::cTestInfo(CBotVar* &var, void* user)
return CBotTypResult(CBotTypBoolean);
}
// Instruction "testinfo(nom, power)".
// Instruction "testinfo(name, power)".
bool CScriptFunctions::rTestInfo(CBotVar* var, CBotVar* result, int& exception, void* user)
{
CScript* script = (static_cast<CObject *>(user))->GetRunScript();
CObject* pThis = static_cast<CObject *>(user);
CObject* pInfo;
CBotString cbs;
Info info;
const char* p;
float power;
int i, total;
CObject* pThis = static_cast<CObject *>(user);
exception = 0;
cbs = var->GetValString();
p = cbs;
CBotString infoNameCbs = var->GetValString();
std::string infoName = std::string(static_cast<const char*>(infoNameCbs));
var = var->GetNext();
power = 10.0f*g_unit;
if ( var != 0 )
float power = 10.0f*g_unit;
if (var != nullptr)
{
power = var->GetValFloat()*g_unit;
var = var->GetNext();
}
pInfo = SearchInfo(script, pThis, power);
if ( pInfo == 0 )
CExchangePost* exchangePost = FindExchangePost(pThis, power);
if (exchangePost == nullptr)
{
result->SetValInt(false);
return true;
}
total = pInfo->GetInfoTotal();
for ( i=0 ; i<total ; i++ )
{
info = pInfo->GetInfo(i);
if ( strcmp(info.name, p) == 0 )
{
result->SetValInt(true);
return true;
}
}
result->SetValInt(false);
bool foundInfo = exchangePost->HasInfo(infoName);
result->SetValInt(foundInfo);
return true;
}

View File

@ -33,6 +33,7 @@
class CObject;
class CScript;
class CExchangePost;
class CScriptFunctions
@ -182,7 +183,7 @@ public:
private:
static bool Process(CScript* script, CBotVar* result, int &exception);
static bool ShouldProcessStop(Error err, int errMode);
static CObject* SearchInfo(CScript* script, CObject* object, float power);
static CExchangePost* FindExchangePost(CObject* object, float power);
static std::unordered_map<int, FILE*> m_files;
static int m_nextFile;