701 lines
19 KiB
C++
701 lines
19 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 "family_behavior.h"
|
|||
|
#include "game_share/fame.h"
|
|||
|
#include "continent.h"
|
|||
|
#include "ai_instance.h"
|
|||
|
#include "ai_grp_npc.h"
|
|||
|
#include "ai_grp_fauna.h"
|
|||
|
|
|||
|
#include "continent_inline.h"
|
|||
|
#include "dyn_grp_inline.h"
|
|||
|
|
|||
|
using namespace MULTI_LINE_FORMATER;
|
|||
|
|
|||
|
using namespace std;
|
|||
|
using namespace NLMISC;
|
|||
|
using namespace NLNET;
|
|||
|
using namespace AITYPES;
|
|||
|
|
|||
|
|
|||
|
|
|||
|
CFamilyBehavior::CFamilyBehavior(CCellZone *owner, const CGroupFamily *grpFamily)
|
|||
|
: CChild<CCellZone>(owner)
|
|||
|
,_BaseLevel(0)
|
|||
|
,_EffectiveLevel(0)
|
|||
|
,_PlayerEffect(0)
|
|||
|
,_CurrentLevel(0)
|
|||
|
,_TheoricalLevel(0)
|
|||
|
,_LastUpdateTime(CTimeInterface::gameCycle()+CAIS::rand32(100))
|
|||
|
,_UpdatePeriod(1)
|
|||
|
,_GrpFamily(grpFamily)
|
|||
|
{
|
|||
|
// create the family behavior
|
|||
|
_FamilyProfile = IFamilyProfile::createFamilyProfile(grpFamily->profileName(),IFamilyProfile::CtorParam(this));
|
|||
|
|
|||
|
_ManagerNpc = new CMgrNpc(this, 0, getName()+":npc_manager", "");
|
|||
|
_ManagerFauna = new CMgrFauna(this, 0, getName()+":fauna_manager", "");
|
|||
|
_ManagerNpc->spawn();
|
|||
|
_ManagerFauna->spawn();
|
|||
|
for (uint32 i=0;i<4;i++ )
|
|||
|
{
|
|||
|
_Modifier[i]=1;
|
|||
|
}
|
|||
|
// tmp nico
|
|||
|
/*
|
|||
|
nlinfo("creating new family beahviour, activities : ");
|
|||
|
nlinfo("FOOD");
|
|||
|
{
|
|||
|
std::set<NLMISC::TStringId> &props = grpFamily->getProfileProperty("food").properties();
|
|||
|
std::set<NLMISC::TStringId>::iterator it;
|
|||
|
for (it = props.begin(); it != props.end(); ++it)
|
|||
|
{
|
|||
|
nlinfo(NLMISC::CStringMapper::unmap(*it).c_str());
|
|||
|
}
|
|||
|
}
|
|||
|
nlinfo("REST");
|
|||
|
{
|
|||
|
std::set<NLMISC::TStringId> &props = grpFamily->getProfileProperty("rest").properties();
|
|||
|
std::set<NLMISC::TStringId>::iterator it;
|
|||
|
for (it = props.begin(); it != props.end(); ++it)
|
|||
|
{
|
|||
|
nlinfo(NLMISC::CStringMapper::unmap(*it).c_str());
|
|||
|
}
|
|||
|
}
|
|||
|
*/
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
std::string CFamilyBehavior::getName() const
|
|||
|
{
|
|||
|
return _GrpFamily->getName();
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
CAIInstance* CFamilyBehavior::getAIInstance() const
|
|||
|
{
|
|||
|
return getOwner()->getAIInstance();
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
const std::string &getLevelString (const uint32 &levelIndex)
|
|||
|
{
|
|||
|
static std::string s0("0-25");
|
|||
|
static std::string s1("25-50");
|
|||
|
static std::string s2("50-75");
|
|||
|
static std::string s3("75-100");
|
|||
|
static std::string invalid("InvalidLevel");
|
|||
|
|
|||
|
switch (levelIndex)
|
|||
|
{
|
|||
|
case 0:
|
|||
|
return s0;
|
|||
|
case 1:
|
|||
|
return s1;
|
|||
|
case 2:
|
|||
|
return s2;
|
|||
|
case 3:
|
|||
|
return s3;
|
|||
|
default:
|
|||
|
return invalid;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
uint32 CFamilyBehavior::energyScale (uint32 levelIndex) const
|
|||
|
{
|
|||
|
if (levelIndex==~0)
|
|||
|
levelIndex=getLevelIndex();
|
|||
|
|
|||
|
return (uint32)(_GrpFamily->levelEnergyValue(levelIndex)*(double)_Modifier[levelIndex]*(double)AITYPES::ENERGY_SCALE);
|
|||
|
}
|
|||
|
|
|||
|
void CFamilyBehavior::displayLogOld (CStringWriter &stringWriter, bool detailled)
|
|||
|
{
|
|||
|
/*
|
|||
|
string res="in "+getCellZone()->getAliasFullName();
|
|||
|
res+=", GroupFamily"+getName();
|
|||
|
res+="\t NrjLvl="+toString(getLevelIndex());
|
|||
|
res+=":"+getLevelString(getLevelIndex());
|
|||
|
res+="("+toString(effectiveLevel()/(float)ENERGY_SCALE);
|
|||
|
res+=") CurNrjScale="+toString(_CurrentLevel/(float)ENERGY_SCALE);
|
|||
|
res+=" FinalNrjScale["+getLevelString(getLevelIndex());
|
|||
|
res+="]="+toString(energyScale()/(float)ENERGY_SCALE);
|
|||
|
res+=" (NrjScale="+toString(_GrpFamily->levelEnergyValue(getLevelIndex()));
|
|||
|
res+="*Modifier="+toString(_Modifier[getLevelIndex()]);
|
|||
|
res+=") Theorical="+toString(_TheoricalLevel/(float)ENERGY_SCALE);
|
|||
|
|
|||
|
stringWriter.append(res);
|
|||
|
|
|||
|
if (!detailled)
|
|||
|
return;
|
|||
|
|
|||
|
for (uint32 i=0;i<4;i++)
|
|||
|
{
|
|||
|
stringWriter.append(" > "+getLevelString(i)+" \t: FinalEnergyScale "
|
|||
|
+toString(energyScale(i)/(float)ENERGY_SCALE)
|
|||
|
+" (EnergyScale="+toString(_GrpFamily->levelEnergyValue(i))
|
|||
|
+" Modifier="+toString(_Modifier[i])
|
|||
|
+")");
|
|||
|
}
|
|||
|
|
|||
|
*/
|
|||
|
string const& celZon = getCellZone()->getAliasFullName();
|
|||
|
string const& grpFam = getName();
|
|||
|
string const& lvlIdx = toString(getLevelIndex());
|
|||
|
string const& lvlIdxStr = getLevelString(getLevelIndex());
|
|||
|
string const& effLvl = toString(effectiveLevel()/(float)ENERGY_SCALE);
|
|||
|
string const& curLvl = toString(_CurrentLevel/(float)ENERGY_SCALE);
|
|||
|
string const& finLvl = toString(energyScale()/(float)ENERGY_SCALE);
|
|||
|
string const& teoLvl = toString(_TheoricalLevel/(float)ENERGY_SCALE);
|
|||
|
string const& lvlNrgVal = toString(_GrpFamily->levelEnergyValue(getLevelIndex()));
|
|||
|
string const& modifier = toString(_Modifier[getLevelIndex()]);
|
|||
|
|
|||
|
string log =
|
|||
|
"in "+celZon+", GroupFamily"+grpFam+"\t NrjLvl="+lvlIdx+":"+lvlIdxStr+"("+effLvl+") CurNrjScale="+curLvl
|
|||
|
+" FinalNrjScale["+lvlIdxStr+"]="+finLvl+" (NrjScale="+lvlNrgVal+"*Modifier="+modifier+") Theorical="+teoLvl;
|
|||
|
|
|||
|
stringWriter.append(log);
|
|||
|
|
|||
|
if (!detailled)
|
|||
|
return;
|
|||
|
|
|||
|
for (uint32 i=0;i<4;i++)
|
|||
|
{
|
|||
|
stringWriter.append(" > "+getLevelString(i)+" \t: FinalEnergyScale "
|
|||
|
+toString(energyScale(i)/(float)ENERGY_SCALE)
|
|||
|
+" (EnergyScale="+toString(_GrpFamily->levelEnergyValue(i))
|
|||
|
+" Modifier="+toString(_Modifier[i])
|
|||
|
+")");
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
void CFamilyBehavior::displayLogHeaders(CStringWriter& stringWriter, int index, bool detailled, std::vector<size_t> widths)
|
|||
|
{
|
|||
|
vector<string> cols(9, "");
|
|||
|
cols[0] = "CellZone";
|
|||
|
cols[1] = "GroupFamily";
|
|||
|
cols[2] = "Levels for";
|
|||
|
cols[3] = "effective";
|
|||
|
cols[4] = "current";
|
|||
|
cols[5] = "final";
|
|||
|
cols[6] = "theorical";
|
|||
|
cols[7] = "value";
|
|||
|
cols[8] = "modifier";
|
|||
|
|
|||
|
for (size_t j=0; j<cols.size(); ++j)
|
|||
|
for (size_t i=cols[j].length(); i<widths[j]; ++i)
|
|||
|
cols[j] += " ";
|
|||
|
|
|||
|
string log = string("| ")+cols[0]+" | "+cols[1]+" | "+cols[2]+" | "+cols[3]+" | "+cols[4]+" | "+cols[5]+" | "+cols[6]+" | "+cols[7]+" | "+cols[8]+" |";
|
|||
|
stringWriter.append(log);
|
|||
|
}
|
|||
|
|
|||
|
void CFamilyBehavior::displayLogLine(CStringWriter& stringWriter, int index, bool detailled, std::vector<size_t> widths)
|
|||
|
{
|
|||
|
vector<string> cols(9, "");
|
|||
|
|
|||
|
for (size_t j=0; j<cols.size(); ++j)
|
|||
|
for (size_t i=cols[j].length(); i<widths[j]; ++i)
|
|||
|
cols[j] += "-";
|
|||
|
|
|||
|
string log = string("+-")+cols[0]+"-+-"+cols[1]+"-+-"+cols[2]+"-+-"+cols[3]+"-+-"+cols[4]+"-+-"+cols[5]+"-+-"+cols[6]+"-+-"+cols[7]+"-+-"+cols[8]+"-+";
|
|||
|
stringWriter.append(log);
|
|||
|
}
|
|||
|
|
|||
|
void CFamilyBehavior::displayLog(CStringWriter& stringWriter, int index, bool detailled, std::vector<size_t> widths)
|
|||
|
{
|
|||
|
vector<string> cols(9, "");
|
|||
|
cols[0] = getCellZone()->getAliasFullName();
|
|||
|
cols[1] = getName();
|
|||
|
cols[2] = toString(getLevelIndex()) + ":" + getLevelString(getLevelIndex());
|
|||
|
cols[3] = toString(effectiveLevel()/(float)ENERGY_SCALE);
|
|||
|
cols[4] = toString(_CurrentLevel/(float)ENERGY_SCALE);
|
|||
|
cols[5] = toString(energyScale()/(float)ENERGY_SCALE);
|
|||
|
cols[6] = toString(_TheoricalLevel/(float)ENERGY_SCALE);
|
|||
|
cols[7] = toString(_GrpFamily->levelEnergyValue(getLevelIndex()));
|
|||
|
cols[8] = toString(_Modifier[getLevelIndex()]);
|
|||
|
|
|||
|
for (size_t j=0; j<cols.size(); ++j)
|
|||
|
for (size_t i=cols[j].length(); i<widths[j]; ++i)
|
|||
|
cols[j] += " ";
|
|||
|
|
|||
|
string log = string("| ")+cols[0]+" | "+cols[1]+" | "+cols[2]+" | "+cols[3]+" | "+cols[4]+" | "+cols[5]+" | "+cols[6]+" | "+cols[7]+" | "+cols[8]+" |";
|
|||
|
|
|||
|
stringWriter.append(log);
|
|||
|
/*
|
|||
|
if (!detailled)
|
|||
|
return;
|
|||
|
|
|||
|
for (uint32 i=0;i<4;i++)
|
|||
|
{
|
|||
|
stringWriter.append(" > "+getLevelString(i)+" \t: FinalEnergyScale "
|
|||
|
+toString(energyScale(i)/(float)ENERGY_SCALE)
|
|||
|
+" (EnergyScale="+toString(_GrpFamily->levelEnergyValue(i))
|
|||
|
+" Modifier="+toString(_Modifier[i])
|
|||
|
+")");
|
|||
|
}
|
|||
|
*/
|
|||
|
}
|
|||
|
|
|||
|
void CFamilyBehavior::checkLogHeadersWidths(std::vector<size_t>& widths, int index, bool detailled)
|
|||
|
{
|
|||
|
vector<string> cols(9, "");
|
|||
|
cols[0] = "CellZone";
|
|||
|
cols[1] = "GroupFamily";
|
|||
|
cols[2] = "Levels for";
|
|||
|
cols[3] = "effective";
|
|||
|
cols[4] = "current";
|
|||
|
cols[5] = "final";
|
|||
|
cols[6] = "theorical";
|
|||
|
cols[7] = "value";
|
|||
|
cols[8] = "modifier";
|
|||
|
|
|||
|
for (size_t j=0; j<cols.size(); ++j)
|
|||
|
widths[j] = std::max(widths[j], cols[j].length());
|
|||
|
}
|
|||
|
|
|||
|
void CFamilyBehavior::checkLogWidths(std::vector<size_t>& widths, int index, bool detailled)
|
|||
|
{
|
|||
|
vector<string> cols(9, "");
|
|||
|
cols[0] = getCellZone()->getAliasFullName();
|
|||
|
cols[1] = getName();
|
|||
|
cols[2] = toString(getLevelIndex()) + ":" + getLevelString(getLevelIndex());
|
|||
|
cols[3] = toString(effectiveLevel()/(float)ENERGY_SCALE);
|
|||
|
cols[4] = toString(_CurrentLevel/(float)ENERGY_SCALE);
|
|||
|
cols[5] = toString(energyScale()/(float)ENERGY_SCALE);
|
|||
|
cols[6] = toString(_TheoricalLevel/(float)ENERGY_SCALE);
|
|||
|
cols[7] = toString(_GrpFamily->levelEnergyValue(getLevelIndex()));
|
|||
|
cols[8] = toString(_Modifier[getLevelIndex()]);
|
|||
|
|
|||
|
for (size_t j=0; j<cols.size(); ++j)
|
|||
|
widths[j] = std::max(widths[j], cols[j].length());
|
|||
|
}
|
|||
|
|
|||
|
std::string CFamilyBehavior::getIndexString() const
|
|||
|
{
|
|||
|
return getOwner()->getIndexString()+toString(":fb%u", getChildIndex());
|
|||
|
}
|
|||
|
|
|||
|
std::string CFamilyBehavior::getOneLineInfoString() const
|
|||
|
{
|
|||
|
return std::string("Family behaviour '") + getName() + "'";
|
|||
|
}
|
|||
|
|
|||
|
std::vector<std::string> CFamilyBehavior::getMultiLineInfoString() const
|
|||
|
{
|
|||
|
std::vector<std::string> container;
|
|||
|
|
|||
|
|
|||
|
pushTitle(container, "CFamilyBehavior");
|
|||
|
pushEntry(container, "id=" + getIndexString());
|
|||
|
container.back() += " name=" + getName();
|
|||
|
pushFooter(container);
|
|||
|
|
|||
|
|
|||
|
return container;
|
|||
|
}
|
|||
|
|
|||
|
std::string CFamilyBehavior::getManagerIndexString(const CManager *child) const
|
|||
|
{
|
|||
|
if (child == _ManagerNpc)
|
|||
|
return getIndexString() + ":mnpc";
|
|||
|
|
|||
|
if (child == _ManagerFauna)
|
|||
|
return getIndexString() + ":mfauna";
|
|||
|
|
|||
|
return getIndexString() + ":munknown";
|
|||
|
}
|
|||
|
|
|||
|
void CFamilyBehavior::updateManagers()
|
|||
|
{
|
|||
|
// update the manager
|
|||
|
// NLMEMORY::CheckHeap(true);
|
|||
|
mgrNpc()->update();
|
|||
|
mgrFauna()->update();
|
|||
|
// NLMEMORY::CheckHeap(true);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
void CFamilyBehavior::getNpcFlags(AITYPES::CPropertySet &flags)
|
|||
|
{
|
|||
|
flags = grpFamily()->getProfileProperty(string("npc"));
|
|||
|
}
|
|||
|
|
|||
|
void CFamilyBehavior::getActivities (CPropertySet &food, CPropertySet &rest/*,bool &plante, const CGroupDesc<CGroupFamily>*const gd*/) const
|
|||
|
{
|
|||
|
food=grpFamily()->getProfileProperty(string("food"));
|
|||
|
rest=grpFamily()->getProfileProperty(string("rest"));
|
|||
|
}
|
|||
|
|
|||
|
extern CVariable<TGameCycle> DynamicMaxUpdatePeriod;
|
|||
|
void CFamilyBehavior::update(uint32 nbTicks)
|
|||
|
{
|
|||
|
// calcs _UpdatePeriod to avoid pingpong problems ..
|
|||
|
breakable
|
|||
|
{
|
|||
|
if (energyScale()==0)
|
|||
|
{
|
|||
|
_UpdatePeriod=1+DynamicMaxUpdatePeriod;
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
double delta=((double)((sint32)energyScale()-(sint32)_TheoricalLevel))/((double)energyScale());
|
|||
|
clamp(delta,0.0,1.0);
|
|||
|
delta=1.0-delta;
|
|||
|
delta*=delta; // ^3
|
|||
|
delta*=delta;
|
|||
|
delta*=delta;
|
|||
|
_UpdatePeriod=1+(uint32)(delta*DynamicMaxUpdatePeriod);
|
|||
|
}
|
|||
|
|
|||
|
CManager *Manager;
|
|||
|
{
|
|||
|
IAliasCont *cont0, *cont1;
|
|||
|
cont0 = mgrNpc()->getAliasCont(AITypeGrp);
|
|||
|
cont1 = mgrFauna()->getAliasCont(AITypeGrp);
|
|||
|
Manager=(cont0->size()>cont1->size())?NLMISC::safe_cast<CManager*>(mgrNpc()):NLMISC::safe_cast<CManager*>(mgrFauna());
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
// TODO : reactivate group deletion
|
|||
|
// delete group that are dead
|
|||
|
while (!_GroupToDelete.empty())
|
|||
|
{
|
|||
|
// NLMEMORY::CheckHeap(true);
|
|||
|
CGroup *const grp=(CGroup*)_GroupToDelete.back();
|
|||
|
_GroupToDelete.pop_back();
|
|||
|
grp->getManager().getAliasCont(AITypeGrp)->removeChildByIndex(grp->getChildIndex());
|
|||
|
// NLMEMORY::CheckHeap(true);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
// check to despawn groups that are no more valid in current energy or season
|
|||
|
breakable
|
|||
|
{
|
|||
|
H_AUTO(FamilyDespawnGroup)
|
|||
|
|
|||
|
const IGroupDesc *gd = NULL;
|
|||
|
CGroup *grp=NULL;
|
|||
|
|
|||
|
breakable
|
|||
|
{
|
|||
|
const uint32 nbGroups=Manager->groups().size();
|
|||
|
|
|||
|
if (nbGroups==0)
|
|||
|
break;
|
|||
|
|
|||
|
grp = Manager->getGroup(CAIS::rand16(nbGroups));
|
|||
|
if (!grp)
|
|||
|
break;
|
|||
|
|
|||
|
CDynGrpBase *const grpDynBase=grp->getGrpDynBase();
|
|||
|
#if !FINAL_VERSION
|
|||
|
nlassert(grpDynBase!=NULL);
|
|||
|
#endif
|
|||
|
if ( grpDynBase
|
|||
|
|| grpDynBase->getDiscardable())
|
|||
|
gd=grpDynBase->getGroupDesc();
|
|||
|
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
if ( !grp
|
|||
|
|| !gd
|
|||
|
|| !grp->isSpawned())
|
|||
|
break;
|
|||
|
|
|||
|
// rajouter un test sur la validit<69> du groupe par rapport aux flags des zones occup<75>es pour savoir s'il faut le despawner .. :)
|
|||
|
|
|||
|
bool alreadyDespawned=false;
|
|||
|
breakable
|
|||
|
{
|
|||
|
CGrpFauna *const grpFauna=dynamic_cast<CGrpFauna*>(grp);
|
|||
|
if (!grpFauna)
|
|||
|
break;
|
|||
|
|
|||
|
const CFaunaZone *faunaZone;
|
|||
|
CPropertySet food, rest;
|
|||
|
// bool plante;
|
|||
|
getActivities (food, rest/*, plante, gd*/);
|
|||
|
// {
|
|||
|
//#if !FINAL_VERSION
|
|||
|
// nlwarning("there is a problem with getActivities for %s", gd->getFullName().c_str());
|
|||
|
//#endif
|
|||
|
// break;
|
|||
|
// }
|
|||
|
|
|||
|
const CAIPlace *place=grpFauna->places()[CGrpFauna::EAT_PLACE];
|
|||
|
place=NLMISC::safe_cast<const CAIRefPlaceXYR *>(place)->getZone();
|
|||
|
faunaZone=NLMISC::safe_cast<const CFaunaZone *>(place);
|
|||
|
if (!faunaZone)
|
|||
|
{
|
|||
|
#if !FINAL_VERSION
|
|||
|
nlassert(faunaZone);
|
|||
|
#endif
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
if (!faunaZone->haveActivity(food))
|
|||
|
{
|
|||
|
grp->getSpawnObj()->despawnBots(true); // not ok, despawn this group ..
|
|||
|
alreadyDespawned=true;
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
place=grpFauna->places()[CGrpFauna::EAT_PLACE];
|
|||
|
place=NLMISC::safe_cast<const CAIRefPlaceXYR *>(place)->getZone();
|
|||
|
faunaZone=NLMISC::safe_cast<const CFaunaZone *>(place);
|
|||
|
if (!faunaZone)
|
|||
|
{
|
|||
|
#if !FINAL_VERSION
|
|||
|
nlassert(faunaZone);
|
|||
|
#endif
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
if (!faunaZone->haveActivity(rest))
|
|||
|
{
|
|||
|
grp->getSpawnObj()->despawnBots(true); // not ok, despawn this group ..
|
|||
|
alreadyDespawned=true;
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
// deals with npcs dyn groups
|
|||
|
breakable
|
|||
|
{
|
|||
|
CGroupNpc *const grpNpc=dynamic_cast<CGroupNpc *>(grp);
|
|||
|
if (!grpNpc)
|
|||
|
break;
|
|||
|
|
|||
|
const CNpcZone *npcZone = grpNpc->getSpawnZone();
|
|||
|
CPropertySet flags;
|
|||
|
getNpcFlags(flags);
|
|||
|
|
|||
|
if (!npcZone || !npcZone->properties().containsAllOf(flags))
|
|||
|
{
|
|||
|
// must despawn group
|
|||
|
grp->getSpawnObj()->despawnBots(true); // not ok, despawn this group ..
|
|||
|
alreadyDespawned=true;
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
if (alreadyDespawned)
|
|||
|
break;
|
|||
|
|
|||
|
if (gd->getWeightForEnergy(getLevelIndex())!=0)
|
|||
|
break;
|
|||
|
|
|||
|
const EGSPD::CSeason::TSeason season=CTimeInterface::season();
|
|||
|
|
|||
|
if ( season<EGSPD::CSeason::Invalid // et si on est <20> une saison valide ..
|
|||
|
&& gd->isValidForSeason(season) )
|
|||
|
break; // pas de raison de despawner.
|
|||
|
|
|||
|
if (!alreadyDespawned)
|
|||
|
grp->getSpawnObj()->despawnBots(false); // not ok, despawn this group ..
|
|||
|
}
|
|||
|
|
|||
|
// check for spawning new group to equilibrate energy level.
|
|||
|
breakable
|
|||
|
{
|
|||
|
H_AUTO(FamilyGroup)
|
|||
|
if (_TheoricalLevel< energyScale())
|
|||
|
{
|
|||
|
H_AUTO(FamilyGroupeSpawn)
|
|||
|
// need to spawn some group ?
|
|||
|
if (_FamilyProfile)
|
|||
|
_FamilyProfile->spawnGroup();
|
|||
|
|
|||
|
break;
|
|||
|
}
|
|||
|
// or check for despawning
|
|||
|
|
|||
|
if (_TheoricalLevel <= (energyScale()+(uint32)(0.01*(double)ENERGY_SCALE)))
|
|||
|
break;
|
|||
|
|
|||
|
CGroup *grp=NULL;
|
|||
|
const IGroupDesc *gd = NULL;
|
|||
|
// need to despawn some group ?
|
|||
|
|
|||
|
{
|
|||
|
H_AUTO(FamilyGroupDespawn)
|
|||
|
|
|||
|
// try to despawn some group in the manager
|
|||
|
const uint32 start = CAIS::rand16(Manager->groups().size());
|
|||
|
|
|||
|
grp = Manager->getGroup(start);
|
|||
|
if (!grp)
|
|||
|
grp = Manager->groups().getNextValidChild(grp);
|
|||
|
|
|||
|
if (grp)
|
|||
|
{
|
|||
|
CDynGrpBase *const grpDynBase=grp->getGrpDynBase();
|
|||
|
if ( grpDynBase
|
|||
|
&& grp->getSpawnObj()
|
|||
|
&& grpDynBase->getDiscardable())
|
|||
|
{
|
|||
|
gd=grpDynBase->getGroupDesc();
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
Manager->groups().setChildSize(start); // There's no group after start, so we can resize the group.
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
if (grp && gd)
|
|||
|
{
|
|||
|
H_AUTO(FamilyGroupDespawn)
|
|||
|
|
|||
|
if ((_TheoricalLevel - gd->groupEnergyValue()) >= energyScale())
|
|||
|
{
|
|||
|
// ok, we can despawn this group
|
|||
|
grp->despawnBots(false);
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
{
|
|||
|
H_AUTO(FamilyProfileUpdate);
|
|||
|
CFollowPathContext fpcFamilyProfileUpdate("FamilyProfileUpdate");
|
|||
|
|
|||
|
// update the family profile (if any)
|
|||
|
if (_FamilyProfile)
|
|||
|
_FamilyProfile->update();
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
void CFamilyBehavior::fillOutpostNames(std::vector<NLMISC::TStringId> outpostNames)
|
|||
|
{
|
|||
|
if (_FamilyProfile)
|
|||
|
_FamilyProfile->fillOutpostNames(outpostNames);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
void CFamilyBehavior::outpostAdd(NLMISC::TStringId outpostName)
|
|||
|
{
|
|||
|
if (_FamilyProfile)
|
|||
|
_FamilyProfile->outpostAdd(outpostName);
|
|||
|
}
|
|||
|
void CFamilyBehavior::outpostRemove(NLMISC::TStringId outpostName)
|
|||
|
{
|
|||
|
if (_FamilyProfile)
|
|||
|
_FamilyProfile->outpostRemove(outpostName);
|
|||
|
}
|
|||
|
|
|||
|
void CFamilyBehavior::outpostEvent(NLMISC::TStringId outpostName, ZCSTATE::TZcState state)
|
|||
|
{
|
|||
|
if (_FamilyProfile)
|
|||
|
_FamilyProfile->outpostEvent(outpostName,state);
|
|||
|
}
|
|||
|
|
|||
|
void CFamilyBehavior::spawnBoss(NLMISC::TStringId outpostName)
|
|||
|
{
|
|||
|
if (_FamilyProfile)
|
|||
|
_FamilyProfile->spawnBoss(outpostName);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
void CFamilyBehavior::groupDead(CGroup *grp)
|
|||
|
{
|
|||
|
#ifdef NL_DEBUG
|
|||
|
for (uint32 i=0;i<_GroupToDelete.size();i++)
|
|||
|
{
|
|||
|
nlassert(_GroupToDelete[i].ptr() != grp);
|
|||
|
}
|
|||
|
#endif
|
|||
|
// ok, we can delete this group
|
|||
|
_GroupToDelete.push_back(grp);
|
|||
|
}
|
|||
|
|
|||
|
void CFamilyBehavior::addEnergy (uint32 energy)
|
|||
|
{
|
|||
|
_CurrentLevel += energy;
|
|||
|
}
|
|||
|
|
|||
|
void CFamilyBehavior::removeEnergy (uint32 energy)
|
|||
|
{
|
|||
|
#ifdef NL_DEBUG
|
|||
|
nlassert(_CurrentLevel>=energy);
|
|||
|
#endif
|
|||
|
_CurrentLevel -= energy;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
void CFamilyBehavior::serviceEvent (const CServiceEvent &info)
|
|||
|
{
|
|||
|
mgrNpc()->serviceEvent (info);
|
|||
|
mgrFauna()->serviceEvent (info);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
CGroupNpc *CFamilyBehavior::createNpcGroup(const CNpcZone *const zone, const CGroupDesc<CGroupFamily> *const groupDesc)
|
|||
|
{
|
|||
|
// const TPopulationFamily &family=getFamily()
|
|||
|
// if ( family.FamilyTag == family_fauna_herbivore
|
|||
|
// || family.FamilyTag == family_fauna_carnivore
|
|||
|
// || family.FamilyTag == family_flora
|
|||
|
// || family.FamilyTag == family_kitin
|
|||
|
// || family.FamilyTag == family_kitin_invasion
|
|||
|
// || family.FamilyTag == family_degen
|
|||
|
// || family.FamilyTag == family_goo )
|
|||
|
// {
|
|||
|
// nlwarning("CRegion::createGroup can't create a npc group for family '%s', energy level %f in region '%s'", family.getFamilyName().c_str(), effectiveLevel(), getOwner()->getOwner()->getAliasFullName().c_str());
|
|||
|
// return NULL;
|
|||
|
// }
|
|||
|
|
|||
|
CGroupNpc *grp=groupDesc->createNpcGroup (mgrNpc(), zone->midPos());
|
|||
|
|
|||
|
if (grp)
|
|||
|
{
|
|||
|
grp->initDynGrp (groupDesc, this);
|
|||
|
grp->setSpawnZone(zone);
|
|||
|
}
|
|||
|
return grp;
|
|||
|
}
|
|||
|
|
|||
|
bool CFamilyBehavior::spawn()
|
|||
|
{
|
|||
|
// Spawn dyn NPCs
|
|||
|
_ManagerNpc->spawn();
|
|||
|
// Spawn dyn fauna
|
|||
|
_ManagerFauna->spawn();
|
|||
|
// We should check individual errors, but fake success here :)
|
|||
|
return true;
|
|||
|
}
|
|||
|
|
|||
|
bool CFamilyBehavior::despawn()
|
|||
|
{
|
|||
|
// Despawn dyn NPCs
|
|||
|
_ManagerNpc->despawnMgr();
|
|||
|
// Despawn dyn fauna
|
|||
|
_ManagerFauna->despawnMgr();
|
|||
|
// We should check individual errors, but fake success here :)
|
|||
|
return true;
|
|||
|
}
|