// Cyphesis Online RPG Server and AI Engine // Copyright (C) 2000,2001 Alistair Riddoch // // 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 2 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, write to the Free Software Foundation, // Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA #include "EntityFactory_impl.h" #include "rulesets/Character.h" #include "rulesets/Creator.h" #include "rulesets/Plant.h" #include "rulesets/Stackable.h" #include "rulesets/World.h" #include "rulesets/TransformsProperty.h" #include "rulesets/LocatedEntity.h" #include "common/debug.h" #include "common/log.h" #include "common/ScriptKit.h" #include "common/TypeNode.h" #include "common/random.h" #include #include using Atlas::Message::MapType; using Atlas::Objects::Root; using Atlas::Objects::Entity::RootEntity; using String::compose; static const bool debug_flag = false; EntityFactoryBase::EntityFactoryBase() : m_scriptFactory(0), m_parent(0) { } EntityFactoryBase::~EntityFactoryBase() { delete m_scriptFactory; } template <> LocatedEntity * EntityFactory::newEntity(const std::string & id, long intId, const Atlas::Objects::Entity::RootEntity & attributes, LocatedEntity* location) { return 0; } void EntityFactoryBase::initializeEntity(LocatedEntity& thing, const Atlas::Objects::Entity::RootEntity & attributes, LocatedEntity* location) { thing.setType(m_type); // Sort out python object if (m_scriptFactory != 0) { debug(std::cout << "Class " << m_type->name() << " has a python class" << std::endl << std::flush;); m_scriptFactory->addScript(&thing); } thing.m_location.m_loc = location; //Only apply attributes if the supplied attributes is valid. //The main use of this is when doing restoration from stored entities and we don't want to apply the default attributes directly when //the entity first is created. if (attributes.isValid()) { thing.m_location.readFromEntity(attributes); auto transProp = thing.requirePropertyClassFixed(); if (!attributes->hasAttr(TransformsProperty::property_name)) { if (thing.m_location.pos().isValid()) { //If a position is provided, but not any transforms, copy the position value into the transforms. transProp->getTranslate() = Vector3D(thing.m_location.pos()); } else { // If no position coords were provided, put it somewhere near origin, but only if there's no transform property transProp->getTranslate() = Vector3D(uniform(-8,8), uniform(-8,8), 0); } } else { transProp->set(attributes->getAttr(TransformsProperty::property_name)); } transProp->apply(&thing); if (thing.m_location.velocity().isValid()) { if (attributes.isValid() && attributes->hasAttrFlag(Atlas::Objects::Entity::VELOCITY_FLAG)) { log(ERROR, compose("EntityFactory::initializeEntity(%1, %2): " "Entity has velocity set from the attributes " "given by the creator", thing.getId(), m_type->name())); } else { log(ERROR, compose("EntityFactory::initializeEntity(%1, %2): Entity has " "velocity set from an unknown source", thing.getId(), m_type->name())); } thing.m_location.m_velocity.setValid(false); } MapType attrs = attributes->asMessage(); // Apply the attribute values thing.merge(attrs); // Then set up the default class properties for (auto& propIter : m_type->defaults()) { PropertyBase * prop = propIter.second; // If a property is in the class it won't have been installed // as setAttr() checks prop->install(&thing, propIter.first); // The property will have been applied if it has an overriden // value, so we only apply it the value is still default. if (attrs.find(propIter.first) == attrs.end()) { prop->apply(&thing); } } } } void EntityFactoryBase::addProperties() { assert(m_type != 0); m_type->addProperties(m_attributes); } void EntityFactoryBase::updateProperties() { assert(m_type != 0); m_type->updateProperties(m_attributes); for (auto& child_factory : m_children) { child_factory->m_attributes = m_attributes; MapType::const_iterator J = child_factory->m_classAttributes.begin(); MapType::const_iterator Jend = child_factory->m_classAttributes.end(); for (; J != Jend; ++J) { child_factory->m_attributes[J->first] = J->second; } child_factory->updateProperties(); } } template class EntityFactory; template class EntityFactory; template class EntityFactory; template class EntityFactory; template class EntityFactory; template class EntityFactory;