462 lines
12 KiB
C++
462 lines
12 KiB
C++
|
// Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
|
||
|
// Copyright (C) 2010 Winch Gate Property Limited
|
||
|
//
|
||
|
// This program is free software: you can redistribute it and/or modify
|
||
|
// it under the terms of the GNU Affero 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 Affero General Public License for more details.
|
||
|
//
|
||
|
// You should have received a copy of the GNU Affero General Public License
|
||
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||
|
|
||
|
|
||
|
|
||
|
#include "stdpch.h"
|
||
|
|
||
|
#include "reynolds_manager.h"
|
||
|
|
||
|
#include "nel/georges/u_form_loader.h"
|
||
|
#include "nel/georges/load_form.h"
|
||
|
|
||
|
using namespace std;
|
||
|
using namespace NLMISC;
|
||
|
using namespace NLPACS;
|
||
|
using namespace NLGEORGES;
|
||
|
|
||
|
|
||
|
/*
|
||
|
* Manager variables
|
||
|
*/
|
||
|
|
||
|
// Continents
|
||
|
CContinentContainer CReynoldsManager::_Continents;
|
||
|
|
||
|
// Track Map, all tracks referenced, held by a simple pointer so when no one references a track, it is deleted
|
||
|
CReynoldsManager::TTrackMap CReynoldsManager::_TrackMap;
|
||
|
|
||
|
// Controlled Track Map, only controlled tracks, held by a smart pointer
|
||
|
CReynoldsManager::TControlledTrackMap CReynoldsManager::_ControlledTrackMap;
|
||
|
|
||
|
// Command interface
|
||
|
CReynoldsManager::ICommandInterface *CReynoldsManager::_CommandInterface = NULL;
|
||
|
|
||
|
// User init callback
|
||
|
CReynoldsManager::TUserCallback CReynoldsManager::_UserInitCallback = NULL;
|
||
|
|
||
|
// User motion callback
|
||
|
CReynoldsManager::TUserMotionCallback CReynoldsManager::_UserMotionCallback = NULL;
|
||
|
|
||
|
// User release callback
|
||
|
CReynoldsManager::TUserCallback CReynoldsManager::_UserReleaseCallback = NULL;
|
||
|
|
||
|
// Georges sheets
|
||
|
map<CSheetId, CTrack::CSheet> CReynoldsManager::_Sheets;
|
||
|
|
||
|
// Sheets initialised ?
|
||
|
bool CReynoldsManager::_Initialised;
|
||
|
|
||
|
// Current internal cycle
|
||
|
uint32 CReynoldsManager::_Cycle;
|
||
|
|
||
|
/*
|
||
|
* Manager methods
|
||
|
*/
|
||
|
|
||
|
|
||
|
// ------------------------------------
|
||
|
// Constructor
|
||
|
CReynoldsManager::CReynoldsManager()
|
||
|
{
|
||
|
nlerror("CReynoldsManager: static library, must not be instanciated !");
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
// ------------------------------------
|
||
|
// Init
|
||
|
void CReynoldsManager::init(const std::string &packSheetFile)
|
||
|
{
|
||
|
_Continents.init(100, 100, 8.0, 1);
|
||
|
|
||
|
initSheets(packSheetFile);
|
||
|
|
||
|
_Cycle = 0;
|
||
|
}
|
||
|
|
||
|
// ------------------------------------
|
||
|
// Update
|
||
|
void CReynoldsManager::update(double dt)
|
||
|
{
|
||
|
TControlledTrackMap::iterator it;
|
||
|
for (it=_ControlledTrackMap.begin(); it!=_ControlledTrackMap.end(); ++it)
|
||
|
{
|
||
|
CTrack *track = (CTrack*)((*it).second);
|
||
|
track->update(dt);
|
||
|
}
|
||
|
|
||
|
++_Cycle;
|
||
|
}
|
||
|
|
||
|
// ------------------------------------
|
||
|
// Release
|
||
|
void CReynoldsManager::release()
|
||
|
{
|
||
|
_Continents.clear();
|
||
|
|
||
|
_ControlledTrackMap.clear();
|
||
|
|
||
|
if (!_TrackMap.empty())
|
||
|
{
|
||
|
nlwarning("ReynoldsLib:CReynoldsManager:release(): TrackMap not empty at release !!");
|
||
|
|
||
|
TTrackMap::iterator it;
|
||
|
for (it=_TrackMap.begin(); it!=_TrackMap.end(); ++it)
|
||
|
delete (*it).second;
|
||
|
|
||
|
_TrackMap.clear();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
// ------------------------------------
|
||
|
// Load continent
|
||
|
void CReynoldsManager::loadContinent(const std::string &name, const std::string &file, sint index)
|
||
|
{
|
||
|
_Continents.loadContinent(name, file, index);
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
// ------------------------------------
|
||
|
// Create Track
|
||
|
CTrack *CReynoldsManager::createTrack(const CEntityId &entity)
|
||
|
{
|
||
|
// look for the target, and create a new track if not found
|
||
|
TTrackMap::iterator itt = _TrackMap.find(entity);
|
||
|
if (itt == _TrackMap.end())
|
||
|
{
|
||
|
CTrack *track = new CTrack();
|
||
|
pair<TTrackMap::iterator, bool> res = _TrackMap.insert(TTrackMap::value_type(entity, track));
|
||
|
itt = res.first;
|
||
|
|
||
|
requestSheet(entity);
|
||
|
}
|
||
|
return (*itt).second;
|
||
|
}
|
||
|
|
||
|
// ------------------------------------
|
||
|
// Remove Track from map
|
||
|
void CReynoldsManager::removeTrackFromMap(const CEntityId &entity)
|
||
|
{
|
||
|
_TrackMap.erase(entity);
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
// ------------------------------------
|
||
|
// Follow
|
||
|
void CReynoldsManager::follow(const NLMISC::CEntityId &entity, const NLMISC::CEntityId &target)
|
||
|
{
|
||
|
// look for the track, and create a new one if not found -- in both maps
|
||
|
CTrack *etrack = createTrack(entity);
|
||
|
|
||
|
TControlledTrackMap::iterator ite = _ControlledTrackMap.find(entity);
|
||
|
if (ite == _ControlledTrackMap.end())
|
||
|
_ControlledTrackMap.insert(TControlledTrackMap::value_type(entity, etrack));
|
||
|
|
||
|
// look for the target, and create a new track if not found
|
||
|
CTrack *ttrack = createTrack(target);
|
||
|
|
||
|
nldebug("ReynoldsLib:CReynoldsManager:follow(): %s now follows %s", entity.toString().c_str(), target.toString().c_str());
|
||
|
|
||
|
// let entity follow the target
|
||
|
etrack->follow(ttrack);
|
||
|
}
|
||
|
|
||
|
// ------------------------------------
|
||
|
// Go to
|
||
|
void CReynoldsManager::goTo(const NLMISC::CEntityId &entity, const NLMISC::CVectorD &position)
|
||
|
{
|
||
|
// look for the track, and create a new one if not found -- in both maps
|
||
|
CTrack *etrack = createTrack(entity);
|
||
|
|
||
|
TControlledTrackMap::iterator ite = _ControlledTrackMap.find(entity);
|
||
|
if (ite == _ControlledTrackMap.end())
|
||
|
_ControlledTrackMap.insert(TControlledTrackMap::value_type(entity, etrack));
|
||
|
|
||
|
// create a fake track for point position
|
||
|
static uint i = 0;
|
||
|
CEntityId id(0, i++, 0, 0);
|
||
|
CTrack *pointTo = createTrack(id);
|
||
|
pointTo->setStatic();
|
||
|
pointTo->setId(id, CSheetId::Unknown);
|
||
|
pointTo->setPosition(position, 0.0f);
|
||
|
|
||
|
nldebug("ReynoldsLib:CReynoldsManager:goTo(): %s now goes to (%.1f,%.1f)", entity.toString().c_str(), position.x, position.y);
|
||
|
|
||
|
// let entity follow the target
|
||
|
etrack->follow(pointTo);
|
||
|
}
|
||
|
|
||
|
// ------------------------------------
|
||
|
// Stop
|
||
|
void CReynoldsManager::leaveMove(const NLMISC::CEntityId &entity)
|
||
|
{
|
||
|
TControlledTrackMap::iterator ite = _ControlledTrackMap.find(entity);
|
||
|
if (ite == _ControlledTrackMap.end())
|
||
|
{
|
||
|
nlwarning("ReynoldsLib:CReynoldsManager:leaveMove(): undefined entity %s", entity.toString().c_str());
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
nldebug("ReynoldsLib:CReynoldsManager:leaveMove(): %s control left", entity.toString().c_str());
|
||
|
|
||
|
(*ite).second->leave();
|
||
|
_ControlledTrackMap.erase(ite);
|
||
|
}
|
||
|
|
||
|
// ------------------------------------
|
||
|
// Destroy
|
||
|
void CReynoldsManager::destroy(const NLMISC::CEntityId &entity)
|
||
|
{
|
||
|
CTrack *track = getTrack(entity);
|
||
|
if (track != NULL)
|
||
|
track->forceRelease();
|
||
|
|
||
|
if (track != NULL && track->hasControlOwned())
|
||
|
track->leave();
|
||
|
|
||
|
_ControlledTrackMap.erase(entity);
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
// ------------------------------------
|
||
|
// Request Sheet
|
||
|
void CReynoldsManager::requestSheet(const NLMISC::CEntityId &entity)
|
||
|
{
|
||
|
if (!checkInterface())
|
||
|
return;
|
||
|
|
||
|
_CommandInterface->requestSheet(entity);
|
||
|
}
|
||
|
|
||
|
// ------------------------------------
|
||
|
// Request Position
|
||
|
void CReynoldsManager::requestPosition(const NLMISC::CEntityId &entity)
|
||
|
{
|
||
|
if (!checkInterface())
|
||
|
return;
|
||
|
|
||
|
_CommandInterface->requestPosition(entity);
|
||
|
}
|
||
|
|
||
|
// ------------------------------------
|
||
|
// Request Position Updates
|
||
|
void CReynoldsManager::requestPositionUpdates(const NLMISC::CEntityId &entity)
|
||
|
{
|
||
|
if (!checkInterface())
|
||
|
return;
|
||
|
|
||
|
_CommandInterface->requestPositionUpdates(entity);
|
||
|
}
|
||
|
|
||
|
// ------------------------------------
|
||
|
// Unrequest Position Updates
|
||
|
void CReynoldsManager::unrequestPositionUpdates(const NLMISC::CEntityId &entity)
|
||
|
{
|
||
|
if (!checkInterface())
|
||
|
return;
|
||
|
|
||
|
_CommandInterface->unrequestPositionUpdates(entity);
|
||
|
}
|
||
|
|
||
|
// ------------------------------------
|
||
|
// Request Vision
|
||
|
void CReynoldsManager::requestVision(const NLMISC::CEntityId &entity)
|
||
|
{
|
||
|
if (!checkInterface())
|
||
|
return;
|
||
|
|
||
|
_CommandInterface->requestVision(entity);
|
||
|
}
|
||
|
|
||
|
// ------------------------------------
|
||
|
// Unrequest Vision
|
||
|
void CReynoldsManager::unrequestVision(const NLMISC::CEntityId &entity)
|
||
|
{
|
||
|
if (!checkInterface())
|
||
|
return;
|
||
|
|
||
|
_CommandInterface->unrequestVision(entity);
|
||
|
}
|
||
|
|
||
|
|
||
|
// ------------------------------------
|
||
|
// Updated position
|
||
|
void CReynoldsManager::updatedPosition(const CEntityId &entity, const CVectorD &position, float heading)
|
||
|
{
|
||
|
if (_CommandInterface != NULL)
|
||
|
_CommandInterface->updatePosition(entity, position, heading);
|
||
|
}
|
||
|
|
||
|
// ------------------------------------
|
||
|
// Updated state
|
||
|
void CReynoldsManager::stateChanged(const CEntityId &entity, CTrackBase::TTrackState state)
|
||
|
{
|
||
|
if (_CommandInterface != NULL)
|
||
|
_CommandInterface->stateChanged(entity, state);
|
||
|
}
|
||
|
|
||
|
|
||
|
// ------------------------------------
|
||
|
// TrackStop
|
||
|
void CReynoldsManager::trackStop(CTrack *track)
|
||
|
{
|
||
|
if (checkInterface())
|
||
|
_CommandInterface->stopTrack(track->getId());
|
||
|
|
||
|
// remove track from controlled tracks
|
||
|
_ControlledTrackMap.erase(track->getId());
|
||
|
}
|
||
|
|
||
|
|
||
|
// ------------------------------------
|
||
|
// Create Move primitive
|
||
|
void CReynoldsManager::createMovePrimitive(const NLMISC::CVectorD &pos, NLPACS::UMovePrimitive *&primitive, NLPACS::UMoveContainer *&container)
|
||
|
{
|
||
|
primitive = NULL;
|
||
|
container = NULL;
|
||
|
|
||
|
uint8 continent = _Continents.findContinent(pos);
|
||
|
if (continent == -1)
|
||
|
{
|
||
|
nlwarning("ReynoldsLib:CReynoldsManager:createMovePrimitive(): unable to create move primitive");
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
container = _Continents.getMoveContainer(continent);
|
||
|
primitive = container->addNonCollisionablePrimitive();
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
// ------------------------------------
|
||
|
// Set Sheet
|
||
|
void CReynoldsManager::setSheet(const NLMISC::CEntityId &id, const NLMISC::CSheetId &sheet)
|
||
|
{
|
||
|
CTrack *track = getTrack(id);
|
||
|
if (track == NULL)
|
||
|
{
|
||
|
nlwarning("ReynoldsLib:CReynoldsManager:setSheet(): Track %s not found", id.toString().c_str());
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if (track->hasId())
|
||
|
{
|
||
|
nlwarning("ReynoldsLib:CReynoldsManager:setSheet(): Track %s already has an Id", id.toString().c_str());
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
track->setId(id, sheet);
|
||
|
}
|
||
|
|
||
|
// ------------------------------------
|
||
|
// Set Position
|
||
|
void CReynoldsManager::setPosition(const NLMISC::CEntityId &id, const NLMISC::CVectorD &position, float heading)
|
||
|
{
|
||
|
CTrack *track = getTrack(id);
|
||
|
if (track == NULL)
|
||
|
{
|
||
|
nlwarning("ReynoldsLib:CReynoldsManager:setPosition(): Track %s not found", id.toString().c_str());
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
track->setPosition(position, heading);
|
||
|
}
|
||
|
|
||
|
// ------------------------------------
|
||
|
// Set Vision
|
||
|
void CReynoldsManager::setVision(const NLMISC::CEntityId &id, const std::vector<NLMISC::CEntityId> &in, const std::vector<NLMISC::CEntityId> &out)
|
||
|
{
|
||
|
CTrack *track = getTrack(id);
|
||
|
if (track == NULL)
|
||
|
{
|
||
|
nlwarning("ReynoldsLib:CReynoldsManager:setVision(): Track %s not found", id.toString().c_str());
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
track->updateVision(in, out);
|
||
|
}
|
||
|
|
||
|
// ------------------------------------
|
||
|
// Set Vision
|
||
|
void CReynoldsManager::setVision(const NLMISC::CEntityId &id, const std::vector<NLMISC::CEntityId> &vision)
|
||
|
{
|
||
|
CTrack *track = getTrack(id);
|
||
|
if (track == NULL)
|
||
|
{
|
||
|
nlwarning("ReynoldsLib:CReynoldsManager:setVision(): Track %s not found", id.toString().c_str());
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
track->updateVision(vision);
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
//-------------------------------------------------------------------------
|
||
|
// Init Sheets
|
||
|
void CReynoldsManager::initSheets(const std::string &packSheetFile)
|
||
|
{
|
||
|
if (_Initialised)
|
||
|
return;
|
||
|
|
||
|
std::vector<std::string> filters;
|
||
|
filters.push_back("creature");
|
||
|
filters.push_back("player");
|
||
|
|
||
|
loadForm(filters, packSheetFile, _Sheets);
|
||
|
|
||
|
_Initialised=true;
|
||
|
}
|
||
|
|
||
|
|
||
|
//-------------------------------------------------------------------------
|
||
|
// Lookup Sheet
|
||
|
const CTrack::CSheet *CReynoldsManager::lookup(const CSheetId &id)
|
||
|
{
|
||
|
nlassert(_Initialised);
|
||
|
|
||
|
// setup an iterator and lookup the sheet id in the map
|
||
|
std::map<CSheetId, CTrack::CSheet>::iterator it;
|
||
|
it=_Sheets.find(id);
|
||
|
|
||
|
// if we found a valid entry return a pointer to the creature record otherwise 0
|
||
|
if (it != _Sheets.end())
|
||
|
return &((*it).second);
|
||
|
else
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
|