Compare commits
12 Commits
colobot2
...
coolant-mo
Author | SHA1 | Date |
---|---|---|
|
8885f8476b | |
|
ad048ce60c | |
|
d7cf54c55b | |
|
80840b7c95 | |
|
e11cbae55e | |
|
8553be4ef3 | |
|
9d7fb57067 | |
|
0662424055 | |
|
8e54962c65 | |
|
346c2ee1f3 | |
|
cd49e4a702 | |
|
84585f4ebc |
|
@ -369,6 +369,7 @@ set(BASE_SOURCES
|
||||||
object/interface/flying_object.h
|
object/interface/flying_object.h
|
||||||
object/interface/fragile_object.h
|
object/interface/fragile_object.h
|
||||||
object/interface/interactive_object.h
|
object/interface/interactive_object.h
|
||||||
|
object/interface/liquid_container_object.h
|
||||||
object/interface/jet_flying_object.h
|
object/interface/jet_flying_object.h
|
||||||
object/interface/jostleable_object.h
|
object/interface/jostleable_object.h
|
||||||
object/interface/movable_object.h
|
object/interface/movable_object.h
|
||||||
|
@ -426,12 +427,15 @@ set(BASE_SOURCES
|
||||||
object/subclass/base_robot.h
|
object/subclass/base_robot.h
|
||||||
object/subclass/base_vehicle.cpp
|
object/subclass/base_vehicle.cpp
|
||||||
object/subclass/base_vehicle.h
|
object/subclass/base_vehicle.h
|
||||||
|
object/subclass/bucket.cpp
|
||||||
object/subclass/exchange_post.cpp
|
object/subclass/exchange_post.cpp
|
||||||
object/subclass/exchange_post.h
|
object/subclass/exchange_post.h
|
||||||
object/subclass/shielder.cpp
|
object/subclass/shielder.cpp
|
||||||
object/subclass/shielder.h
|
object/subclass/shielder.h
|
||||||
object/subclass/static_object.cpp
|
object/subclass/static_object.cpp
|
||||||
object/subclass/static_object.h
|
object/subclass/static_object.h
|
||||||
|
object/subclass/water_pump.cpp
|
||||||
|
object/subclass/water_pump.h
|
||||||
object/task/task.cpp
|
object/task/task.cpp
|
||||||
object/task/task.h
|
object/task/task.h
|
||||||
object/task/taskadvance.cpp
|
object/task/taskadvance.cpp
|
||||||
|
|
|
@ -77,6 +77,8 @@ enum Error
|
||||||
ERR_RESEARCH_ENERGY = 321, //!< more energy
|
ERR_RESEARCH_ENERGY = 321, //!< more energy
|
||||||
ERR_RESEARCH_TYPE = 322, //!< the wrong type of battery
|
ERR_RESEARCH_TYPE = 322, //!< the wrong type of battery
|
||||||
ERR_RESEARCH_ALREADY = 323, //!< research already done
|
ERR_RESEARCH_ALREADY = 323, //!< research already done
|
||||||
|
ERR_RESEARCH_NEED_COOLANT = 324, //!< need coolant
|
||||||
|
ERR_RESEARCH_MORE_COOLANT = 325, //!< need more coolant
|
||||||
ERR_ENERGY_NULL = 330, //!< no energy underground
|
ERR_ENERGY_NULL = 330, //!< no energy underground
|
||||||
ERR_ENERGY_LOW = 331, //!< not enough energy
|
ERR_ENERGY_LOW = 331, //!< not enough energy
|
||||||
ERR_ENERGY_EMPTY = 332, //!< lack of metal
|
ERR_ENERGY_EMPTY = 332, //!< lack of metal
|
||||||
|
|
|
@ -567,6 +567,8 @@ void InitializeRestext()
|
||||||
stringsObject[OBJECT_APOLLO4] = TR("Remains of Apollo mission");
|
stringsObject[OBJECT_APOLLO4] = TR("Remains of Apollo mission");
|
||||||
stringsObject[OBJECT_APOLLO5] = TR("Remains of Apollo mission");
|
stringsObject[OBJECT_APOLLO5] = TR("Remains of Apollo mission");
|
||||||
stringsObject[OBJECT_APOLLO2] = TR("Lunar Roving Vehicle");
|
stringsObject[OBJECT_APOLLO2] = TR("Lunar Roving Vehicle");
|
||||||
|
stringsObject[OBJECT_WATERPUMP] = TR("Water pump");
|
||||||
|
stringsObject[OBJECT_BUCKET] = TR("Bucket");
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -614,6 +616,8 @@ void InitializeRestext()
|
||||||
stringsErr[ERR_RESEARCH_ENERGY] = TR("Not enough energy");
|
stringsErr[ERR_RESEARCH_ENERGY] = TR("Not enough energy");
|
||||||
stringsErr[ERR_RESEARCH_TYPE] = TR("Inappropriate cell type");
|
stringsErr[ERR_RESEARCH_TYPE] = TR("Inappropriate cell type");
|
||||||
stringsErr[ERR_RESEARCH_ALREADY]= TR("Research program already performed");
|
stringsErr[ERR_RESEARCH_ALREADY]= TR("Research program already performed");
|
||||||
|
stringsErr[ERR_RESEARCH_NEED_COOLANT] = TR("No coolant cell");
|
||||||
|
stringsErr[ERR_RESEARCH_MORE_COOLANT] = TR("Not enough coolant");
|
||||||
stringsErr[ERR_ENERGY_NULL] = TR("No energy in the subsoil");
|
stringsErr[ERR_ENERGY_NULL] = TR("No energy in the subsoil");
|
||||||
stringsErr[ERR_ENERGY_LOW] = TR("Not enough energy yet");
|
stringsErr[ERR_ENERGY_LOW] = TR("Not enough energy yet");
|
||||||
stringsErr[ERR_ENERGY_EMPTY] = TR("No titanium to transform");
|
stringsErr[ERR_ENERGY_EMPTY] = TR("No titanium to transform");
|
||||||
|
|
|
@ -924,7 +924,8 @@ void CCamera::IsCollisionFix(Math::Vector &eye, Math::Vector lookat)
|
||||||
type == OBJECT_ANT ||
|
type == OBJECT_ANT ||
|
||||||
type == OBJECT_SPIDER ||
|
type == OBJECT_SPIDER ||
|
||||||
type == OBJECT_BEE ||
|
type == OBJECT_BEE ||
|
||||||
type == OBJECT_WORM ) continue;
|
type == OBJECT_WORM ||
|
||||||
|
type == OBJECT_BUCKET ) continue;
|
||||||
|
|
||||||
Math::Sphere objSphere = obj->GetCameraCollisionSphere();
|
Math::Sphere objSphere = obj->GetCameraCollisionSphere();
|
||||||
Math::Vector objPos = objSphere.pos;
|
Math::Vector objPos = objSphere.pos;
|
||||||
|
|
|
@ -57,7 +57,18 @@ bool COldModelManager::LoadModel(const std::string& fileName, bool mirrored, int
|
||||||
if (!stream.is_open())
|
if (!stream.is_open())
|
||||||
throw CModelIOException(std::string("Could not open file '") + fileName + "'");
|
throw CModelIOException(std::string("Could not open file '") + fileName + "'");
|
||||||
|
|
||||||
|
std::string::size_type extension_index = fileName.find_last_of('.');
|
||||||
|
if (extension_index == std::string::npos)
|
||||||
|
throw CModelIOException(std::string("Filename '") + fileName + "' has no extension");
|
||||||
|
|
||||||
|
std::string extension = fileName.substr(extension_index + 1);
|
||||||
|
|
||||||
|
if (extension == "mod")
|
||||||
model = ModelInput::Read(stream, ModelFormat::Old);
|
model = ModelInput::Read(stream, ModelFormat::Old);
|
||||||
|
else if (extension == "txt")
|
||||||
|
model = ModelInput::Read(stream, ModelFormat::Text);
|
||||||
|
else
|
||||||
|
throw CModelIOException(std::string("Filename '") + fileName + "' has unknown extension");
|
||||||
}
|
}
|
||||||
catch (const CModelIOException& e)
|
catch (const CModelIOException& e)
|
||||||
{
|
{
|
||||||
|
|
|
@ -533,6 +533,8 @@ ObjectType CLevelParserParam::ToObjectType(std::string value)
|
||||||
if (value == "Me" ) return OBJECT_HUMAN;
|
if (value == "Me" ) return OBJECT_HUMAN;
|
||||||
if (value == "Tech" ) return OBJECT_TECH;
|
if (value == "Tech" ) return OBJECT_TECH;
|
||||||
if (value == "MissionController" ) return OBJECT_CONTROLLER;
|
if (value == "MissionController" ) return OBJECT_CONTROLLER;
|
||||||
|
if (value == "WaterPump" ) return OBJECT_WATERPUMP;
|
||||||
|
if (value == "Bucket" ) return OBJECT_BUCKET;
|
||||||
return static_cast<ObjectType>(Cast<int>(value, "object"));
|
return static_cast<ObjectType>(Cast<int>(value, "object"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -730,6 +732,8 @@ const std::string CLevelParserParam::FromObjectType(ObjectType value)
|
||||||
if (value == OBJECT_HUMAN ) return "Me";
|
if (value == OBJECT_HUMAN ) return "Me";
|
||||||
if (value == OBJECT_TECH ) return "Tech";
|
if (value == OBJECT_TECH ) return "Tech";
|
||||||
if (value == OBJECT_CONTROLLER ) return "MissionController";
|
if (value == OBJECT_CONTROLLER ) return "MissionController";
|
||||||
|
if (value == OBJECT_WATERPUMP ) return "WaterPump";
|
||||||
|
if (value == OBJECT_BUCKET ) return "Bucket";
|
||||||
return boost::lexical_cast<std::string>(static_cast<int>(value));
|
return boost::lexical_cast<std::string>(static_cast<int>(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -33,6 +33,8 @@
|
||||||
#include "object/old_object.h"
|
#include "object/old_object.h"
|
||||||
|
|
||||||
#include "object/interface/powered_object.h"
|
#include "object/interface/powered_object.h"
|
||||||
|
#include "object/interface/liquid_container_object.h"
|
||||||
|
#include "object/interface/slotted_object.h"
|
||||||
|
|
||||||
#include "sound/sound.h"
|
#include "sound/sound.h"
|
||||||
|
|
||||||
|
@ -127,6 +129,12 @@ Error CAutoResearch::StartAction(int param)
|
||||||
{
|
{
|
||||||
return ERR_RESEARCH_ENERGY;
|
return ERR_RESEARCH_ENERGY;
|
||||||
}
|
}
|
||||||
|
CObject* coolantObj = dynamic_cast<CSlottedObject*>(m_object)->GetSlotContainedObject(0);
|
||||||
|
if (coolantObj == nullptr || !coolantObj->Implements(ObjectInterfaceType::LiquidContainer))
|
||||||
|
return ERR_RESEARCH_NEED_COOLANT;
|
||||||
|
CLiquidContainerObject *coolantAsLiq = dynamic_cast<CLiquidContainerObject*>(coolantObj);
|
||||||
|
if (coolantAsLiq->GetLiquidAmount() < 1.0f || coolantAsLiq->GetLiquidType() != LiquidType::WATER)
|
||||||
|
return ERR_RESEARCH_MORE_COOLANT;
|
||||||
|
|
||||||
float time = SEARCH_TIME;
|
float time = SEARCH_TIME;
|
||||||
if ( m_research == RESEARCH_TANK ) time *= 0.3f;
|
if ( m_research == RESEARCH_TANK ) time *= 0.3f;
|
||||||
|
@ -221,7 +229,11 @@ bool CAutoResearch::EventProcess(const Event &event)
|
||||||
FireStopUpdate(m_progress, true); // flashes
|
FireStopUpdate(m_progress, true); // flashes
|
||||||
if ( m_progress < 1.0f )
|
if ( m_progress < 1.0f )
|
||||||
{
|
{
|
||||||
if ( m_object->GetPower() == nullptr || !m_object->GetPower()->Implements(ObjectInterfaceType::PowerContainer) ) // more battery?
|
CObject* coolantObj = dynamic_cast<CSlottedObject*>(m_object)->GetSlotContainedObject(0);
|
||||||
|
|
||||||
|
if ( m_object->GetPower() == nullptr || !m_object->GetPower()->Implements(ObjectInterfaceType::PowerContainer) // more battery?
|
||||||
|
|| coolantObj == nullptr || !coolantObj->Implements(ObjectInterfaceType::LiquidContainer) // coolant cell removed?
|
||||||
|
|| dynamic_cast<CLiquidContainerObject*>(coolantObj)->GetLiquidType() != LiquidType::WATER)
|
||||||
{
|
{
|
||||||
SetBusy(false);
|
SetBusy(false);
|
||||||
UpdateInterface();
|
UpdateInterface();
|
||||||
|
@ -233,6 +245,7 @@ bool CAutoResearch::EventProcess(const Event &event)
|
||||||
}
|
}
|
||||||
power = dynamic_cast<CPowerContainerObject*>(m_object->GetPower());
|
power = dynamic_cast<CPowerContainerObject*>(m_object->GetPower());
|
||||||
power->SetEnergyLevel(1.0f-m_progress);
|
power->SetEnergyLevel(1.0f-m_progress);
|
||||||
|
dynamic_cast<CLiquidContainerObject*>(coolantObj)->SetLiquid(LiquidType::WATER, 1.0f - m_progress);
|
||||||
|
|
||||||
if ( m_lastParticle+m_engine->ParticleAdapt(0.05f) <= m_time )
|
if ( m_lastParticle+m_engine->ParticleAdapt(0.05f) <= m_time )
|
||||||
{
|
{
|
||||||
|
|
|
@ -0,0 +1,56 @@
|
||||||
|
/*
|
||||||
|
* This file is part of the Colobot: Gold Edition source code
|
||||||
|
* Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam
|
||||||
|
* http://epsitec.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_interface_type.h"
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
enum class LiquidType {
|
||||||
|
EMPTY,
|
||||||
|
WATER
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \class CLiquidContainerObject
|
||||||
|
* \brief Interface for buckets
|
||||||
|
*/
|
||||||
|
class CLiquidContainerObject
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
LiquidType m_liquidType = LiquidType::EMPTY;
|
||||||
|
float m_liquidAmount = 0.0f;
|
||||||
|
public:
|
||||||
|
explicit CLiquidContainerObject(ObjectInterfaceTypes& types)
|
||||||
|
{
|
||||||
|
types[static_cast<int>(ObjectInterfaceType::LiquidContainer)] = true;
|
||||||
|
}
|
||||||
|
virtual ~CLiquidContainerObject()
|
||||||
|
{}
|
||||||
|
|
||||||
|
void SetLiquid(LiquidType type, float level) {
|
||||||
|
assert(level >= 0.0f && level <= 1.0f);
|
||||||
|
assert(type != LiquidType::EMPTY || level == 0.0f);
|
||||||
|
m_liquidType = (level == 0.0f ? LiquidType::EMPTY : type);
|
||||||
|
m_liquidAmount = level;
|
||||||
|
}
|
||||||
|
|
||||||
|
LiquidType GetLiquidType() const {return m_liquidType;}
|
||||||
|
float GetLiquidAmount() const {return m_liquidAmount;}
|
||||||
|
};
|
|
@ -0,0 +1,53 @@
|
||||||
|
/*
|
||||||
|
* This file is part of the Colobot: Gold Edition source code
|
||||||
|
* Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam
|
||||||
|
* http://epsitec.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_interface_type.h"
|
||||||
|
#include "math/vector.h"
|
||||||
|
|
||||||
|
class CObject;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \class CSlottedObject
|
||||||
|
* \brief Interface for objects that hold other objects
|
||||||
|
*/
|
||||||
|
class CSlottedObject
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit CSlottedObject(ObjectInterfaceTypes& types)
|
||||||
|
{
|
||||||
|
types[static_cast<int>(ObjectInterfaceType::Slotted)] = true;
|
||||||
|
}
|
||||||
|
virtual ~CSlottedObject()
|
||||||
|
{}
|
||||||
|
|
||||||
|
//! Get number of slots. Valid slot numbers are 0 up to GetNumSlots()-1. Using invalid slot numbers in the other functions will crash the game.
|
||||||
|
virtual int GetNumSlots() = 0;
|
||||||
|
//! Get relative position of a slot.
|
||||||
|
virtual Math::Vector GetSlotPosition(int slotNum) = 0;
|
||||||
|
//! Get relative angle (in radians) where robot should be positioned when inserting into a slot.
|
||||||
|
virtual float GetSlotAngle(int slotNum) = 0;
|
||||||
|
//! Get the maximum angular distance from the ideal angle (in radians) where robot should be positioned when inserting into a slot.
|
||||||
|
virtual float GetSlotAcceptanceAngle(int slotNum) = 0;
|
||||||
|
//! Get object contained in a slot.
|
||||||
|
virtual CObject *GetSlotContainedObject(int slotNum) = 0;
|
||||||
|
//! Set object contained in a slot.
|
||||||
|
virtual void SetSlotContainedObject(int slotNum, CObject *object) = 0;
|
||||||
|
};
|
|
@ -211,6 +211,7 @@ public:
|
||||||
//! \todo It will work like this for now but later I'd like to refactor this to something more manageable ~krzys_h
|
//! \todo It will work like this for now but later I'd like to refactor this to something more manageable ~krzys_h
|
||||||
virtual bool IsBulletWall() { return false; }
|
virtual bool IsBulletWall() { return false; }
|
||||||
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
//! Transform crash sphere by object's world matrix
|
//! Transform crash sphere by object's world matrix
|
||||||
virtual void TransformCrashSphere(Math::Sphere& crashSphere) = 0;
|
virtual void TransformCrashSphere(Math::Sphere& crashSphere) = 0;
|
||||||
|
|
|
@ -46,6 +46,7 @@
|
||||||
#include "object/subclass/base_building.h"
|
#include "object/subclass/base_building.h"
|
||||||
#include "object/subclass/base_robot.h"
|
#include "object/subclass/base_robot.h"
|
||||||
#include "object/subclass/exchange_post.h"
|
#include "object/subclass/exchange_post.h"
|
||||||
|
#include "object/subclass/water_pump.h"
|
||||||
#include "object/subclass/shielder.h"
|
#include "object/subclass/shielder.h"
|
||||||
#include "object/subclass/static_object.h"
|
#include "object/subclass/static_object.h"
|
||||||
|
|
||||||
|
@ -87,6 +88,13 @@ CObjectUPtr CObjectFactory::CreateObject(const ObjectCreateParams& params)
|
||||||
case OBJECT_INFO:
|
case OBJECT_INFO:
|
||||||
return CExchangePost::Create(params, m_oldModelManager, m_engine);
|
return CExchangePost::Create(params, m_oldModelManager, m_engine);
|
||||||
|
|
||||||
|
case OBJECT_WATERPUMP:
|
||||||
|
return CreateObjectWaterPump(params, m_oldModelManager, m_modelManager, m_engine);
|
||||||
|
|
||||||
|
case OBJECT_BUCKET:
|
||||||
|
std::unique_ptr<CObject> CreateObjectBucket(const ObjectCreateParams&, Gfx::COldModelManager*, Gfx::CEngine*);
|
||||||
|
return CreateObjectBucket(params, m_oldModelManager, m_engine);
|
||||||
|
|
||||||
case OBJECT_PORTICO:
|
case OBJECT_PORTICO:
|
||||||
case OBJECT_BASE:
|
case OBJECT_BASE:
|
||||||
case OBJECT_DERRICK:
|
case OBJECT_DERRICK:
|
||||||
|
|
|
@ -45,6 +45,8 @@ struct ObjectCreateParams;
|
||||||
|
|
||||||
using CObjectUPtr = std::unique_ptr<CObject>;
|
using CObjectUPtr = std::unique_ptr<CObject>;
|
||||||
|
|
||||||
|
std::unique_ptr<CObject> CreateObjectBucket(const ObjectCreateParams ¶ms, Gfx::COldModelManager *modelManager, Gfx::CEngine *graphicsEngine);
|
||||||
|
|
||||||
class CObjectFactory
|
class CObjectFactory
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -54,6 +54,8 @@ enum class ObjectInterfaceType
|
||||||
Shielded, //!< objects that can be destroyed after the shield goes down to 0
|
Shielded, //!< objects that can be destroyed after the shield goes down to 0
|
||||||
ShieldedAutoRegen, //!< shielded objects with auto shield regeneration
|
ShieldedAutoRegen, //!< shielded objects with auto shield regeneration
|
||||||
Old, //!< old objects, TODO: remove once no longer necessary
|
Old, //!< old objects, TODO: remove once no longer necessary
|
||||||
|
LiquidContainer, //!< liquid container
|
||||||
|
Slotted, //!< objects that can carry other objects (in their gripper, power cell slot, or other slots)
|
||||||
Max //!< maximum value (for getting number of items in enum)
|
Max //!< maximum value (for getting number of items in enum)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -230,6 +230,8 @@ enum ObjectType
|
||||||
OBJECT_APOLLO4 = 903, //!< ApolloModule
|
OBJECT_APOLLO4 = 903, //!< ApolloModule
|
||||||
OBJECT_APOLLO5 = 904, //!< ApolloAntenna
|
OBJECT_APOLLO5 = 904, //!< ApolloAntenna
|
||||||
OBJECT_HOME1 = 910, //!< Home
|
OBJECT_HOME1 = 910, //!< Home
|
||||||
|
OBJECT_WATERPUMP = 920, //!< WaterPump
|
||||||
|
OBJECT_BUCKET = 921, //!< Bucket
|
||||||
|
|
||||||
OBJECT_MAX = 1000 //!< number of values
|
OBJECT_MAX = 1000 //!< number of values
|
||||||
};
|
};
|
||||||
|
|
|
@ -747,7 +747,8 @@ void COldObject::SetType(ObjectType type)
|
||||||
m_type == OBJECT_RESEARCH ||
|
m_type == OBJECT_RESEARCH ||
|
||||||
m_type == OBJECT_ENERGY ||
|
m_type == OBJECT_ENERGY ||
|
||||||
m_type == OBJECT_LABO ||
|
m_type == OBJECT_LABO ||
|
||||||
m_type == OBJECT_NUCLEAR )
|
m_type == OBJECT_NUCLEAR ||
|
||||||
|
m_type == OBJECT_WATERPUMP)
|
||||||
{
|
{
|
||||||
m_implementedInterfaces[static_cast<int>(ObjectInterfaceType::Powered)] = true;
|
m_implementedInterfaces[static_cast<int>(ObjectInterfaceType::Powered)] = true;
|
||||||
}
|
}
|
||||||
|
@ -772,6 +773,7 @@ void COldObject::SetType(ObjectType type)
|
||||||
m_type == OBJECT_SPIDER ||
|
m_type == OBJECT_SPIDER ||
|
||||||
m_type == OBJECT_BEE ||
|
m_type == OBJECT_BEE ||
|
||||||
m_type == OBJECT_TEEN28 )
|
m_type == OBJECT_TEEN28 )
|
||||||
|
// TODO OBJECT_BUCKET
|
||||||
{
|
{
|
||||||
m_implementedInterfaces[static_cast<int>(ObjectInterfaceType::Damageable)] = true;
|
m_implementedInterfaces[static_cast<int>(ObjectInterfaceType::Damageable)] = true;
|
||||||
m_implementedInterfaces[static_cast<int>(ObjectInterfaceType::Destroyable)] = true;
|
m_implementedInterfaces[static_cast<int>(ObjectInterfaceType::Destroyable)] = true;
|
||||||
|
@ -3204,13 +3206,15 @@ float COldObject::GetLightningHitProbability()
|
||||||
m_type == OBJECT_NUCLEAR ||
|
m_type == OBJECT_NUCLEAR ||
|
||||||
m_type == OBJECT_PARA ||
|
m_type == OBJECT_PARA ||
|
||||||
m_type == OBJECT_SAFE ||
|
m_type == OBJECT_SAFE ||
|
||||||
m_type == OBJECT_HUSTON ) // building?
|
m_type == OBJECT_HUSTON ||
|
||||||
|
m_type == OBJECT_WATERPUMP) // building?
|
||||||
{
|
{
|
||||||
return 1.0f;
|
return 1.0f;
|
||||||
}
|
}
|
||||||
if ( m_type == OBJECT_METAL ||
|
if ( m_type == OBJECT_METAL ||
|
||||||
m_type == OBJECT_POWER ||
|
m_type == OBJECT_POWER ||
|
||||||
m_type == OBJECT_ATOMIC ) // resource?
|
m_type == OBJECT_ATOMIC ||
|
||||||
|
m_type == OBJECT_BUCKET ) // resource?
|
||||||
{
|
{
|
||||||
return 0.3f;
|
return 0.3f;
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "object/subclass/base_building.h"
|
#include "object/subclass/base_building.h"
|
||||||
|
#include "object/interface/slotted_object.h"
|
||||||
|
|
||||||
#include "common/make_unique.h"
|
#include "common/make_unique.h"
|
||||||
|
|
||||||
|
@ -47,6 +48,41 @@
|
||||||
#include "object/auto/autotower.h"
|
#include "object/auto/autotower.h"
|
||||||
#include "object/auto/autovault.h"
|
#include "object/auto/autovault.h"
|
||||||
|
|
||||||
|
class CResearchLab : public CBaseBuilding, public CSlottedObject {
|
||||||
|
public:
|
||||||
|
CResearchLab(int id)
|
||||||
|
: CBaseBuilding(id, OBJECT_RESEARCH)
|
||||||
|
, CSlottedObject(m_implementedInterfaces)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
CObject *m_extraSlotObject = nullptr;
|
||||||
|
|
||||||
|
virtual int GetNumSlots() override {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
virtual Math::Vector GetSlotPosition(int slotNum) override {
|
||||||
|
assert(slotNum == 0);
|
||||||
|
return Math::Vector(-7.5f, 3.0f, 0.0f); // opposite the power cell slot
|
||||||
|
}
|
||||||
|
virtual float GetSlotAngle(int slotNum) override {
|
||||||
|
assert(slotNum == 0);
|
||||||
|
return Math::PI; // 180 degrees
|
||||||
|
}
|
||||||
|
virtual float GetSlotAcceptanceAngle(int slotNum) override {
|
||||||
|
assert(slotNum == 0);
|
||||||
|
return 45.0f*Math::PI/180.0f; // up to 45 degree offset is allowed, in either direction
|
||||||
|
}
|
||||||
|
virtual CObject *GetSlotContainedObject(int slotNum) override {
|
||||||
|
assert(slotNum == 0);
|
||||||
|
return m_extraSlotObject;
|
||||||
|
}
|
||||||
|
virtual void SetSlotContainedObject(int slotNum, CObject *object) override {
|
||||||
|
assert(slotNum == 0);
|
||||||
|
m_extraSlotObject = object;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
CBaseBuilding::CBaseBuilding(int id, ObjectType type)
|
CBaseBuilding::CBaseBuilding(int id, ObjectType type)
|
||||||
: COldObject(id)
|
: COldObject(id)
|
||||||
|
@ -62,7 +98,7 @@ std::unique_ptr<CBaseBuilding> CBaseBuilding::Create(
|
||||||
Gfx::COldModelManager* modelManager,
|
Gfx::COldModelManager* modelManager,
|
||||||
Gfx::CEngine* engine)
|
Gfx::CEngine* engine)
|
||||||
{
|
{
|
||||||
auto obj = MakeUnique<CBaseBuilding>(params.id, params.type);
|
auto obj = (params.type == OBJECT_RESEARCH ? MakeUnique<CResearchLab>(params.id) : MakeUnique<CBaseBuilding>(params.id, params.type));
|
||||||
|
|
||||||
obj->SetTeam(params.team);
|
obj->SetTeam(params.team);
|
||||||
|
|
||||||
|
@ -272,7 +308,7 @@ std::unique_ptr<CBaseBuilding> CBaseBuilding::Create(
|
||||||
|
|
||||||
if ( params.type == OBJECT_RESEARCH )
|
if ( params.type == OBJECT_RESEARCH )
|
||||||
{
|
{
|
||||||
modelManager->AddModelReference("search1.mod", false, rank, params.team);
|
modelManager->AddModelReference("search1_with_water.txt", false, rank, params.team);
|
||||||
obj->SetPosition(params.pos);
|
obj->SetPosition(params.pos);
|
||||||
obj->SetRotationY(params.angle);
|
obj->SetRotationY(params.angle);
|
||||||
obj->SetFloorHeight(0.0f);
|
obj->SetFloorHeight(0.0f);
|
||||||
|
|
|
@ -0,0 +1,112 @@
|
||||||
|
/*
|
||||||
|
* This file is part of the Colobot: Gold Edition source code
|
||||||
|
* Copyright (C) 2001-2020, Daniel Roux, EPSITEC SA & TerranovaTeam
|
||||||
|
* http://epsitec.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/object.h"
|
||||||
|
#include "object/old_object.h"
|
||||||
|
#include "object/interface/liquid_container_object.h"
|
||||||
|
|
||||||
|
#include "object/object_factory.h"
|
||||||
|
|
||||||
|
#include "graphics/engine/engine.h"
|
||||||
|
#include "graphics/engine/oldmodelmanager.h"
|
||||||
|
|
||||||
|
#include "common/make_unique.h"
|
||||||
|
|
||||||
|
#include "level/parser/parserexceptions.h"
|
||||||
|
#include "level/parser/parserline.h"
|
||||||
|
#include "level/parser/parserparam.h"
|
||||||
|
|
||||||
|
#include "object/object_create_params.h"
|
||||||
|
|
||||||
|
#include <boost/lexical_cast.hpp>
|
||||||
|
|
||||||
|
class CBucket
|
||||||
|
: public COldObject
|
||||||
|
, public CLiquidContainerObject
|
||||||
|
{
|
||||||
|
LiquidType m_displayedLiquidType = LiquidType::EMPTY;
|
||||||
|
float m_displayedLiquidAmount = -100; // force initial update
|
||||||
|
public:
|
||||||
|
CBucket(int id)
|
||||||
|
: COldObject(id)
|
||||||
|
, CLiquidContainerObject(m_implementedInterfaces)
|
||||||
|
{
|
||||||
|
SetType(OBJECT_BUCKET);
|
||||||
|
m_implementedInterfaces[static_cast<int>(ObjectInterfaceType::Transportable)] = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool EventProcess(const Event& event) override {
|
||||||
|
if (!COldObject::EventProcess(event))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (event.type == EVENT_FRAME && (m_displayedLiquidType != m_liquidType || !Math::IsEqual(m_displayedLiquidAmount, m_liquidAmount, 0.003f))) {
|
||||||
|
UpdateTextureMapping();
|
||||||
|
m_displayedLiquidType = m_liquidType;
|
||||||
|
m_displayedLiquidAmount = m_liquidAmount;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
void UpdateTextureMapping() {
|
||||||
|
Gfx::Material mat;
|
||||||
|
mat.diffuse = Gfx::Color(1.0f, 1.0f, 1.0f); // white
|
||||||
|
mat.ambient = Gfx::Color(0.5f, 0.5f, 0.5f);
|
||||||
|
|
||||||
|
int type = static_cast<int>(m_liquidType) - 1;
|
||||||
|
if(type > 0) type--; // don't use a texture slot for EMPTY liquid type, just reuse whatever liquid comes first
|
||||||
|
float vcoord = (type + 0.5f) / 128.0f;
|
||||||
|
|
||||||
|
// Y coordinate ranges from 0 to 2.
|
||||||
|
// If m_liquidAmount is 0, u coordinate ranges from 0 to 0.5.
|
||||||
|
// If m_liquidAmount is 1, u coordinate ranges from 0.5 to 1.
|
||||||
|
// In any case, v is a constant depending on the liquid type.
|
||||||
|
// The highest u coordinate needs to be at the lowest Y coordinate.
|
||||||
|
|
||||||
|
m_engine->ChangeTextureMapping(m_objectPart[0].object,
|
||||||
|
mat, Gfx::ENG_RSTATE_PART3, "objects/liquid.png", "",
|
||||||
|
Gfx::ENG_TEX_MAPPING_X,
|
||||||
|
0.0f, vcoord, -0.25f, 0.5f + 0.5f*m_liquidAmount);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
std::unique_ptr<CObject> CreateObjectBucket(const ObjectCreateParams ¶ms, Gfx::COldModelManager *modelManager, Gfx::CEngine *graphicsEngine)
|
||||||
|
{
|
||||||
|
std::unique_ptr<CBucket> newObj = MakeUnique<CBucket>(params.id);
|
||||||
|
|
||||||
|
int rootGraphObj = graphicsEngine->CreateObject();
|
||||||
|
graphicsEngine->SetObjectType(rootGraphObj, Gfx::ENG_OBJTYPE_FIX); // XXX: why is ENG_OBJTYPE_FIX used for movable objects? (this is the same as for powercells, titanium, etc)
|
||||||
|
newObj->SetObjectRank(0, rootGraphObj);
|
||||||
|
modelManager->AddModelCopy("bucket.txt", false, rootGraphObj);
|
||||||
|
|
||||||
|
newObj->SetPosition(params.pos);
|
||||||
|
newObj->SetRotationY(params.angle);
|
||||||
|
|
||||||
|
// standard settings for transportable objects
|
||||||
|
newObj->AddCrashSphere(CrashSphere(Math::Vector(0.0f, 1.0f, 0.0f), 1.0f, SOUND_BOUMm, 0.45f));
|
||||||
|
newObj->SetCameraCollisionSphere(Math::Sphere(Math::Vector(0.0f, 1.0f, 0.0f), 1.5f));
|
||||||
|
newObj->CreateShadowCircle(1.5f, 1.0f);
|
||||||
|
newObj->SetFloorHeight(0.0f);
|
||||||
|
newObj->FloorAdjust();
|
||||||
|
|
||||||
|
graphicsEngine->LoadAllTextures();
|
||||||
|
|
||||||
|
return newObj;
|
||||||
|
}
|
|
@ -0,0 +1,162 @@
|
||||||
|
/*
|
||||||
|
* This file is part of the Colobot: Gold Edition source code
|
||||||
|
* Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam
|
||||||
|
* http://epsitec.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/water_pump.h"
|
||||||
|
#include "object/interface/liquid_container_object.h"
|
||||||
|
|
||||||
|
#include "common/make_unique.h"
|
||||||
|
#include "common/regex_utils.h"
|
||||||
|
|
||||||
|
#include "graphics/engine/oldmodelmanager.h" // XXX delete
|
||||||
|
#include "graphics/model/model_manager.h"
|
||||||
|
|
||||||
|
#include "level/parser/parserexceptions.h"
|
||||||
|
#include "level/parser/parserline.h"
|
||||||
|
#include "level/parser/parserparam.h"
|
||||||
|
|
||||||
|
#include "object/object_create_params.h"
|
||||||
|
|
||||||
|
#include "sound/sound.h"
|
||||||
|
|
||||||
|
#include "ui/controls/interface.h"
|
||||||
|
#include "ui/controls/list.h"
|
||||||
|
#include "ui/controls/window.h"
|
||||||
|
|
||||||
|
#include <boost/lexical_cast.hpp>
|
||||||
|
|
||||||
|
class CWaterPump : public CBaseBuilding
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CWaterPump(int id)
|
||||||
|
: CBaseBuilding(id, OBJECT_WATERPUMP)
|
||||||
|
{
|
||||||
|
m_implementedInterfaces[static_cast<int>(ObjectInterfaceType::Powered)] = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Write(CLevelParserLine* line) override;
|
||||||
|
void Read(CLevelParserLine* line) override;
|
||||||
|
|
||||||
|
using COldObject::SetAuto;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct CAutoWaterPump : public CAuto
|
||||||
|
{
|
||||||
|
CAutoWaterPump(CWaterPump* object) : CAuto(object) {}
|
||||||
|
~CAutoWaterPump() {}
|
||||||
|
|
||||||
|
float cycle = 0.0f;
|
||||||
|
|
||||||
|
bool EventProcess(const Event &event) override {
|
||||||
|
CAuto::EventProcess(event);
|
||||||
|
if (event.type == EVENT_FRAME && !m_engine->GetPause()) {
|
||||||
|
CObject *powerCell = m_object->GetPower();
|
||||||
|
if (powerCell != nullptr) {
|
||||||
|
|
||||||
|
if (powerCell->Implements(ObjectInterfaceType::LiquidContainer)) {
|
||||||
|
// test code
|
||||||
|
CLiquidContainerObject *asPC = dynamic_cast<CLiquidContainerObject*>(powerCell);
|
||||||
|
if (asPC->GetLiquidType() == LiquidType::WATER || asPC->GetLiquidType() == LiquidType::EMPTY) {
|
||||||
|
float water = asPC->GetLiquidAmount();
|
||||||
|
|
||||||
|
if (water < 1.0f)
|
||||||
|
{
|
||||||
|
// animation
|
||||||
|
cycle = fmodf(cycle + event.rTime, 1.0f);
|
||||||
|
if (cycle < 0.5f)
|
||||||
|
m_object->SetPartPosition(1, Math::Vector(0.0f, 4.0f * cycle + 1.5f, 0.0f));
|
||||||
|
else
|
||||||
|
m_object->SetPartPosition(1, Math::Vector(0.0f, 4.0f - (4.0f * cycle) + 1.5f, 0.0f));
|
||||||
|
}
|
||||||
|
|
||||||
|
water = water + (0.2f * event.rTime);
|
||||||
|
if(water > 1.0f) water = 1.0f;
|
||||||
|
asPC->SetLiquid(LiquidType::WATER, water);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true; // XXX what does this mean?
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
std::unique_ptr<CObject> CreateObjectWaterPump(
|
||||||
|
const ObjectCreateParams& params,
|
||||||
|
Gfx::COldModelManager* oldModelManager, // XXX remove
|
||||||
|
Gfx::CModelManager* modelManager,
|
||||||
|
Gfx::CEngine* engine)
|
||||||
|
{
|
||||||
|
auto obj = MakeUnique<CWaterPump>(params.id);
|
||||||
|
|
||||||
|
obj->SetTeam(params.team);
|
||||||
|
|
||||||
|
/*static int info1_base_rank = -1;
|
||||||
|
if (info1_base_rank == -1) {
|
||||||
|
Gfx::CModel& model_info1 = modelManager->GetModel("info1");
|
||||||
|
info1_base_rank = engine->CreateBaseObject();
|
||||||
|
engine->AddBaseObjTriangles(info1_base_rank, model_info1.GetMesh("main")->GetTriangles());
|
||||||
|
}*/
|
||||||
|
|
||||||
|
int rank = engine->CreateObject();
|
||||||
|
engine->SetObjectType(rank, Gfx::ENG_OBJTYPE_FIX); // it is a stationary object
|
||||||
|
obj->SetObjectRank(0, rank);
|
||||||
|
//engine->SetObjectBaseRank(rank, info1_base_rank);
|
||||||
|
oldModelManager->AddModelReference("waterpump.txt", false, rank);
|
||||||
|
obj->SetPosition(params.pos);
|
||||||
|
obj->SetRotationY(params.angle);
|
||||||
|
obj->SetFloorHeight(0.0f);
|
||||||
|
|
||||||
|
rank = engine->CreateObject();
|
||||||
|
engine->SetObjectType(rank, Gfx::ENG_OBJTYPE_DESCENDANT);
|
||||||
|
obj->SetObjectRank(1, rank);
|
||||||
|
obj->SetObjectParent(1, 0);
|
||||||
|
//engine->SetObjectBaseRank(rank, info1_base_rank);
|
||||||
|
oldModelManager->AddModelReference("info2.mod", false, rank);
|
||||||
|
obj->SetPartPosition(1, Math::Vector(0.0f, 1.0f, 0.0f));
|
||||||
|
obj->SetPartRotationY(1, 0.0f);
|
||||||
|
|
||||||
|
obj->AddCrashSphere(CrashSphere(Math::Vector(0.0f, 3.0f, 0.0f), 6.0f, SOUND_BOUMm, 0.45f));
|
||||||
|
obj->AddCrashSphere(CrashSphere(Math::Vector(7.0f, 1.0f, 0.0f), 1.5f, SOUND_BOUMm, 0.45f));
|
||||||
|
obj->SetCameraCollisionSphere(Math::Sphere(Math::Vector(0.0f, 5.0f, 0.0f), 6.0f));
|
||||||
|
obj->SetPowerPosition(Math::Vector(7.0, 2.5, 0.0));
|
||||||
|
|
||||||
|
obj->CreateShadowCircle(8.0f, 1.0f);
|
||||||
|
|
||||||
|
Math::Vector pos = obj->GetPosition();
|
||||||
|
pos.y += params.height;
|
||||||
|
obj->SetPosition(pos); // to display the shadows immediately
|
||||||
|
|
||||||
|
auto objAuto = MakeUnique<CAutoWaterPump>(obj.get());
|
||||||
|
objAuto->Init();
|
||||||
|
obj->SetAuto(std::move(objAuto));
|
||||||
|
|
||||||
|
engine->LoadAllTextures();
|
||||||
|
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CWaterPump::Write(CLevelParserLine* line)
|
||||||
|
{
|
||||||
|
CBaseBuilding::Write(line);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CWaterPump::Read(CLevelParserLine* line)
|
||||||
|
{
|
||||||
|
CBaseBuilding::Read(line);
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,81 @@
|
||||||
|
/*
|
||||||
|
* This file is part of the Colobot: Gold Edition source code
|
||||||
|
* Copyright (C) 2001-2018, Daniel Roux, EPSITEC SA & TerranovaTeam
|
||||||
|
* http://epsitec.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/subclass/base_building.h"
|
||||||
|
|
||||||
|
#include "object/auto/auto.h"
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include <boost/optional.hpp>
|
||||||
|
|
||||||
|
struct ObjectCreateParams;
|
||||||
|
|
||||||
|
namespace Gfx
|
||||||
|
{
|
||||||
|
class COldModelManager;
|
||||||
|
class CModelManager;
|
||||||
|
class CEngine;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<CObject> CreateObjectWaterPump(
|
||||||
|
const ObjectCreateParams& params,
|
||||||
|
Gfx::COldModelManager* oldModelManager,
|
||||||
|
Gfx::CModelManager* modelManager,
|
||||||
|
Gfx::CEngine* engine);
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
};*/
|
|
@ -1274,6 +1274,16 @@ bool CTaskGoto::GetHotPoint(CObject *pObj, Math::Vector &pos,
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( type == OBJECT_WATERPUMP )
|
||||||
|
{
|
||||||
|
mat = pObj->GetWorldMatrix(0);
|
||||||
|
pos.x += 7.0f;
|
||||||
|
if ( bTake && distance != 0.0f ) suppl = 2.5f;
|
||||||
|
if ( bTake ) pos.x += TAKE_DIST+TAKE_DIST_OTHER+distance+suppl;
|
||||||
|
pos = Transform(*mat, pos);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
if ( type == OBJECT_ENERGY )
|
if ( type == OBJECT_ENERGY )
|
||||||
{
|
{
|
||||||
mat = pObj->GetWorldMatrix(0);
|
mat = pObj->GetWorldMatrix(0);
|
||||||
|
|
|
@ -33,11 +33,14 @@
|
||||||
#include "object/interface/carrier_object.h"
|
#include "object/interface/carrier_object.h"
|
||||||
#include "object/interface/powered_object.h"
|
#include "object/interface/powered_object.h"
|
||||||
#include "object/interface/transportable_object.h"
|
#include "object/interface/transportable_object.h"
|
||||||
|
#include "object/interface/slotted_object.h"
|
||||||
|
|
||||||
#include "physics/physics.h"
|
#include "physics/physics.h"
|
||||||
|
|
||||||
#include "sound/sound.h"
|
#include "sound/sound.h"
|
||||||
|
|
||||||
|
const int INVALID_SLOT = -1;
|
||||||
|
const int ENERGY_CELL_SLOT = -2;
|
||||||
|
|
||||||
//?const float MARGIN_FRONT = 2.0f;
|
//?const float MARGIN_FRONT = 2.0f;
|
||||||
//?const float MARGIN_BACK = 2.0f;
|
//?const float MARGIN_BACK = 2.0f;
|
||||||
|
@ -263,6 +266,16 @@ void CTaskManip::InitAngle()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool ObjectSlotOccupied(CObject *obj, int slotnum) {
|
||||||
|
if(slotnum == ENERGY_CELL_SLOT)
|
||||||
|
return ObjectHasPowerCell(obj);
|
||||||
|
else {
|
||||||
|
if (!obj->Implements(ObjectInterfaceType::Slotted))
|
||||||
|
return false;
|
||||||
|
return dynamic_cast<CSlottedObject*>(obj)->GetSlotContainedObject(slotnum) != nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Assigns the goal was achieved.
|
// Assigns the goal was achieved.
|
||||||
|
|
||||||
Error CTaskManip::Start(TaskManipOrder order, TaskManipArm arm)
|
Error CTaskManip::Start(TaskManipOrder order, TaskManipArm arm)
|
||||||
|
@ -393,7 +406,8 @@ Error CTaskManip::Start(TaskManipOrder order, TaskManipArm arm)
|
||||||
if ( m_arm == TMA_FFRONT )
|
if ( m_arm == TMA_FFRONT )
|
||||||
{
|
{
|
||||||
front = SearchTakeFrontObject(true, fPos, fDist, fAngle);
|
front = SearchTakeFrontObject(true, fPos, fDist, fAngle);
|
||||||
other = SearchOtherObject(true, oPos, oDist, oAngle, oHeight);
|
int slotNum;
|
||||||
|
other = SearchOtherObject(true, oPos, oDist, oAngle, oHeight, slotNum);
|
||||||
|
|
||||||
if ( front != nullptr && fDist < oDist )
|
if ( front != nullptr && fDist < oDist )
|
||||||
{
|
{
|
||||||
|
@ -403,7 +417,7 @@ Error CTaskManip::Start(TaskManipOrder order, TaskManipArm arm)
|
||||||
}
|
}
|
||||||
else if ( other != nullptr && oDist < fDist )
|
else if ( other != nullptr && oDist < fDist )
|
||||||
{
|
{
|
||||||
if (! ObjectHasPowerCell(other)) return ERR_MANIP_NIL;
|
if (! ObjectSlotOccupied(other, slotNum)) return ERR_MANIP_NIL;
|
||||||
m_targetPos = oPos;
|
m_targetPos = oPos;
|
||||||
m_angle = oAngle;
|
m_angle = oAngle;
|
||||||
m_height = oHeight;
|
m_height = oHeight;
|
||||||
|
@ -436,8 +450,9 @@ Error CTaskManip::Start(TaskManipOrder order, TaskManipArm arm)
|
||||||
{
|
{
|
||||||
if ( m_arm == TMA_FFRONT )
|
if ( m_arm == TMA_FFRONT )
|
||||||
{
|
{
|
||||||
other = SearchOtherObject(true, oPos, oDist, oAngle, oHeight);
|
int slotNum;
|
||||||
if (other != nullptr && !ObjectHasPowerCell(other))
|
other = SearchOtherObject(true, oPos, oDist, oAngle, oHeight, slotNum);
|
||||||
|
if (other != nullptr && !ObjectSlotOccupied(other, slotNum))
|
||||||
{
|
{
|
||||||
m_targetPos = oPos;
|
m_targetPos = oPos;
|
||||||
m_angle = oAngle;
|
m_angle = oAngle;
|
||||||
|
@ -868,8 +883,10 @@ CObject* CTaskManip::SearchTakeBackObject(bool bAdvance, Math::Vector &pos,
|
||||||
|
|
||||||
CObject* CTaskManip::SearchOtherObject(bool bAdvance, Math::Vector &pos,
|
CObject* CTaskManip::SearchOtherObject(bool bAdvance, Math::Vector &pos,
|
||||||
float &distance, float &angle,
|
float &distance, float &angle,
|
||||||
float &height)
|
float &height, int &slotNumOut)
|
||||||
{
|
{
|
||||||
|
slotNumOut = INVALID_SLOT;
|
||||||
|
|
||||||
Math::Matrix* mat;
|
Math::Matrix* mat;
|
||||||
float iAngle, oAngle, oLimit, aLimit, dLimit;
|
float iAngle, oAngle, oLimit, aLimit, dLimit;
|
||||||
|
|
||||||
|
@ -901,15 +918,11 @@ CObject* CTaskManip::SearchOtherObject(bool bAdvance, Math::Vector &pos,
|
||||||
if ( pObj == m_object ) continue; // yourself?
|
if ( pObj == m_object ) continue; // yourself?
|
||||||
|
|
||||||
ObjectType type = pObj->GetType();
|
ObjectType type = pObj->GetType();
|
||||||
if ( !pObj->Implements(ObjectInterfaceType::Powered) ) continue;
|
if ( pObj->Implements(ObjectInterfaceType::Powered) ) {
|
||||||
|
|
||||||
CObject* power = dynamic_cast<CPoweredObject*>(pObj)->GetPower();
|
CObject* power = dynamic_cast<CPoweredObject*>(pObj)->GetPower();
|
||||||
if (power != nullptr)
|
if (power == nullptr || (!power->GetLock() && power->GetScaleY() == 1.0f))
|
||||||
{
|
{
|
||||||
if (power->GetLock()) continue;
|
|
||||||
if (power->GetScaleY() != 1.0f) continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
mat = pObj->GetWorldMatrix(0);
|
mat = pObj->GetWorldMatrix(0);
|
||||||
Math::Vector oPos = Transform(*mat, dynamic_cast<CPoweredObject*>(pObj)->GetPowerPosition());
|
Math::Vector oPos = Transform(*mat, dynamic_cast<CPoweredObject*>(pObj)->GetPowerPosition());
|
||||||
|
|
||||||
|
@ -931,6 +944,10 @@ CObject* CTaskManip::SearchOtherObject(bool bAdvance, Math::Vector &pos,
|
||||||
{
|
{
|
||||||
oLimit = 45.0f*Math::PI/180.0f;
|
oLimit = 45.0f*Math::PI/180.0f;
|
||||||
}
|
}
|
||||||
|
else if ( type == OBJECT_WATERPUMP )
|
||||||
|
{
|
||||||
|
oLimit = 3; //Math::PI doesn't work
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
oLimit = 45.0f*Math::PI/180.0f;
|
oLimit = 45.0f*Math::PI/180.0f;
|
||||||
|
@ -938,8 +955,8 @@ CObject* CTaskManip::SearchOtherObject(bool bAdvance, Math::Vector &pos,
|
||||||
}
|
}
|
||||||
oAngle = Math::NormAngle(oAngle); // 0..2*Math::PI
|
oAngle = Math::NormAngle(oAngle); // 0..2*Math::PI
|
||||||
angle = Math::RotateAngle(iPos.x-oPos.x, oPos.z-iPos.z); // CW !
|
angle = Math::RotateAngle(iPos.x-oPos.x, oPos.z-iPos.z); // CW !
|
||||||
if ( !Math::TestAngle(angle, oAngle-oLimit, oAngle+oLimit) ) continue;
|
if ( Math::TestAngle(angle, oAngle-oLimit, oAngle+oLimit) )
|
||||||
|
{
|
||||||
distance = fabs(Math::Distance(oPos, iPos)-TAKE_DIST);
|
distance = fabs(Math::Distance(oPos, iPos)-TAKE_DIST);
|
||||||
if ( distance <= dLimit )
|
if ( distance <= dLimit )
|
||||||
{
|
{
|
||||||
|
@ -949,10 +966,51 @@ CObject* CTaskManip::SearchOtherObject(bool bAdvance, Math::Vector &pos,
|
||||||
Math::Vector powerPos = dynamic_cast<CPoweredObject*>(pObj)->GetPowerPosition();
|
Math::Vector powerPos = dynamic_cast<CPoweredObject*>(pObj)->GetPowerPosition();
|
||||||
height = powerPos.y;
|
height = powerPos.y;
|
||||||
pos = oPos;
|
pos = oPos;
|
||||||
|
slotNumOut = ENERGY_CELL_SLOT;
|
||||||
return pObj;
|
return pObj;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pObj->Implements(ObjectInterfaceType::Slotted)) {
|
||||||
|
CSlottedObject *obj = dynamic_cast<CSlottedObject*>(pObj);
|
||||||
|
int slotNum = obj->GetNumSlots();
|
||||||
|
for (int slot = 0; slot < slotNum; slot++) {
|
||||||
|
mat = pObj->GetWorldMatrix(0);
|
||||||
|
Math::Vector worldSlotPos = Transform(*mat, obj->GetSlotPosition(slot));
|
||||||
|
// TODO: check GetLock and GetScaleY, like for energy cell slot
|
||||||
|
|
||||||
|
CObject *objectInSlot = obj->GetSlotContainedObject(slot);
|
||||||
|
if (objectInSlot != nullptr && (objectInSlot->GetLock() || objectInSlot->GetScaleY() != 1.0f))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// The robot must be in the correct angle relative to the slot (it can't be on the other side of the object)
|
||||||
|
float angleFromObjectToRobot = Math::RotateAngle(iPos.x-worldSlotPos.x, worldSlotPos.z-iPos.z); // CW !
|
||||||
|
float objectAngleOffsetLimit = obj->GetSlotAcceptanceAngle(slot);
|
||||||
|
float objectIdealAngle = obj->GetSlotAngle(slot);
|
||||||
|
|
||||||
|
if ( Math::TestAngle(angleFromObjectToRobot, objectIdealAngle - objectAngleOffsetLimit, objectIdealAngle + objectAngleOffsetLimit) ) {
|
||||||
|
distance = fabs(Math::Distance(worldSlotPos, iPos)-TAKE_DIST);
|
||||||
|
// The robot must be close enough to the slot
|
||||||
|
if ( distance <= dLimit )
|
||||||
|
{
|
||||||
|
// The slot must be in the correct position relative to the robot (the robot must be facing towards the slot, not sideways or away)
|
||||||
|
angle = Math::RotateAngle(worldSlotPos.x-iPos.x, iPos.z-worldSlotPos.z); // CW !
|
||||||
|
if ( Math::TestAngle(angle, iAngle-aLimit, iAngle+aLimit) )
|
||||||
|
{
|
||||||
|
Math::Vector powerPos = obj->GetSlotPosition(slot);
|
||||||
|
height = powerPos.y;
|
||||||
|
pos = worldSlotPos;
|
||||||
|
slotNumOut = slot;
|
||||||
|
return pObj;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
distance = 1000000.0f;
|
distance = 1000000.0f;
|
||||||
angle = 0.0f;
|
angle = 0.0f;
|
||||||
|
@ -1090,11 +1148,15 @@ bool CTaskManip::TransporterTakeObject()
|
||||||
{
|
{
|
||||||
Math::Vector pos;
|
Math::Vector pos;
|
||||||
float dist = 0.0f, angle = 0.0f;
|
float dist = 0.0f, angle = 0.0f;
|
||||||
CObject* other = SearchOtherObject(false, pos, dist, angle, m_height);
|
int slotNum;
|
||||||
|
CObject* other = SearchOtherObject(false, pos, dist, angle, m_height, slotNum);
|
||||||
if (other == nullptr) return false;
|
if (other == nullptr) return false;
|
||||||
|
assert(slotNum != INVALID_SLOT);
|
||||||
|
CObject *cargo;
|
||||||
|
if (slotNum == ENERGY_CELL_SLOT) {
|
||||||
assert(other->Implements(ObjectInterfaceType::Powered));
|
assert(other->Implements(ObjectInterfaceType::Powered));
|
||||||
|
|
||||||
CObject* cargo = dynamic_cast<CPoweredObject*>(other)->GetPower();
|
cargo = dynamic_cast<CPoweredObject*>(other)->GetPower();
|
||||||
if (cargo == nullptr) return false; // the other does not have a battery?
|
if (cargo == nullptr) return false; // the other does not have a battery?
|
||||||
assert(cargo->Implements(ObjectInterfaceType::Transportable));
|
assert(cargo->Implements(ObjectInterfaceType::Transportable));
|
||||||
|
|
||||||
|
@ -1103,6 +1165,19 @@ bool CTaskManip::TransporterTakeObject()
|
||||||
dynamic_cast<CPoweredObject*>(other)->SetPower(nullptr);
|
dynamic_cast<CPoweredObject*>(other)->SetPower(nullptr);
|
||||||
dynamic_cast<CTransportableObject*>(cargo)->SetTransporter(m_object);
|
dynamic_cast<CTransportableObject*>(cargo)->SetTransporter(m_object);
|
||||||
dynamic_cast<CTransportableObject*>(cargo)->SetTransporterPart(3); // takes with the hand
|
dynamic_cast<CTransportableObject*>(cargo)->SetTransporterPart(3); // takes with the hand
|
||||||
|
} else {
|
||||||
|
assert(other->Implements(ObjectInterfaceType::Slotted));
|
||||||
|
|
||||||
|
cargo = dynamic_cast<CSlottedObject*>(other)->GetSlotContainedObject(slotNum);
|
||||||
|
if (cargo == nullptr) return false; // the other does not have a battery?
|
||||||
|
assert(cargo->Implements(ObjectInterfaceType::Transportable));
|
||||||
|
|
||||||
|
m_cargoType = cargo->GetType();
|
||||||
|
|
||||||
|
dynamic_cast<CSlottedObject*>(other)->SetSlotContainedObject(slotNum, nullptr);
|
||||||
|
dynamic_cast<CTransportableObject*>(cargo)->SetTransporter(m_object);
|
||||||
|
dynamic_cast<CTransportableObject*>(cargo)->SetTransporterPart(3); // takes with the hand
|
||||||
|
}
|
||||||
|
|
||||||
pos = Math::Vector(4.7f, 0.0f, 0.0f); // relative to the hand (lem4)
|
pos = Math::Vector(4.7f, 0.0f, 0.0f); // relative to the hand (lem4)
|
||||||
cargo->SetPosition(pos);
|
cargo->SetPosition(pos);
|
||||||
|
@ -1189,23 +1264,38 @@ bool CTaskManip::TransporterDeposeObject()
|
||||||
Math::Vector pos;
|
Math::Vector pos;
|
||||||
float angle = 0.0f, dist = 0.0f;
|
float angle = 0.0f, dist = 0.0f;
|
||||||
|
|
||||||
CObject* other = SearchOtherObject(false, pos, dist, angle, m_height);
|
int slotNum;
|
||||||
|
CObject* other = SearchOtherObject(false, pos, dist, angle, m_height, slotNum);
|
||||||
if (other == nullptr) return false;
|
if (other == nullptr) return false;
|
||||||
|
assert(slotNum != INVALID_SLOT);
|
||||||
|
if (slotNum == ENERGY_CELL_SLOT) {
|
||||||
assert(other->Implements(ObjectInterfaceType::Powered));
|
assert(other->Implements(ObjectInterfaceType::Powered));
|
||||||
|
|
||||||
CObject* cargo = dynamic_cast<CPoweredObject*>(other)->GetPower();
|
CObject* cargo = dynamic_cast<CPoweredObject*>(other)->GetPower();
|
||||||
if (cargo != nullptr) return false; // the other already has a battery?
|
if (cargo != nullptr) return false; // the other already has a battery?
|
||||||
|
} else {
|
||||||
|
assert(other->Implements(ObjectInterfaceType::Slotted));
|
||||||
|
CObject* cargo = dynamic_cast<CSlottedObject*>(other)->GetSlotContainedObject(slotNum);
|
||||||
|
if (cargo != nullptr) return false; // the other already has a battery?
|
||||||
|
}
|
||||||
|
|
||||||
cargo = m_object->GetCargo();
|
CObject *cargo = m_object->GetCargo();
|
||||||
if (cargo == nullptr) return false;
|
if (cargo == nullptr) return false;
|
||||||
assert(cargo->Implements(ObjectInterfaceType::Transportable));
|
assert(cargo->Implements(ObjectInterfaceType::Transportable));
|
||||||
|
|
||||||
m_cargoType = cargo->GetType();
|
m_cargoType = cargo->GetType();
|
||||||
|
|
||||||
|
if (slotNum == ENERGY_CELL_SLOT)
|
||||||
dynamic_cast<CPoweredObject*>(other)->SetPower(cargo);
|
dynamic_cast<CPoweredObject*>(other)->SetPower(cargo);
|
||||||
|
else
|
||||||
|
dynamic_cast<CSlottedObject*>(other)->SetSlotContainedObject(slotNum, cargo);
|
||||||
dynamic_cast<CTransportableObject*>(cargo)->SetTransporter(other);
|
dynamic_cast<CTransportableObject*>(cargo)->SetTransporter(other);
|
||||||
|
|
||||||
|
// TODO: isn't this wrong? PowerPosition (and SlotContainedPosition) is an object-local position.
|
||||||
|
if (slotNum == ENERGY_CELL_SLOT)
|
||||||
cargo->SetPosition(dynamic_cast<CPoweredObject*>(other)->GetPowerPosition());
|
cargo->SetPosition(dynamic_cast<CPoweredObject*>(other)->GetPowerPosition());
|
||||||
|
else
|
||||||
|
cargo->SetPosition(dynamic_cast<CSlottedObject*>(other)->GetSlotPosition(slotNum));
|
||||||
cargo->SetRotationY(0.0f);
|
cargo->SetRotationY(0.0f);
|
||||||
cargo->SetRotationX(0.0f);
|
cargo->SetRotationX(0.0f);
|
||||||
cargo->SetRotationZ(0.0f);
|
cargo->SetRotationZ(0.0f);
|
||||||
|
|
|
@ -73,7 +73,7 @@ protected:
|
||||||
CObject* SearchTakeUnderObject(Math::Vector &pos, float dLimit);
|
CObject* SearchTakeUnderObject(Math::Vector &pos, float dLimit);
|
||||||
CObject* SearchTakeFrontObject(bool bAdvance, Math::Vector &pos, float &distance, float &angle);
|
CObject* SearchTakeFrontObject(bool bAdvance, Math::Vector &pos, float &distance, float &angle);
|
||||||
CObject* SearchTakeBackObject(bool bAdvance, Math::Vector &pos, float &distance, float &angle);
|
CObject* SearchTakeBackObject(bool bAdvance, Math::Vector &pos, float &distance, float &angle);
|
||||||
CObject* SearchOtherObject(bool bAdvance, Math::Vector &pos, float &distance, float &angle, float &height);
|
CObject* SearchOtherObject(bool bAdvance, Math::Vector &pos, float &distance, float &angle, float &height, int &slotNumOut);
|
||||||
bool TransporterTakeObject();
|
bool TransporterTakeObject();
|
||||||
bool TransporterDeposeObject();
|
bool TransporterDeposeObject();
|
||||||
bool IsFreeDeposeObject(Math::Vector pos);
|
bool IsFreeDeposeObject(Math::Vector pos);
|
||||||
|
|
|
@ -2725,7 +2725,8 @@ bool CPhysics::ExploOther(ObjectType iType,
|
||||||
oType == OBJECT_NUCLEAR ||
|
oType == OBJECT_NUCLEAR ||
|
||||||
oType == OBJECT_PARA ||
|
oType == OBJECT_PARA ||
|
||||||
oType == OBJECT_SAFE ||
|
oType == OBJECT_SAFE ||
|
||||||
oType == OBJECT_HUSTON ) // building?
|
oType == OBJECT_HUSTON ||
|
||||||
|
oType == OBJECT_WATERPUMP) // building?
|
||||||
{
|
{
|
||||||
assert(pObj->Implements(ObjectInterfaceType::Damageable));
|
assert(pObj->Implements(ObjectInterfaceType::Damageable));
|
||||||
// TODO: implement "killer"?
|
// TODO: implement "killer"?
|
||||||
|
|
|
@ -115,6 +115,8 @@ const char* GetObjectName(ObjectType type)
|
||||||
if ( type == OBJECT_BEE ) return "AlienWasp";
|
if ( type == OBJECT_BEE ) return "AlienWasp";
|
||||||
if ( type == OBJECT_WORM ) return "AlienWorm";
|
if ( type == OBJECT_WORM ) return "AlienWorm";
|
||||||
if ( type == OBJECT_RUINmobilew1) return "Wreck";
|
if ( type == OBJECT_RUINmobilew1) return "Wreck";
|
||||||
|
if ( type == OBJECT_WATERPUMP ) return "WaterPump";
|
||||||
|
if ( type == OBJECT_BUCKET ) return "Bucket";
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -213,6 +215,7 @@ std::string GetHelpFilename(ObjectType type)
|
||||||
if ( type == OBJECT_BEE ) helpfile = "object/wasp";
|
if ( type == OBJECT_BEE ) helpfile = "object/wasp";
|
||||||
if ( type == OBJECT_WORM ) helpfile = "object/worm";
|
if ( type == OBJECT_WORM ) helpfile = "object/worm";
|
||||||
if ( type == OBJECT_RUINmobilew1) helpfile = "object/wreck";
|
if ( type == OBJECT_RUINmobilew1) helpfile = "object/wreck";
|
||||||
|
// XXX WaterPump
|
||||||
|
|
||||||
if (helpfile.empty())
|
if (helpfile.empty())
|
||||||
return "";
|
return "";
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
bl_info = {
|
bl_info = {
|
||||||
"name": "Colobot Model Format (.txt)",
|
"name": "Colobot Model Format (.txt)",
|
||||||
"author": "TerranovaTeam",
|
"author": "TerranovaTeam",
|
||||||
"version": (0, 0, 2),
|
"version": (0, 0, 3),
|
||||||
"blender": (2, 6, 4),
|
"blender": (2, 6, 4),
|
||||||
"location": "File > Export > Colobot (.txt)",
|
"location": "File > Export > Colobot (.txt)",
|
||||||
"description": "Export Colobot Model Format (.txt)",
|
"description": "Export Colobot Model Format (.txt)",
|
||||||
|
@ -35,7 +35,7 @@ FUZZY_TOLERANCE = 1e-5
|
||||||
|
|
||||||
class ColobotError(Exception):
|
class ColobotError(Exception):
|
||||||
"""Exception in I/O operations"""
|
"""Exception in I/O operations"""
|
||||||
def __init__(self, value):
|
def __init__(self, value, errcode=None):
|
||||||
self.value = value
|
self.value = value
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return repr(self.value)
|
return repr(self.value)
|
||||||
|
@ -199,6 +199,7 @@ def write_colobot_model(filename, model):
|
||||||
file.write('tex1 ' + t.mat.tex1 + '\n')
|
file.write('tex1 ' + t.mat.tex1 + '\n')
|
||||||
file.write('tex2 ' + t.mat.tex2 + '\n')
|
file.write('tex2 ' + t.mat.tex2 + '\n')
|
||||||
file.write('var_tex2 ' + ( 'Y' if t.mat.var_tex2 else 'N' + '\n' ) )
|
file.write('var_tex2 ' + ( 'Y' if t.mat.var_tex2 else 'N' + '\n' ) )
|
||||||
|
if model.version == 1:
|
||||||
file.write('lod_level ' + str(t.lod_level) + '\n')
|
file.write('lod_level ' + str(t.lod_level) + '\n')
|
||||||
file.write('state ' + str(t.mat.state) + '\n')
|
file.write('state ' + str(t.mat.state) + '\n')
|
||||||
file.write('\n')
|
file.write('\n')
|
||||||
|
@ -281,8 +282,8 @@ def read_colobot_model(filename):
|
||||||
if (tokens[0] != 'version'):
|
if (tokens[0] != 'version'):
|
||||||
raise ColobotError("Invalid header", "version")
|
raise ColobotError("Invalid header", "version")
|
||||||
model.version = int(tokens[1])
|
model.version = int(tokens[1])
|
||||||
if (model.version != 1):
|
if (model.version != 1 and model.version != 2):
|
||||||
raise ColobotError("Unknown model file version")
|
raise ColobotError("Unknown model file version "+str(model.version))
|
||||||
|
|
||||||
tokens, index = token_next_line(lines, index)
|
tokens, index = token_next_line(lines, index)
|
||||||
if (tokens[0] != 'total_triangles'):
|
if (tokens[0] != 'total_triangles'):
|
||||||
|
@ -329,10 +330,13 @@ def read_colobot_model(filename):
|
||||||
raise ColobotError("Invalid triangle", "var_tex2")
|
raise ColobotError("Invalid triangle", "var_tex2")
|
||||||
t.mat.var_tex2 = tokens[1] == 'Y'
|
t.mat.var_tex2 = tokens[1] == 'Y'
|
||||||
|
|
||||||
|
if (model.version == 1):
|
||||||
tokens, index = token_next_line(lines, index)
|
tokens, index = token_next_line(lines, index)
|
||||||
if (tokens[0] != 'lod_level'):
|
if (tokens[0] != 'lod_level'):
|
||||||
raise ColobotError("Invalid triangle", "lod_level")
|
raise ColobotError("Invalid triangle", "lod_level")
|
||||||
t.lod_level = int(tokens[1])
|
t.lod_level = int(tokens[1])
|
||||||
|
else:
|
||||||
|
t.lod_level = 0 # constant
|
||||||
|
|
||||||
tokens, index = token_next_line(lines, index)
|
tokens, index = token_next_line(lines, index)
|
||||||
if (tokens[0] != 'state'):
|
if (tokens[0] != 'state'):
|
||||||
|
@ -384,9 +388,9 @@ def append_obj_to_colobot_model(obj, model, scene, defaults):
|
||||||
t.mat.specular[3] = mat.specular_alpha
|
t.mat.specular[3] = mat.specular_alpha
|
||||||
|
|
||||||
if (mat.texture_slots[0] != None):
|
if (mat.texture_slots[0] != None):
|
||||||
t.tex1 = bpy.path.basename(mat.texture_slots[0].texture.image.filepath)
|
t.mat.tex1 = bpy.path.basename(mat.texture_slots[0].texture.image.filepath)
|
||||||
if (mat.texture_slots[1] != None):
|
if (mat.texture_slots[1] != None):
|
||||||
t.tex2 = bpy.path.basename(mat.texture_slots[1].texture.image.filepath)
|
t.mat.tex2 = bpy.path.basename(mat.texture_slots[1].texture.image.filepath)
|
||||||
|
|
||||||
t.var_tex2 = mat.get('var_tex2', defaults['var_tex2'])
|
t.var_tex2 = mat.get('var_tex2', defaults['var_tex2'])
|
||||||
t.state = mat.get('state', defaults['state'])
|
t.state = mat.get('state', defaults['state'])
|
||||||
|
@ -589,7 +593,7 @@ class ExportColobotDialog(bpy.types.Operator):
|
||||||
write_colobot_model(EXPORT_FILEPATH, model)
|
write_colobot_model(EXPORT_FILEPATH, model)
|
||||||
|
|
||||||
except ColobotError as e:
|
except ColobotError as e:
|
||||||
self.report({'ERROR'}, e.args.join(": "))
|
self.report({'ERROR'}, ": ".join(e.args))
|
||||||
return {'FINISHED'}
|
return {'FINISHED'}
|
||||||
|
|
||||||
self.report({'INFO'}, 'Export OK')
|
self.report({'INFO'}, 'Export OK')
|
||||||
|
@ -665,7 +669,7 @@ class ImportColobotDialog(bpy.types.Operator):
|
||||||
obj.layers = layers
|
obj.layers = layers
|
||||||
|
|
||||||
except ColobotError as e:
|
except ColobotError as e:
|
||||||
self.report({'ERROR'}, e.args.join(": "))
|
self.report({'ERROR'}, ": ".join(e.args))
|
||||||
return {'FINISHED'}
|
return {'FINISHED'}
|
||||||
|
|
||||||
self.report({'INFO'}, 'Import OK')
|
self.report({'INFO'}, 'Import OK')
|
||||||
|
|
Loading…
Reference in New Issue