khanat-opennel-code/code/ryzom/server/src/ai_service/ai_place.cpp
2017-03-15 20:43:10 +01:00

419 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 "ai_place.h"
#include "ai_place_xyr.h"
#include "ai_place_patat.h"
#include "ai_instance.h"
#include "ai_grp_fauna.h" // TODO nico : try to get rid of that dependency
//////////////////////////////////////////////////////////////////////////////
// CAIPlace //
//////////////////////////////////////////////////////////////////////////////
std::string CAIPlace::getIndexString() const
{
return getOwner()->getIndexString()+NLMISC::toString(":%u", getChildIndex());
}
//////////////////////////////////////////////////////////////////////////////
// CAIPlaceXYR //
//////////////////////////////////////////////////////////////////////////////
bool CAIPlaceXYR::atPlace(CAIEntityPhysical const* entity) const
{
return atPlace(entity->pos());
}
//////////////////////////////////////////////////////////////////////////////
// CAIPlaceXYRFauna //
//////////////////////////////////////////////////////////////////////////////
std::string CAIPlaceXYRFauna::getOneLineInfoString() const
{
std::string result = NLMISC::toString("Name = %s; Active : %s, index = %d ", getFullName().c_str(), getActive() ? "on" : "off", (int) getIndex());
if (getFlag(FLAG_SPAWN)) result +="spawn ";
if (getFlag(FLAG_EAT)) result +="food ";
if (getFlag(FLAG_REST)) result +="rest ";
if (getTimeDriven()) result += NLMISC::toString(" TIME_DRIVEN : days=%s; time=%s", getDayInterval().c_str(), getTimeInterval().c_str());
return result;
}
//////////////////////////////////////////////////////////////////////////////
// CAIPlaceFastXYR //
//////////////////////////////////////////////////////////////////////////////
bool CAIPlaceFastXYR::atPlace(CAIEntityPhysical const* entity) const
{
return atPlace(entity->pos());
}
void CAIPlaceFastXYR::display(CStringWriter& stringWriter) const
{
stringWriter.append("XYR: ("+_Pos.x().toString()
+" "
+_Pos.y().toString()
+" "+NLMISC::toString(_Pos.h())
+") Radius "
+NLMISC::toString(_Radius)
+" "
+getName());
}
uint CFaunaGenericPlace::setupFromOldName(const std::string &name)
{
uint32 stayTime;
uint placeIndex = std::numeric_limits<uint>::max();
// depending on place name setup eat/ rest/ sleep pointers
if (NLMISC::nlstricmp(name,"spawn")==0)
{
placeIndex = CGrpFauna::SPAWN_PLACE;
setIndex(0);
setReachNext(true);
setFlag(FLAG_SPAWN, true);
stayTime = CGrpFauna::refTimer(CGrpFauna::CORPSE_TIME);
}
else
if (NLMISC::nlstricmp(name,"food")==0)
{
placeIndex = CGrpFauna::EAT_PLACE;
setIndex(1);
setReachNext(true);
setFlag(FLAG_EAT, true);
stayTime = CGrpFauna::refTimer(CGrpFauna::EAT_TIME);
}
else
if (NLMISC::nlstricmp(name,"rest")==0)
{
placeIndex = CGrpFauna::REST_PLACE;
setIndex(2);
std::vector<sint32> arcs(1);
arcs[0] = 1; // can reach place 1 from place 2
setArcs(arcs);
setFlag(FLAG_REST, true);
stayTime = CGrpFauna::refTimer(CGrpFauna::REST_TIME);
}
else
{
nlwarning("Unknown fauna place type");
nlassert(0);
}
stayTime *= FAUNA_BEHAVIOR_GLOBAL_SCALE;
setMinStayTime(stayTime);
setMaxStayTime(stayTime);
return placeIndex;
}
bool CFaunaGenericPlace::getActive() const
{
if (!_TimeDriven) return _Active;
// NB : INDICES FOR DAYS are expected to start at 1!!
extern bool FAUNA_GRAPH_USES_DEBUG_TIME;
const CRyzomTime &rt = FAUNA_GRAPH_USES_DEBUG_TIME ? CTimeInterface::getRyzomDebugTime() : CTimeInterface::getRyzomTime();
std::vector<std::string> dayIntervals;
NLMISC::explode(_DayInterval, std::string(","), dayIntervals, true);
std::string season = EGSPD::CSeason::toString(rt.getRyzomSeason());
std::string weekday = WEEKDAY::toString((WEEKDAY::EWeekDay) rt.getRyzomDay());
bool found = false;
for (uint k = 0; k < dayIntervals.size(); ++k)
{
bool goodToken = false;
if (NLMISC::nlstricmp(dayIntervals[k], "always") == 0)
{
found = true;
break;
}
if (NLMISC::nlstricmp(dayIntervals[k], season) == 0)
{
found = true;
break;
}
if (EGSPD::CSeason::fromString(season) != EGSPD::CSeason::Unknown)
{
goodToken = true;
}
if (NLMISC::nlstricmp(dayIntervals[k], weekday) == 0)
{
found = true;
break;
}
if (WEEKDAY::toWeekDay(dayIntervals[k]) != WEEKDAY::UNKNOWN)
{
goodToken = true;
}
// see if this is a n interval
int startDay, endDay;
if (sscanf(dayIntervals[k].c_str(), "%d-%d", &startDay, &endDay) == 2)
{
goodToken = true;
if ((int) (rt.getRyzomDay() + 1) >= startDay && (int) (rt.getRyzomDay() + 1) <= endDay)
{
found = true;
break;
}
}
// see if this is a single day
int day;
if (sscanf(dayIntervals[k].c_str(), "%d", &day) == 1)
{
goodToken = true;
if ((int) (rt.getRyzomDay() + 1) == day)
{
found = true;
break;
}
}
if (!goodToken)
{
nlwarning("Unknwon time interval token : %s", dayIntervals[k].c_str());
}
}
if (!found) return false;
// test against time interval
// If no interval is given then assume whole day
if (_TimeInterval.empty()) return true;
std::vector<std::string> timeIntervals;
NLMISC::explode(_TimeInterval, std::string(","), timeIntervals, true);
for (uint k = 0; k < dayIntervals.size(); ++k)
{
uint startHour, endHour;
if (sscanf(timeIntervals[k].c_str(), "%d-%d", &startHour, &endHour) == 2)
{
if (startHour > endHour)
{
// reversed interval
if (rt.getRyzomTime() >= startHour || rt.getRyzomTime() <= endHour)
{
return true;
}
}
else
{
if (rt.getRyzomTime() >= startHour && rt.getRyzomTime() <= endHour)
{
return true;
}
}
}
else
{
nlwarning("Unknwon time interval token : %s", timeIntervals[k].c_str());
}
}
return false;
}
//////////////////////////////////////////////////////////////////////////////
// CAIPlaceShape //
//////////////////////////////////////////////////////////////////////////////
CAIPlaceShape::CAIPlaceShape(CPlaceOwner* owner, CAIAliasDescriptionNode* aliasDescription, bool warnOnInvalidPosition)
: CAIPlace(owner, aliasDescription), _Shape(!warnOnInvalidPosition)
{
_Shape.calcRandomPos(_MidPos);
CWorldContainer::getWorldMap().setWorldPosition(AITYPES::vp_auto, _WorldValidPos, _MidPos);
_Shape.calcRandomPos(_MidPos);
}
bool CAIPlaceShape::atPlace(CAIVector const& pos) const
{
return _Shape.contains(pos);
}
bool CAIPlaceShape::atPlace(const CAIVectorMirror &pos) const
{
return _Shape.contains(pos);
}
bool CAIPlaceShape::atPlace(CAIEntityPhysical const* entity) const
{
return atPlace(entity->pos());
}
CAIPos const& CAIPlaceShape::midPos() const
{
return _MidPos;
}
RYAI_MAP_CRUNCH::CWorldPosition const& CAIPlaceShape::worldValidPos() const
{
return _WorldValidPos;
}
float CAIPlaceShape::getRadius() const
{
// :TODO: Compute a real radius here.
return 20.f;
}
AITYPES::TVerticalPos CAIPlaceShape::getVerticalPos() const
{
return _Shape.getVerticalPos();
}
void CAIPlaceShape::getRandomPos(RYAI_MAP_CRUNCH::CWorldPosition& pos) const
{
CAIPos aiPos;
_Shape.calcRandomPos(aiPos);
CWorldContainer::getWorldMap().setWorldPosition(AITYPES::vp_auto, pos, aiPos);
}
bool CAIPlaceShape::calcRandomPos(CAIPos& pos) const
{
return _Shape.calcRandomPos(pos);
}
bool CAIPlaceShape::setPatat(AITYPES::TVerticalPos verticalPos, std::vector<CAIVector> const& points)
{
return _Shape.setPatat(verticalPos, points);
}
//////////////////////////////////////////////////////////////////////////////
// CAIPlaceIntersect //
//////////////////////////////////////////////////////////////////////////////
CAIPlaceIntersect::CAIPlaceIntersect(CPlaceOwner* owner, CAIAliasDescriptionNode* aliasDescription)
: CAIPlace(owner, aliasDescription)
{
}
bool CAIPlaceIntersect::atPlace(CAIVector const& pos) const
{
if (_Place1 && _Place2)
return _Place1->atPlace(pos) && _Place2->atPlace(pos);
if (_Place1)
return _Place1->atPlace(pos);
if (_Place2)
return _Place2->atPlace(pos);
return false;
}
bool CAIPlaceIntersect::atPlace(const CAIVectorMirror &pos) const
{
if (_Place1 && _Place2)
return _Place1->atPlace(pos) && _Place2->atPlace(pos);
if (_Place1)
return _Place1->atPlace(pos);
if (_Place2)
return _Place2->atPlace(pos);
return true;
}
bool CAIPlaceIntersect::atPlace(CAIEntityPhysical const* pos) const
{
if (_Place1 && _Place2)
return _Place1->atPlace(pos) && _Place2->atPlace(pos);
if (_Place1)
return _Place1->atPlace(pos);
if (_Place2)
return _Place2->atPlace(pos);
return true;
}
CAIPos const& CAIPlaceIntersect::midPos() const
{
nlassert(_Place1 || _Place2);
if (_Place1)
return _Place1->midPos();
if (_Place2)
return _Place2->midPos();
return _DummyMidPos;
}
RYAI_MAP_CRUNCH::CWorldPosition const& CAIPlaceIntersect::worldValidPos() const
{
nlassert(_Place1 || _Place2);
if (_Place1)
return _Place1->worldValidPos();
if (_Place2)
return _Place2->worldValidPos();
return _DummyValidPos;
}
float CAIPlaceIntersect::getRadius() const
{
nlassert(_Place1 || _Place2);
if (_Place1)
return _Place1->getRadius();
if (_Place2)
return _Place2->getRadius();
return 0.f;
}
AITYPES::TVerticalPos CAIPlaceIntersect::getVerticalPos() const
{
nlassert(_Place1 || _Place2);
if (_Place1)
return _Place1->getVerticalPos();
if (_Place2)
return _Place2->getVerticalPos();
return AITYPES::vp_auto;
}
void CAIPlaceIntersect::getRandomPos(RYAI_MAP_CRUNCH::CWorldPosition& pos) const
{
nlassert(_Place1 || _Place2);
if (_Place1)
_Place1->getRandomPos(pos);
if (_Place2)
_Place2->getRandomPos(pos);
}
bool CAIPlaceIntersect::calcRandomPos(CAIPos& pos) const
{
// if (_Place1 && _Place1->calcRandomPos(pos))
// return true;
// if (_Place2 && _Place2->calcRandomPos(pos))
// return true;
return false;
}
void CAIPlaceIntersect::setPlace1(NLMISC::CSmartPtr<CAIPlace const> const& place)
{
_Place1 = place;
}
void CAIPlaceIntersect::setPlace2(NLMISC::CSmartPtr<CAIPlace const> const& place)
{
_Place2 = place;
}
//////////////////////////////////////////////////////////////////////////////
// CAIPlaceOutpost //
//////////////////////////////////////////////////////////////////////////////
CAIPlaceOutpost::CAIPlaceOutpost(CPlaceOwner* owner, CAIAliasDescriptionNode* aliasDescription)
: CAIPlaceShape(owner, aliasDescription,false)
, _OutpostAlias(0)
{
}
bool CAIPlaceOutpost::atPlace(CAIEntityPhysical const* entity) const
{
if (_OutpostAlias!=0)
{
CMirrorPropValueRO<TYPE_IN_OUTPOST_ZONE_ALIAS> entityInOutpostAlias(TheDataset, entity->dataSetRow(), DSPropertyIN_OUTPOST_ZONE_ALIAS);
return (entityInOutpostAlias == _OutpostAlias);
}
return CAIPlaceShape::atPlace(entity);
}
void CAIPlaceOutpost::setOutpostAlias(uint32 outpostAlias)
{
_OutpostAlias = outpostAlias;
}