From 72d29ef8f63a18f1cf3d7190cf11239f93d9e104 Mon Sep 17 00:00:00 2001 From: Ulukyn Date: Fri, 28 Aug 2020 12:22:48 +0200 Subject: [PATCH] Merge branch 'fixes' --- ryzom/server/src/ai_service/ai_bot_npc.cpp | 210 ++++++++++-------- ryzom/server/src/ai_service/ai_bot_npc.h | 124 ++++++----- ryzom/server/src/ai_service/ai_instance.cpp | 42 ++-- ryzom/server/src/ai_service/ai_instance.h | 71 +++--- .../server/src/ai_service/ai_profile_npc.cpp | 18 +- ryzom/server/src/ai_service/ai_vision.h | 50 ++--- ryzom/server/src/ai_service/messages.cpp | 81 +++---- .../server/src/ai_service/state_instance.cpp | 72 +++--- .../src/input_output_service/chat_manager.cpp | 22 +- 9 files changed, 374 insertions(+), 316 deletions(-) diff --git a/ryzom/server/src/ai_service/ai_bot_npc.cpp b/ryzom/server/src/ai_service/ai_bot_npc.cpp index f6389faea..7f06d37d9 100644 --- a/ryzom/server/src/ai_service/ai_bot_npc.cpp +++ b/ryzom/server/src/ai_service/ai_bot_npc.cpp @@ -42,6 +42,8 @@ using namespace RYAI_MAP_CRUNCH; static bool VerboseLog = false; #define LOG if (!VerboseLog) { } else nlinfo +extern CAIVector randomPos(double dispersionRadius); + ////////////////////////////////////////////////////////////////////////////// // CSpawnBotNpc // ////////////////////////////////////////////////////////////////////////////// @@ -64,14 +66,14 @@ void CSpawnBotNpc::sendInfoToEGS() const { if (!EGSHasMirrorReady) return; - + CSpawnBot::sendInfoToEGS(); TGenNpcDescMsgImp msg; msg.setEntityIndex(dataSetRow()); - + getPersistent().fillDescriptionMsg(msg); - + msg.setChat(_CurrentChatProfile); msg.send("EGS"); } @@ -86,7 +88,7 @@ void CSpawnBotNpc::processEvent(CCombatInterface::CEvent const& event) // no self aggro. if (event._targetRow==event._originatorRow) return; - + if ((event._nature==ACTNATURE::FIGHT || event._nature==ACTNATURE::OFFENSIVE_MAGIC) && !getPersistent().ignoreOffensiveActions()) { float aggro = event._weight; @@ -116,7 +118,7 @@ void CSpawnBotNpc::processEvent(CCombatInterface::CEvent const& event) { ++AISStat::BotTotalUpdCtr; ++AISStat::BotNpcUpdCtr; - + { H_AUTO(AIHpTrig); // Fix for HP triggers @@ -136,7 +138,7 @@ void CSpawnBotNpc::processEvent(CCombatInterface::CEvent const& event) _OldHpPercentage = getPhysical().hpPercentage(); } } - + // Bot chat and dyn chat override AI profile unless fighting // The directing adjustment is done client-slide (each player sees the NPC facing him) if (!getActiveChats().empty()) @@ -156,10 +158,10 @@ void CSpawnBotNpc::processEvent(CCombatInterface::CEvent const& event) if (sp) { sp->getPersistent().notifyStopNpcControl(); - } + } + + _PlayerController = NULL; - _PlayerController = NULL; - } if (_PlayerController == NULL) @@ -186,16 +188,16 @@ void CSpawnBotNpc::processEvent(CCombatInterface::CEvent const& event) // If sit and move then stand up if (IsRingShard) - { + { if (getMode() == MBEHAV::SIT && (x().asInt() != startPos.x().asInt() || y().asInt() != startPos.y().asInt()) ) { setMode(MBEHAV::NORMAL); } - + if (_FacingTick != 0) - { + { uint32 tick = CTimeInterface::gameCycle(); if ( (tick - _FacingTick) > 40) { @@ -213,7 +215,7 @@ void CSpawnBotNpc::setFacing(CAngle theta) { _FacingTheta = pos().theta(); } - + setTheta(theta); _FacingTick = CTimeInterface::gameCycle(); } @@ -260,8 +262,8 @@ std::vector CSpawnBotNpc::getMultiLineInfoString() const { std::vector container; std::vector strings; - - + + pushTitle(container, "CSpawnBotNpc"); strings.clear(); strings = CSpawnBot::getMultiLineInfoString(); @@ -287,8 +289,8 @@ std::vector CSpawnBotNpc::getMultiLineInfoString() const } } pushFooter(container); - - + + return container; } @@ -301,7 +303,7 @@ void CSpawnBotNpc::beginBotChat(CBotPlayer* plr) nlwarning("Chat pair added more than once!!!"); } #endif - + // add an entry to the bot chat vector _ActiveChats.push_back(plr); } @@ -313,11 +315,11 @@ void CSpawnBotNpc::endBotChat(CBotPlayer* plr) { if (_ActiveChats[i]!=plr) continue; - + // we've found a match for the player so remove the entry from the _aciveChats vector and return _ActiveChats[i] = _ActiveChats[_ActiveChats.size()-1]; _ActiveChats.pop_back(); - + #ifdef NL_DEBUG for (size_t j=i;j<_ActiveChats.size();++j) { @@ -342,14 +344,14 @@ void CSpawnBotNpc::propagateAggro() const CDynGrpBase* myDgb = pGroup->getGrpDynBase(); nlassert(myDgb); CFamilyBehavior* myfb = myDgb->getFamilyBehavior(); - + CAIVision vision; // look for bots around vision.updateBotsAndPlayers(pGroup->getAIInstance(), CAIVector(pos()), 0, (uint32)getAggroPropagationRadius()); - + typedef map TCandidatesCont; TCandidatesCont candidates; - + if (myfb!=NULL) { FOREACH(it, CAIVision, vision) @@ -358,32 +360,32 @@ void CSpawnBotNpc::propagateAggro() const CSpawnBot* otherSpBot = otherPBot.getSpawnObj(); CGroup* otherPGroup = otherPBot.getOwner(); CSpawnGroup* otherSpGroup = otherPGroup->getSpawnObj(); - + // If bot is in our group skip it if (otherSpGroup==spGroup) continue; - + // If bot is not in a dynamic system skip it CDynGrpBase* otherDGB = otherPGroup->getGrpDynBase(); if (!otherDGB) continue; - + // If bot is not in our family skip it CFamilyBehavior* otherFB = otherDGB->getFamilyBehavior(); if (otherFB!=myfb) continue; - + // ok, this group should help us ! - + // TODO : take only groups with the 'activity_figth' property // filter out if the group is already in combat mode - + // If group is not spawned skip it (???) (:TODO: See why this test) if (!otherPGroup->isSpawned()) continue; - + CProfilePtr& otherFightProfile = otherSpGroup->fightProfile(); - + if (!otherFightProfile.getAIProfile() || otherFightProfile.getAIProfileType()!=AITYPES::FIGHT_NORMAL || !(static_cast(otherFightProfile.getAIProfile())->stillHaveEnnemy())) { float dist = (float)CAIVector(otherSpBot->pos()).quickDistTo(pos()); @@ -392,10 +394,10 @@ void CSpawnBotNpc::propagateAggro() const } } } - + if (!candidates.empty()) nldebug("Tick %u, prop aggro from %p to %u bots", CTickEventHandler::getGameCycle(), this, candidates.size()); - + FOREACH (it, TCandidatesCont, candidates) { float propFactor = 1.0f - (it->second / getAggroPropagationRadius()); @@ -435,7 +437,7 @@ void CSpawnBotNpc::setCurrentChatProfile(CNpcChatProfileImp* chatProfile) { if (chatProfile) _CurrentChatProfile = *chatProfile; - else + else _CurrentChatProfile.clear(); // clear the chat profile } @@ -466,7 +468,7 @@ CBotNpc::CBotNpc(CGroup* owner, uint32 alias, std::string const& name) init(); } -CBotNpc::~CBotNpc() +CBotNpc::~CBotNpc() { if (isSpawned()) { @@ -479,12 +481,12 @@ void CBotNpc::calcSpawnPos(RYAI_MAP_CRUNCH::CWorldMap const& worldMap) CAIStatePositional const* const state = static_cast(grp().getStartState()); RYAI_MAP_CRUNCH::CWorldPosition wp; uint32 maxTries = 100; - + breakable { if (!state) break; - + if (state->shape().hasPatat() && state->shape().getRandomPosCount()) { do @@ -497,11 +499,11 @@ void CBotNpc::calcSpawnPos(RYAI_MAP_CRUNCH::CWorldMap const& worldMap) _StartPos.setTheta(0); // to initialise among vertices deltas (no?). break; } - + if (!state->shape().hasPoints()) break; - - std::vector const& posList = state->shape().getGeometry(); + + std::vector const& posList = state->shape().getGeometry(); do { const uint32 a=CAIS::rand16((uint32)posList.size()); @@ -560,15 +562,15 @@ std::string CBotNpc::getCustomLootTableId() return _CustomLootTableId; } -void CBotNpc::setPrimAlias(uint32 alias) -{ +void CBotNpc::setPrimAlias(uint32 alias) +{ _PrimAlias = alias; } -uint32 CBotNpc::getPrimAlias() const -{ - return _PrimAlias; +uint32 CBotNpc::getPrimAlias() const +{ + return _PrimAlias; } @@ -578,18 +580,18 @@ void CBotNpc::fillDescriptionMsg(RYMSG::TGenNpcDescMsg& msg) const msg.setBotAttackable(grp().getBotAttackable()); msg.setAlias(getAlias()); msg.setGrpAlias(grp().getAlias()); - + msg.setSheet(getSheet()->SheetId()); - + msg.setRightHandItem(getSheet()->RightItem()); msg.setRightHandItemQuality(1); - + msg.setLeftHandItem(getSheet()->LeftItem()); msg.setLeftHandItemQuality(1); - + msg.setDontFollow(isStuck()); msg.setBuildingBot(isBuildingBot()); - + for (size_t i=0; i<_LootList.size(); ++i) { NLMISC::CSheetId const& sheetRef = _LootList[i]; @@ -629,12 +631,12 @@ bool CBotNpc::finalizeSpawnNpc() getSpawn()->setOutpostAlias(ownerOutpost->getAlias()); getSpawn()->setOutpostSide(_OutpostSide); } - + CMirrors::initSheetServer(getSpawn()->dataSetRow(), getSheet()->SheetId()); - + getSpawn()->setCurrentChatProfile(_ChatProfile); getSpawn()->sendInfoToEGS(); - + if (_useVisualProperties) // use VisualPropertyA, B, C { sendVisualProperties(); @@ -643,9 +645,9 @@ bool CBotNpc::finalizeSpawnNpc() { sendVPA (); } - + getSpawn()->spawnGrp().botHaveSpawn(this); - + return true; } @@ -671,10 +673,10 @@ bool CBotNpc::spawn() nlwarning("spawn() Aborted for bot '%s' due to bad sheet", getFullName().c_str()); return false; } - + if (!CBot::spawn()) return false; - + // :KLUDGE: Last part calls a tricky method also called by sheetChanged // :TODO: Clean that mess return finalizeSpawnNpc(); @@ -688,12 +690,12 @@ void CBotNpc::sendVPA() // alternate VPA CVisualSlotManager* visualSlotManager = CVisualSlotManager::getInstance(); NLMISC::CSheetId rightSheet = getSheet()->RightItem(); NLMISC::CSheetId leftSheet = getSheet()->LeftItem(); - + visProp.Element.WeaponRightHand = visualSlotManager->rightItem2Index(rightSheet); visProp.Element.WeaponLeftHand = visualSlotManager->leftItem2Index(leftSheet); } - - // setting up the visual property A mirror record + + // setting up the visual property A mirror record visProp.Element.ColorTop = getSheet()->ColorBody(); visProp.Element.ColorBot = getSheet()->ColorLegs(); visProp.Element.ColorHair = getSheet()->ColorHead(); @@ -714,7 +716,7 @@ void CBotNpc::sendVPA() // alternate VPA visProp.Element.ColorBoot, visProp.Element.ColorArm, visProp.Element.Seed); - + CMirrors::setVPA(getSpawn()->dataSetRow(), visProp); } @@ -732,7 +734,7 @@ bool CBotNpc::reSpawn(bool sendMessage) { if (!spawn()) return false; - + getSpawn()->updateChat(grp().getCAIState()); return true; } @@ -746,7 +748,7 @@ void CBotNpc::despawnBot() } } -void CBotNpc::equipmentInit() +void CBotNpc::equipmentInit() { _Sheet->reset(); _Hat = false; @@ -762,7 +764,7 @@ void CBotNpc::equipmentAdd(std::string const& input) // if string is empty just return without making a fuss if (input.empty()) return; - + // split string into keyword and tail std::string keyword, tail; if (!AI_SHARE::stringToKeywordAndTail(input,keyword,tail)) @@ -773,7 +775,7 @@ void CBotNpc::equipmentAdd(std::string const& input) input.c_str()); return; } - + // do something depending on keyword if (NLMISC::nlstricmp(keyword,"ri")==0) { @@ -836,7 +838,7 @@ void CBotNpc::equipmentAdd(std::string const& input) else if ( NLMISC::nlstricmp(keyword,"CLIENT_SHEET")==0 ) { setClientSheet(tail + ".creature"); - } + } else if (NLMISC::nlstricmp(keyword,"loot")==0) { if (tail.empty()) @@ -854,14 +856,14 @@ void CBotNpc::equipmentAdd(std::string const& input) } else if (NLMISC::nlstricmp(keyword, "USER_MODEL") == 0) { - + uint32 primAlias = getAlias() >> LigoConfig.getDynamicAliasSize(); nldebug("Parsing userModelId '%s' with primAlias: '%u'", tail.c_str(), primAlias); setPrimAlias(primAlias); setUserModelId(tail); } else if (NLMISC::nlstricmp(keyword, "CUSTOM_LOOT_TABLE") == 0) - { + { uint32 primAlias = getAlias() >> LigoConfig.getDynamicAliasSize(); nldebug("Parsing customLootTableId '%s' with primAlias: '%u'", tail.c_str(), primAlias); setPrimAlias(primAlias); @@ -878,14 +880,14 @@ void CBotNpc::equipmentAdd(std::string const& input) /* Colors are something like that: - 3D INTERFACE MP -0: ROUGE ROUGE RED -1: BEIGE ORANGE BEIGE -2: VERT CITRON VERT CITRON GREEN -3: VERT VERT TURQUOISE -4: BLEU BLEU BLUE -5: ROUGE dark ROUGE (normal) CRIMSON -6: BLANC JAUNE WHITE + 3D INTERFACE MP +0: ROUGE ROUGE RED +1: BEIGE ORANGE BEIGE +2: VERT CITRON VERT CITRON GREEN +3: VERT VERT TURQUOISE +4: BLEU BLEU BLUE +5: ROUGE dark ROUGE (normal) CRIMSON +6: BLANC JAUNE WHITE 7: NOIR BLEU very dark BLACK 3D column is (probably) used for equipment @@ -894,7 +896,7 @@ void CBotNpc::setColour(uint8 colour) { _Sheet->setColorHead(colour); _Sheet->setColorArms(colour); - _Sheet->setColorHands(colour); + _Sheet->setColorHands(colour); _Sheet->setColorBody(colour); _Sheet->setColorLegs(colour); _Sheet->setColorFeets(colour); @@ -906,11 +908,11 @@ void CBotNpc::setColours(std::string input) int const numColours = 8; static std::vector colourNames[numColours]; static bool init = false; - + // if string is empty just return without making a fuss if (input.empty()) return; - + if (!init) { // lookup 'ColourNames' in config file (should be a multi-line field) @@ -920,7 +922,7 @@ void CBotNpc::setColours(std::string input) // for each line in config file var try to add an alternative name for one of the colour slots for (uint i=0; isize(); ++i) { - // split line into name and idx (line example: 'red: 5') + // split line into name and idx (line example: 'red: 5') std::string name, idxStr; if (AI_SHARE::stringToKeywordAndTail(varPtr->asString(i),name,idxStr)) { @@ -994,12 +996,12 @@ void CBotNpc::setColours(std::string input) } } } - + if (i==numColours) nlwarning("Failed to identify colour: '%s' in line: '%s'",colour.c_str(),input.c_str()); } } - + // assuming that we found more than 0 results pick one at random if (results.empty()) { @@ -1151,9 +1153,10 @@ void CBotNpc::init() { _ChatProfile = NULL; _MaxHitRangeForPC = -1.0f; + _DispersionRadius = 0; // _MissionIconFlags.IsMissionStepIconDisplayable = true; // _MissionIconFlags.IsMissionGiverIconDisplayable = true; - + equipmentInit(); } @@ -1169,21 +1172,38 @@ CSpawnBotNpc const* CBotNpc::getSpawn() const void CBotNpc::getSpawnPos(CAIVector& triedPos, RYAI_MAP_CRUNCH::CWorldPosition& pos, RYAI_MAP_CRUNCH::CWorldMap const& worldMap, CAngle& spawnTheta) { - if (_StartPos.isNull()) + if (_DispersionRadius > 0) + { + RYAI_MAP_CRUNCH::CWorldPosition wp; + CAIVector rpos = _FirstPosition; + uint32 maxTries = 100; + do + { + rpos = _FirstPosition; + rpos += randomPos(_DispersionRadius); + --maxTries; + } + while (!worldMap.setWorldPosition(AITYPES::vp_auto, wp, rpos) && maxTries>0); + if (maxTries > 0 ) { + nlinfo("set pos %f,%f", rpos.x().asDouble(), rpos.x().asDouble()); + _StartPos.setXY(rpos); + } + } + else if (_StartPos.isNull()) calcSpawnPos(worldMap); - + if (isStuck() || IsRingShard) worldMap.setWorldPosition(_VerticalPos, pos, _StartPos); else CWorldContainer::calcNearestWPosFromPosAnRadius(_VerticalPos, worldMap, pos, _StartPos, 10, 200, CWorldContainer::CPosValidatorDefault()); - + #ifdef NL_DEBUG if (!pos.isValid() && !isStuck()) { nlwarning("Npc Spawn Pos Error %s", pos.toString().c_str()); } #endif - + spawnTheta = _StartPos.theta(); triedPos = _StartPos; } @@ -1220,20 +1240,20 @@ void CBotNpc::sheetChanged() CAngle spawnTheta = getSpawnObj()->theta(); float botMeterSize = getSheet()->Scale()*getSheet()->Radius(); // :TODO: Save profile info - + // If stuck bot position may be outside collision and must be recomputed if (isStuck() || IsRingShard) getSpawnPos(lastTriedPos, botWPos, CWorldContainer::getWorldMap(), spawnTheta); - + // Delete old bot CMirrors::removeEntity(getSpawnObj()->getEntityId()); setSpawn(NULL); // automatic smart pointer deletion notifyBotDespawn(); - + // Finalize spawn object creation if (!finalizeSpawn(botWPos, spawnTheta, botMeterSize)) return; - + // :KLUDGE: Both finalizeSpawn and finalizeSpawnNpc are called, // sheetChanged has a strange herited meaning and may confuse future // coders @@ -1252,16 +1272,16 @@ NLMISC_COMMAND(verboseNPCBotProfiles, "Turn on or off or check the state of verb { if (args.size()>1) return false; - + if (args.size()==1) NLMISC::fromString(args[0], VerboseLog); - + nlinfo("VerboseLogging is %s",VerboseLog?"ON":"OFF"); return true; } // virtual function so do not need to be inlined bool CBotNpc::getFaunaBotUseBotName() const -{ - return _FaunaBotUseBotName; +{ + return _FaunaBotUseBotName; } diff --git a/ryzom/server/src/ai_service/ai_bot_npc.h b/ryzom/server/src/ai_service/ai_bot_npc.h index 3455e7f58..aaaeb6757 100644 --- a/ryzom/server/src/ai_service/ai_bot_npc.h +++ b/ryzom/server/src/ai_service/ai_bot_npc.h @@ -41,47 +41,47 @@ class CSpawnBotNpc { public: CSpawnBotNpc(TDataSetRow const& row, CBot& owner, NLMISC::CEntityId const& id, float radius, uint32 level, RYAI_MAP_CRUNCH::TAStarFlag denyFlags); - + void update(uint32 ticks); - + CSpawnGroupNpc& spawnGrp() const; - + // Accessors for NPC dynamic parameters ----------------------------- void setCurrentChatProfile(CNpcChatProfileImp* chatProfile); void updateChat(CAIState const* state); - + virtual void processEvent(CCombatInterface::CEvent const& event); - + CAIEntityPhysical& getPhysical() { return *this; } - - /// @name Chat parameter management + + /// @name Chat parameter management //@{ void beginBotChat(CBotPlayer* plr); void endBotChat(CBotPlayer* plr); void beginDynChat() { ++_NbCurrentDynChats; } void endDynChat() { --_NbCurrentDynChats; } //@} - + // Return the active bot chats std::vector& getActiveChats() { return _ActiveChats; } - + // Return the number of dyn chats (these chats are not managed by the AIS) uint getNbActiveDynChats() { return _NbCurrentDynChats; } - + /// Dispatching message to EGS to describe chat possibilities void sendInfoToEGS() const; - + virtual std::vector getMultiLineInfoString() const; - + CBotNpc& getPersistent() const; - + virtual RYZOMID::TTypeId getRyzomType() const { return RYZOMID::npc; } - + virtual bool isBotAttackable() const; - + virtual void propagateAggro() const; - + float getReturnDistCheck() const; void setPlayerController(CBotPlayer* player); @@ -102,7 +102,7 @@ public: private: std::vector _ActiveChats; // vector of ptrs to players currently chatting with bot float _OldHpPercentage; // Fix for HP triggers - + CNpcChatProfileImp _CurrentChatProfile; sint32 _NbCurrentDynChats; NLMISC::CSmartPtr _PlayerController; @@ -135,7 +135,7 @@ public: { reset(); } - + ///@name ICreature overloads //@{ virtual uint8 ColorHead() const { return _ColorHead; } @@ -144,7 +144,7 @@ public: virtual uint8 ColorBody() const { return _ColorBody; } virtual uint8 ColorLegs() const { return _ColorLegs; } virtual uint8 ColorFeets() const { return _ColorFeets; } - + virtual NLMISC::CSheetId const& LeftItem() const { if (_LeftItem!=NLMISC::CSheetId::Unknown) @@ -160,7 +160,7 @@ public: return this->CCreatureProxy::RightItem(); } //@} - + ///@name Setters //@{ void setColorHead(uint8 val) { _ColorHead = val; } @@ -169,7 +169,7 @@ public: void setColorBody(uint8 val) { _ColorBody = val; } void setColorLegs(uint8 val) { _ColorLegs = val; } void setColorFeets(uint8 val) { _ColorFeets = val; } - + void setLeftItem(NLMISC::CSheetId const& val) { _LeftItem = val; } void setRightItem(NLMISC::CSheetId const& val) { _RightItem = val; } //@} @@ -188,13 +188,13 @@ public: _ColorFeets = _Sheet->ColorFeets(); } } - -private: + +private: NLMISC::CSheetId _LeftItem; NLMISC::CSheetId _RightItem; uint8 _ColorHead; uint8 _ColorArms; - uint8 _ColorHands; + uint8 _ColorHands; uint8 _ColorBody; uint8 _ColorLegs; uint8 _ColorFeets; @@ -212,72 +212,74 @@ class CBotNpc { public: friend class CSpawnBotNpc; // allows CSpawnBotNpc to acceed his definition. - + public: CBotNpc(CGroup* owner, CAIAliasDescriptionNode* alias = NULL); CBotNpc(CGroup* owner, uint32 alias, std::string const& name); virtual ~CBotNpc(); - + void init(); - + RYZOMID::TTypeId getRyzomType() const { return RYZOMID::npc; } - + CSpawnBotNpc* getSpawn(); CSpawnBotNpc const* getSpawn() const; - + CAIS::CCounter& getSpawnCounter(); - + void calcSpawnPos(RYAI_MAP_CRUNCH::CWorldMap const& worldMap); - + void getSpawnPos(CAIVector& triedPos, RYAI_MAP_CRUNCH::CWorldPosition& pos, RYAI_MAP_CRUNCH::CWorldMap const& worldMap, CAngle& spawnTheta); - + CSpawnBot* getSpawnBot(TDataSetRow const& row, NLMISC::CEntityId const& id, float radius); - + // spawn & despawn -------------------------------------------------- virtual bool spawn(); virtual void despawnBot(); - + bool reSpawn(bool sendMessage = true); - + //------------------------------------------------------------ - // accessing the parent mgr, group, etc + // accessing the parent mgr, group, etc CGroupNpc& grp() const; - + // Carried equipment management ------------------------------------- void equipmentInit(); void equipmentAdd(std::string const& kit); - + // Write accessors for NPC base parameters -------------------------- void setStartPos(double x, double y, float theta, AITYPES::TVerticalPos verticalPos); - + void setColour(uint8 colour); void setColours(std::string colours); void setVisualProperties(std::string input); + inline void saveFirstPosition(CAIVector pos, uint8 value) { _FirstPosition = pos, _DispersionRadius = value; } + inline void setMaxHitRangeForPlayer(float maxHitRange) { _MaxHitRangeForPC = maxHitRange; } // void setMissionStepIconHidden(bool hide) { _MissionIconFlags.IsMissionStepIconDisplayable = !hide; } // void setMissionGiverIconHidden(bool hide) { _MissionIconFlags.IsMissionGiverIconDisplayable = !hide; } - + // Read accessors for NPC base parameters --------------------------- NLMISC::CSheetId getStats() const { return getSheet()->SheetId(); } CAIPos const& getStartPos() const { return _StartPos; } AITYPES::TVerticalPos getStartVerticalPos() const { return _VerticalPos; } - + // Callback called on state change of parent group (including changes to/from punctual states) - + // the update routine (delegates control to the _aiProfile object) -- // void update(uint32 ticks); - + // do nothing for 'ticks' ticks // return number of ticks of movement time left after destination reached (or 0) void sendVPA(); void sendVisualProperties(); - + void newChat(); - + NLMISC::CSmartPtr const& getChat() const { return _ChatProfile; } void setUserModelId(const std::string &userModelId); std::string getUserModelId(); @@ -287,13 +289,13 @@ public: void setPrimAlias(uint32 alias); uint32 getPrimAlias() const; - + // void fillDescriptionMsg(CNpcBotDescriptionImp& msg) const; void fillDescriptionMsg(RYMSG::TGenNpcDescMsg& msg) const; - - + + virtual std::string getOneLineInfoString() const { return std::string("NPC bot '") + getName() + "'"; } - + virtual AISHEETS::ICreatureCPtr getSheet() const { return _Sheet.getPtr(); } virtual void setSheet(AISHEETS::ICreatureCPtr const& sheet); @@ -302,22 +304,22 @@ public: { return _Sheet!=NULL && _Sheet->isValid(); } - + void setOutpostSide(OUTPOSTENUMS::TPVPSide side) { _OutpostSide = side; } - + virtual bool getFaunaBotUseBotName() const; - + protected: virtual void sheetChanged(); bool finalizeSpawnNpc(); virtual void initAdditionalMirrorValues(); - + protected: // stuff supplied by CAIBot ------------------ // sheet (.creature) for game parameters // position & orientation // mode and behaviour - + // A static bot object with a fauna sheet must not display SheetName but botobject name bool _FaunaBotUseBotName; @@ -332,23 +334,25 @@ protected: // look parameters --------------------------- bool _Hat; - + bool _useVisualProperties; // true => use VisualPropertyA, B, C instead of alternate VPA uint64 _VisualPropertyA; uint64 _VisualPropertyB; uint64 _VisualPropertyC; - + CBotNpcSheetPtr _Sheet; - - + + // spawn place ------------------------------- CAIPos _StartPos; - + CAIVector _FirstPosition; + uint8 _DispersionRadius; + std::vector _LootList; // static chat parameters -------------------- NLMISC::CSmartPtr _ChatProfile; - + // Outpost side OUTPOSTENUMS::TPVPSide _OutpostSide; diff --git a/ryzom/server/src/ai_service/ai_instance.cpp b/ryzom/server/src/ai_service/ai_instance.cpp index 8e81fa143..5c7cf70fd 100644 --- a/ryzom/server/src/ai_service/ai_instance.cpp +++ b/ryzom/server/src/ai_service/ai_instance.cpp @@ -216,8 +216,9 @@ void CAIInstance::initInstance(string const& continentName, uint32 instanceNumbe _ContinentName = continentName; _InstanceNumber = instanceNumber; - _LastSpawnAlias = (900 + _InstanceNumber) << LigoConfig.getDynamicAliasSize(); + _LastSpawnAlias = (900 + _InstanceNumber) << LigoConfig.getDynamicAliasSize(); _LastStateAlias = 0; + _LastGroupAlias = (900 + _InstanceNumber) << LigoConfig.getDynamicAliasSize(); sendInstanceInfoToEGS(); @@ -344,8 +345,9 @@ CGroup* CAIInstance::findGroup(uint32 alias) void CAIInstance::findGroup(std::vector& result, std::string const& name) { std::map > >::iterator it(_GroupFromNames.find(name)); - if (it != _GroupFromNames.end()) + if (it != _GroupFromNames.end()) { result.insert(result.end(), it->second.begin(), it->second.end()); + } } void CAIInstance::addMissionInfo(std::string const& missionName, uint32 alias) @@ -647,8 +649,9 @@ std::vector CAIInstance::getMultiLineInfoString() const #include "ai_bot_npc.h" #include "ai_profile_npc.h" -inline -static CAIVector randomPos(double dispersionRadius) +extern CAIVector randomPos(double dispersionRadius); + +CAIVector randomPos(double dispersionRadius) { if (dispersionRadius<=0.) { @@ -684,14 +687,15 @@ CGroupNpc* CAIInstance::eventCreateNpcGroup(uint nbBots, NLMISC::CSheetId const& return NULL; } + _LastGroupAlias++; + string name = botsName.empty() ? NLMISC::toString("event_group_%u", _LastGroupAlias):botsName; // Create a group - CGroupNpc* grp = new CGroupNpc(_EventNpcManager, NULL, RYAI_MAP_CRUNCH::Nothing); + CGroupNpc* grp = new CGroupNpc(_EventNpcManager, _LastGroupAlias, name, RYAI_MAP_CRUNCH::Nothing); // Register it in the manager _EventNpcManager->groups().addAliasChild(grp); // Set the group parameters grp->setAutoSpawn(false); - string name = botsName.empty() ? NLMISC::toString("event_group_%u", grp->getChildIndex()):botsName; grp->setName(name); grp->clearParameters(); @@ -707,7 +711,7 @@ CGroupNpc* CAIInstance::eventCreateNpcGroup(uint nbBots, NLMISC::CSheetId const& { // build unnamed bot - for (uint i=0; isetStuck(true); } + + float angle = 0.f; + if (orientation < (NLMISC::Pi * 2.0) && orientation > (-NLMISC::Pi * 2.0)) + angle = (float)orientation; + else + angle = randomAngle(); + // Spawn all randomly except if only 1 bot - if (nbBots > 1) + if (nbBots > 1 || dispersionRadius > 1) { + bot->saveFirstPosition(pos, dispersionRadius); RYAI_MAP_CRUNCH::CWorldMap const& worldMap = CWorldContainer::getWorldMap(); RYAI_MAP_CRUNCH::CWorldPosition wp; uint32 maxTries = 100; @@ -742,15 +754,11 @@ CGroupNpc* CAIInstance::eventCreateNpcGroup(uint nbBots, NLMISC::CSheetId const& while (!worldMap.setWorldPosition(AITYPES::vp_auto, wp, rpos) && maxTries>0); if (maxTries<=0) rpos = pos; - } - float angle = 0.f; - if (orientation < (NLMISC::Pi * 2.0) && orientation > (-NLMISC::Pi * 2.0)) - angle = (float)orientation; + bot->setStartPos(pos.x().asDouble(), pos.y().asDouble(), angle, AITYPES::vp_auto); + } else - angle = randomAngle(); - - bot->setStartPos(rpos.x().asDouble(),rpos.y().asDouble(), angle, AITYPES::vp_auto); + bot->setStartPos(rpos.x().asDouble(),rpos.y().asDouble(), angle, AITYPES::vp_auto); } } @@ -786,7 +794,7 @@ CGroupNpc* CAIInstance::eventCreateNpcGroup(uint nbBots, NLMISC::CSheetId const& } grp->setNextState(statePositional); } - + if (spawnBots) grp->getSpawnObj()->spawnBots(); @@ -999,7 +1007,7 @@ void cbEventNpcGroupScript( NLNET::CMessage& msgin, const std::string &serviceNa CEntityId playerId; if (!eid.empty()) playerId = CEntityId(eid); - + strings.resize(nbString-1); CSString groupname = CSString(firstCommand); if (firstCommand[0] == '#' && firstCommand[1] == '(') diff --git a/ryzom/server/src/ai_service/ai_instance.h b/ryzom/server/src/ai_service/ai_instance.h index 38b62fafb..2b5114441 100644 --- a/ryzom/server/src/ai_service/ai_instance.h +++ b/ryzom/server/src/ai_service/ai_instance.h @@ -65,7 +65,7 @@ class CAIInstance public: CAIInstance(CAIS* owner); virtual ~CAIInstance(); - + typedef CHashMap, NLMISC::CStringIdHashMapTraits> TZoneList; TZoneList zoneList; void addZone(std::string const& zoneName, CNpcZone* zone); @@ -73,50 +73,50 @@ public: CNpcZone* getZone(NLMISC::TStringId zoneName); // Trig Event if player in zone void updateZoneTrigger(CBotPlayer* player); - + // overloads for IManagerParent virtuals CAIInstance* getAIInstance() const { return const_cast(this); } CCellZone* getCellZone() { return NULL; } virtual std::string getIndexString() const; virtual std::string getOneLineInfoString() const; virtual std::vector getMultiLineInfoString() const; - + std::string getManagerIndexString(CManager const* manager) const; - + void groupDead(CGroup* grp) { } - + void serviceEvent(CServiceEvent const& info); - + //------------------------------------------------------------------- // classic init(), update() and release() - + // the update routine called once per tick // this is the routine that calls the managers' updates void update(); - + //------------------------------------------------------------------- // managing the set of managers // factory for creating new managers and for adding them to the _managers map CManager* newMgr(AITYPES::TMgrType type, uint32 alias, std::string const& name, std::string const& mapName, std::string const& filename); - + // a method that parse a supposed know type of manager:group:bot hierarchy and return the element as CAIEntity. CManager* tryToGetManager(char const* str); CGroup* tryToGetGroup(char const* str); - + CAIEntity* tryToGetEntity(char const* str, CAIS::TSearchType searchType); - + // erase a manager (free resources, free id, etc, etc // asserts if the id is invalid (<0 or >1023) // displays a warning and returns cleanly if the id is unused void deleteMgr(sint mgrId); - + //------------------------------------------------------------------- - // the previous interfaces for searching the data structures for named objects are transfered in CAIEntityId + // the previous interfaces for searching the data structures for named objects are transfered in CAIEntityId // as its one of their object behavior. a solution to build id directly was added. CMgrPet* getPetMgr() { return _PetManager; } CManagerPlayer* getPlayerMgr() { return _PlayerManager; } - + //------------------------------------------------------------------- // Interface to kami management void registerKamiDeposit(uint32 alias, CGroupNpc* grp); @@ -124,23 +124,23 @@ public: //------------------------------------------------------------------- // Interface to the vision management matrices - + // read accessors for getting hold of the vision matrices and their associated iterator tables CAIEntityMatrix& playerMatrix() { return _PlayerMatrix; } CAIEntityMatrix& botMatrix() { return _BotMatrix; } - + CAliasCont& managers() { return _Managers; } - + CCont& continents() { return _Continents; } CCont const& continents() const { return _Continents; } - + // Methods to retreive location in the dynamic system. CContinent* locateContinentForPos(CAIVector const& pos); CRegion* locateRegionForPos(CAIVector const& pos); CCellZone* locateCellZoneForPos(CAIVector const& pos); CCell* locateCellForPos(CAIVector const& pos); - - + + //------------------------------------------------------------------- // Mission name/alias retreiver /** Add a mission name and alias info. If alias is already mapped to a mission name, replace the mapping. @@ -161,7 +161,7 @@ public: * This search is not optimized, linar time search ! */ std::string const& findMissionName(uint32 alias); - + //------------------------------------------------------------------- // group name/alias retreiver void addGroupInfo(CGroup* grp); @@ -169,19 +169,19 @@ public: void removeGroupInfo(CGroup* grp, CAliasTreeOwner* grpAliasTreeOwner); CGroup* findGroup(uint32 alias); void findGroup(std::vector& result, std::string const& name); - + /// Time warp management. This method is called when time as warped more than 600ms bool advanceUserTimer(uint32 nbTicks); - + bool spawn(); bool despawn(); - + uint32 getInstanceNumber() const { return _InstanceNumber; } std::string const& getContinentName() const { return _ContinentName; } std::string& getContinentName() { return _ContinentName; } - + void initInstance(std::string const& continentName, uint32 instanceNumber); - + /// Main squad family accessor COutpostSquadFamily *getSquadFamily() { return _SquadFamily; } @@ -219,7 +219,7 @@ public: private: void sendInstanceInfoToEGS(); - + private: /// @name AI service hierarchy //@{ @@ -228,16 +228,16 @@ private: /// the set of managers and the service's root alias description tree node CAliasCont _Managers; //@} - + static NLLIGO::CLigoConfig _LigoConfig; - + /// The ai instance continent name (multi ai system) std::string _ContinentName; /// The ai instance number (multi ai system) uint32 _InstanceNumber; - + CAIEntity* tryToGetEntity(char const* str); - + // we must share pets and players .. later :) /// pet manager CMgrPet* _PetManager; @@ -246,9 +246,10 @@ private: /// event npc Manager. CMgrNpc* _EventNpcManager; + uint32 _LastGroupAlias; uint32 _LastSpawnAlias; uint32 _LastStateAlias; - + /// easter egg manager NLMISC::CRefPtr _EasterEggManager; @@ -257,14 +258,14 @@ private: /// map of kami groups by alias (for kami groups associated with deposits) std::map _KamiDeposits; - + /// matrices used for vision generation and their associated iterator tables CAIEntityMatrix _PlayerMatrix; CAIEntityMatrix _BotMatrix; - + // Mission name to alias container. std::map > _MissionToAlias; - + /// Group name and alias container. std::map > > _GroupFromNames; std::map > _GroupFromAlias; diff --git a/ryzom/server/src/ai_service/ai_profile_npc.cpp b/ryzom/server/src/ai_service/ai_profile_npc.cpp index 35a32c15b..50805a7a9 100644 --- a/ryzom/server/src/ai_service/ai_profile_npc.cpp +++ b/ryzom/server/src/ai_service/ai_profile_npc.cpp @@ -3926,7 +3926,21 @@ void CGrpProfileFaction::checkTargetsAround() const uint32 playerRadius=assistPlayers||attackPlayers?thisGrpNpc._AggroRange:0; const uint32 botRadius=assistBots||attackBots?thisGrpNpc._AggroRange:0; - Vision.updateBotsAndPlayers(thisGrpNpc.getAIInstance(), centerPos, playerRadius, botRadius); + CCont::iterator itBot=_Grp->bots().begin(); + uint32 cellValue = 0; + CBot* bot = *itBot; + if (bot) + { + CSpawnBot* spawnBot = bot->getSpawnObj(); + if (spawnBot) + { + CMirrorPropValueRO cell( TheDataset, spawnBot->dataSetRow(), DSPropertyCELL ); + cellValue = cell(); + } else + nlinfo("BOT NOT SPAWN TO GET CELL"); + } + + Vision.updateBotsAndPlayers(thisGrpNpc.getAIInstance(), centerPos, playerRadius, botRadius, cellValue); } // Assist players @@ -4046,7 +4060,7 @@ void CGrpProfileFaction::checkTargetsAround() void CGrpProfileFaction::updateProfile(uint ticksSinceLastUpdate) { - checkTargetsAround (); + checkTargetsAround(); CGrpProfileNormal::updateProfile(ticksSinceLastUpdate); } diff --git a/ryzom/server/src/ai_service/ai_vision.h b/ryzom/server/src/ai_service/ai_vision.h index 916c16218..01d33e367 100644 --- a/ryzom/server/src/ai_service/ai_vision.h +++ b/ryzom/server/src/ai_service/ai_vision.h @@ -53,12 +53,12 @@ public: {} virtual ~CAIVision() {} - template - void updateBotsAndPlayers(CAIInstance *aii, const VectorClass &xy,uint32 playerRadiusInMeters,uint32 botRadiusInMeters) + template + void updateBotsAndPlayers(CAIInstance *aii, const VectorClass &xy,uint32 playerRadiusInMeters,uint32 botRadiusInMeters, uint32 cell=0) { // _lastUpdate=CTimeInterface::gameCycle(); - updatePlayers(aii, xy, playerRadiusInMeters); - updateBots(aii, xy, botRadiusInMeters); + updatePlayers(aii, xy, playerRadiusInMeters, cell); + updateBots(aii, xy, botRadiusInMeters, cell); } void clear () @@ -85,7 +85,7 @@ public: { public: iterator(): _vect(NULL), _vision(NULL) {} - iterator(const CAIVision *vision): _vision(vision) + iterator(const CAIVision *vision): _vision(vision) { if (!vision->players().empty()) { @@ -116,7 +116,7 @@ public: #endif const NLMISC::CDbgPtr &dbgRef=*_it; T* objPtr=(T*)dbgRef; - + return objPtr; } iterator operator++() @@ -156,17 +156,17 @@ public: private: const CAIVision *_vision; - const std::vector > *_vect; + const std::vector > *_vect; typename std::vector >::const_iterator _it; }; //---------------------------------------------------------------------- // stl-like begin() and end() - iterator begin() + iterator begin() { return iterator(this); } - iterator end() + iterator end() { return iterator(); } @@ -190,17 +190,17 @@ private: - template - void updateBots(CAIInstance *aii, const VectorClass &xy,uint32 botRadiusInMeters) + template + void updateBots(CAIInstance *aii, const VectorClass &xy, uint32 botRadiusInMeters, uint32 cell) { H_AUTO(VisionUpdateBots); _botsVisionCenter = xy; _botsVisionRadius = botRadiusInMeters; - + const CAIEntityMatrixIteratorTblLinear *tbl; typename CAIEntityMatrix::CEntityIteratorLinear it; - + _bots.clear(); if (botRadiusInMeters==0) return; @@ -211,24 +211,26 @@ private: for (it = aii->botMatrix().beginEntities(tbl,xy); !it.end(); ++it) { CAIEntityPhysical const* phys = const_cast(&*it)->getSpawnObj(); - if (phys && phys->aipos().quickDistTo(aiVectorXy) < botRadiusInMeters) + + CMirrorPropValueRO botCell( TheDataset, phys->dataSetRow(), DSPropertyCELL ); + if ((cell >= 0 || botCell() == cell) && phys && phys->aipos().quickDistTo(aiVectorXy) < botRadiusInMeters) { _bots.push_back(const_cast(&*it)); } } } - - template - void updatePlayers(CAIInstance *aii, const VectorClass &xy,uint32 playerRadiusInMeters) + + template + void updatePlayers(CAIInstance *aii, const VectorClass &xy, uint32 playerRadiusInMeters, uint32 cell = 0) { H_AUTO(VisionUpdatePlayers); - + _playersVisionCenter = xy; _playersVisionRadius = playerRadiusInMeters; - + const CAIEntityMatrixIteratorTblLinear *tbl; typename CAIEntityMatrix::CEntityIteratorLinear it; - + _players.clear(); if (playerRadiusInMeters==0) return; @@ -238,16 +240,14 @@ private: for (it = aii->playerMatrix().beginEntities(tbl,xy); !it.end(); ++it) { CAIEntityPhysical const* phys = const_cast(&*it)->getSpawnObj(); - - CMirrorPropValueRO cell( TheDataset, phys->dataSetRow(), DSPropertyCELL ); - - if (phys && phys->aipos().quickDistTo(aiVectorXy) < playerRadiusInMeters) + CMirrorPropValueRO botCell( TheDataset, phys->dataSetRow(), DSPropertyCELL ); + if ((cell >= 0 || botCell() == cell) && phys && phys->aipos().quickDistTo(aiVectorXy) < playerRadiusInMeters) { _players.push_back(const_cast(&*it)); } } } - + //---------------------------------------------------------------------- // private data diff --git a/ryzom/server/src/ai_service/messages.cpp b/ryzom/server/src/ai_service/messages.cpp index 74f229945..efd40ac66 100644 --- a/ryzom/server/src/ai_service/messages.cpp +++ b/ryzom/server/src/ai_service/messages.cpp @@ -88,7 +88,7 @@ class CCharacterBotChatBeginEndReceiver: public CCharacterBotChatBeginEnd for (uint i=0;iPdr.fromBuffer((const char*)buffer, size); delete [] buffer; - + CAIS::instance().addTickedTask(tick + 1,task1); CAIS::instance().addTickedTask(tick + 2, task2); - + } if( isBase ) @@ -349,7 +349,7 @@ static void cbR2GoLive( NLNET::CMessage& msgin, const std::string &serviceName, CUnifiedNetwork::getInstance()->send("DSS",msgout); nlinfo( "R2An: ack sent to DSS for anim session %u", aiInstance ); } - + return; } @@ -367,7 +367,7 @@ public: { ICommand::execute(toString("createDynamicAIInstance %d", _AiInstance), *InfoLog); - + // load a primitiv.binprim from DSS //ICommand::execute(toString("despawnManagers %s", isBase?"base":"act"), *InfoLog); ICommand::execute(toString("unloadPrimitiveFile \"r2.%04d.act.primitive\"", _AiInstance), *InfoLog); @@ -385,7 +385,7 @@ public: private: uint32 _AiInstance; - bool _IsBase; + bool _IsBase; }; static void cbR2StopLive( NLNET::CMessage& msgin, const std::string &serviceName, NLNET::TServiceId serviceId ) @@ -397,7 +397,7 @@ static void cbR2StopLive( NLNET::CMessage& msgin, const std::string &serviceName msgin.serial(isBase); uint32 tick = CTimeInterface::gameCycle(); - CTask* task1 = new CTaskR2StopLive( aiInstance, isBase); + CTask* task1 = new CTaskR2StopLive( aiInstance, isBase); CAIS::instance().addTickedTask(tick ,task1); } @@ -425,15 +425,15 @@ private: }; static void cbR2StartInstance( NLNET::CMessage& msgin, const std::string &serviceName, NLNET::TServiceId serviceId ) -{ +{ uint32 aiInstance; - msgin.serial(aiInstance); + msgin.serial(aiInstance); uint32 tick = CTimeInterface::gameCycle(); - CTask* task1 = new CTaskR2StartInstance( aiInstance); + CTask* task1 = new CTaskR2StartInstance( aiInstance); CAIS::instance().addTickedTask(tick ,task1); - + } //-------------------------------------------------------------------------- @@ -492,7 +492,7 @@ void cbValidateSourceSpawn( NLNET::CMessage& msgin, const std::string &serviceNa if ( canSpawnHere && (wPos.getFlags() & (RYAI_MAP_CRUNCH::Water | RYAI_MAP_CRUNCH::Interior)) ) canSpawnHere = false; //continue; - + msgout.fastWrite( canSpawnHere ); // TODO: Browse the possible surfaces for the position (x,y), then keep only the one(s) @@ -569,7 +569,7 @@ void CMsgAIOpenMgrs::callback (const std::string &serviceName, uint8 sid) // failed to identify type so give up nlwarning("Failed to translate '%s' into a known type - request to open manager %04d (%s) ignored", Type[i].c_str(),MgrId[i],Name[i].c_str()); - std::string msgStr("Failed to open "+Name[i]+" due to bad type: '"+Type[i]+"'"); + std::string msgStr("Failed to open "+Name[i]+" due to bad type: '"+Type[i]+"'"); CMsgAIFeedback(msgStr).send("AIDS"); } } @@ -657,17 +657,17 @@ void CMessages::init() TRANSPORT_CLASS_REGISTER( CHandledAIGroupDespawnedMsg ); TRANSPORT_CLASS_REGISTER( CGiveItemRequestMsg ); TRANSPORT_CLASS_REGISTER( CReceiveItemRequestMsg ); - + // Classes used for comms between AI and EGS TRANSPORT_CLASS_REGISTER (CPetSpawnMsgImp); TRANSPORT_CLASS_REGISTER (CPetSpawnConfirmationMsg); TRANSPORT_CLASS_REGISTER (CPetCommandMsgImp); TRANSPORT_CLASS_REGISTER (CPetCommandConfirmationMsg); - + TRANSPORT_CLASS_REGISTER (CBSAIDeathReport); TRANSPORT_CLASS_REGISTER (CCAisActionMsg); - + TRANSPORT_CLASS_REGISTER (CEGSExecutePhraseMsg); TRANSPORT_CLASS_REGISTER (CEGSExecuteAiActionMsg); @@ -708,7 +708,7 @@ void CMessages::init() TRANSPORT_CLASS_REGISTER (CChangeCreatureHPMsg); TRANSPORT_CLASS_REGISTER (CChangeCreatureModeMsgImp); TRANSPORT_CLASS_REGISTER (CQueryEgs); - + // setup the callback array CUnifiedNetwork::getInstance()->addCallbackArray( CbArray, sizeof(CbArray)/sizeof(CbArray[0]) ); @@ -732,7 +732,7 @@ void CEnableAggroOnPlayerImp::callback (const std::string &name, NLNET::TService { nlwarning("CEnableAggroOnPlayerImp::callback: unknow entity %s on this AIS !", EntityRowId.toString().c_str()); } - + return; } @@ -794,7 +794,7 @@ void CChangeActionFlagMsgImp::callback (const std::string &name, NLNET::TService { const uint32 size = (uint32)Entities.size(); nlassert( size == ActionFlags.size() && size == Values.size()); - + for (uint32 i = 0 ; i < size ; ++i) { CAIEntityPhysical *const phys=CAIS::instance().getEntityPhysical(Entities[i]); @@ -825,7 +825,7 @@ void CChangeCreatureModeMsgImp::callback (const std::string &name, NLNET::TServi //{ //public: // TDataSetRow EntityRowId; -// +// // virtual void description () // { // className ("CAIAskForInfosOnEntityMsg"); @@ -842,7 +842,7 @@ void CChangeCreatureModeMsgImp::callback (const std::string &name, NLNET::TServi //public: // TDataSetRow EntityRowId; // std::vector Infos; -// +// // virtual void description () // { // className ("CAIInfosOnEntityMsg"); @@ -972,7 +972,7 @@ void CBSAIDeathReport::callback(const std::string &name, NLNET::TServiceId id) } } - + switch(phys->getRyzomType()) { case RYZOMID::npc: @@ -982,10 +982,10 @@ void CBSAIDeathReport::callback(const std::string &name, NLNET::TServiceId id) const CMgrNpc &mgr = spawnGrp.getPersistent().mgr(); spawnGrp.addBotToDespawnAndRespawnTime (&(sb->getPersistent()), spawnGrp.getPersistent().despawnTime(), spawnGrp.getPersistent().respawnTime()); - + if (spawnGrp.getPersistent().getSquadLeader(false)==&sb->getPersistent()) spawnGrp.getPersistent().processStateEvent(mgr.EventSquadLeaderKilled); - + CBotNpc* bot = NLMISC::safe_cast(&(sb->getPersistent())); spawnGrp.botHaveDied (bot); @@ -996,7 +996,7 @@ void CBSAIDeathReport::callback(const std::string &name, NLNET::TServiceId id) { nlinfo("NPC: TRIGGER EVENT BOT KILLED"); } - + spawnGrp.getPersistent().processStateEvent(mgr.EventBotKilled); std::string eventGroupKilled; @@ -1020,7 +1020,7 @@ void CBSAIDeathReport::callback(const std::string &name, NLNET::TServiceId id) std::vector playerAggroable; for (; aggroIt != aggroEnd; ++aggroIt) - { + { if (CMirrors::getEntityId(aggroIt->first).getType() != RYZOMID::player) continue; CAIEntityPhysical* ep = CAIS::instance().getEntityPhysical(aggroIt->first); @@ -1033,7 +1033,7 @@ void CBSAIDeathReport::callback(const std::string &name, NLNET::TServiceId id) continue; playerAggroable.push_back(aggroIt->first); } - + NLNET::CMessage msgout("TRIGGER_WEBIG"); if (!eventBotKilled.empty()) msgout.serial(eventBotKilled); @@ -1107,7 +1107,7 @@ void CAITauntImp::callback (const std::string &name, NLNET::TServiceId id) if (!aggroOwner) return; - + aggroOwner->maximizeAggroFor(PlayerRowId); } @@ -1145,7 +1145,7 @@ void sAggroLost(TDataSetRow playerBot, TDataSetRow targetBot) void sAggroGain(TDataSetRow playerBot, TDataSetRow targetBot) { - CAIEntityPhysical *entity=CAIS::instance().getEntityPhysical(playerBot); // necessary ? + CAIEntityPhysical *entity=CAIS::instance().getEntityPhysical(playerBot); if ( !entity || CMirrors::getEntityId(playerBot).getType()!=RYZOMID::player) return; @@ -1153,6 +1153,9 @@ void sAggroGain(TDataSetRow playerBot, TDataSetRow targetBot) CAIGainAggroMsg msg(targetBot, playerBot, false); msg.send("EGS"); + if (entity->getActionFlags() & RYZOMACTIONFLAGS::InWater) + return; + CAIEntityPhysical *botEntity = CAIEntityPhysicalLocator::getInstance()->getEntity(targetBot); CSpawnBotNpc* bot = dynamic_cast(botEntity); if (bot && bot->getPersistent().getOwner()) { @@ -1170,7 +1173,7 @@ void sAggroGain(TDataSetRow playerBot, TDataSetRow targetBot) CBot* bot = *itBot; CSpawnBot *const sp = bot->getSpawnObj(); if (sp && sp->isAlive()) - { + { CAIGainAggroMsg msg(sp->dataSetRow(), playerBot, true); msg.send("EGS"); } diff --git a/ryzom/server/src/ai_service/state_instance.cpp b/ryzom/server/src/ai_service/state_instance.cpp index 4e170b1fa..3d4b78e65 100644 --- a/ryzom/server/src/ai_service/state_instance.cpp +++ b/ryzom/server/src/ai_service/state_instance.cpp @@ -41,13 +41,13 @@ CAIState const* CStateInstance::getActiveState() const if (!this) return NULL; // ugly! -> to remove date = 19/05/2004. #endif - + if (_PunctualState) // the puntual state is active ! return _PunctualState; - + if (_state) // the normal state is active ! return _state; - + // no state is active ! return NULL; } @@ -110,7 +110,7 @@ void CStateInstance::callScriptCallBack(IScriptContext* caller, TStringId const& AIVM::CByteCodeEntry const* const codeScript = getScriptCallBackPtr(funcName); if (!codeScript || !codeScript->isValid()) return; - + interpretCode(caller, *codeScript); // effectively calls the call back. } @@ -153,15 +153,15 @@ void CStateInstance::dumpVarsAndFunctions(CStringWriter& sw) const sw.append("float variables:"); FOREACHC(varIt, TLogicVarList, _LogicVar) sw.append(" "+CStringMapper::unmap(varIt->first)+" = "+NLMISC::toString(varIt->second)); - + sw.append("string variables:"); FOREACHC(varIt, TStrLogicVarList, _StrLogicVar) sw.append(" "+CStringMapper::unmap(varIt->first)+" = "+varIt->second); - + sw.append("context variables:"); FOREACHC(varIt, TCtxLogicVarList, _CtxLogicVar) sw.append(" "+CStringMapper::unmap(varIt->first)+" = "+NLMISC::toStringPtr(varIt->second)); - + sw.append("callBacks:"); FOREACHC(varIt, TCallBackList, _CallBacks) sw.append(" "+CStringMapper::unmap(varIt->first)); @@ -183,7 +183,7 @@ void CStateInstance::interpretCodeOnChildren(CByteCodeEntry const& codeScriptEnt vector > tmpList; FOREACH(childIt, CPersistentStateInstance::TChildList, getPersistentStateInstance()->childs()) tmpList.push_back((*childIt)->getGroup()); - + FOREACH(childIt, vector >, tmpList) (*childIt)->getPersistentStateInstance()->interpretCode(this, codeScriptEntry); } @@ -195,7 +195,7 @@ IScriptContext* CStateInstance::findContext(NLMISC::TStringId const strId) #endif std::vector grps; this->getGroup()->getAIInstance()->findGroup(grps, CStringMapper::unmap(strId)); - if (grps.size()==1) + if (grps.size() >= 1) return grps.back()->getPersistentStateInstance(); else return NULL; @@ -213,7 +213,7 @@ void CStateInstance::init(CAIState* startState) _state= _PunctualState= _NextPunctualState=NULL; - + _CancelPunctualState = false; _NextState = startState; _LogicVarChanged = false; @@ -244,12 +244,12 @@ void CStateInstance::setGlobalNelVar(std::string const& varId, std::string value void CStateInstance::blockUserEvent(uint32 eventId) { - _UserEventBlocked |= (1 << eventId); + _UserEventBlocked |= (1 << eventId); } void CStateInstance::unblockUserEvent(uint32 eventId) { - _UserEventBlocked &= ~(1 << eventId); + _UserEventBlocked &= ~(1 << eventId); } bool CStateInstance::isUserEventBlocked(uint32 eventId) const @@ -264,15 +264,15 @@ bool CStateInstance::isUserEventBlocked(uint32 eventId) const void CPersistentStateInstance::updateStateInstance() { // deal with timer events ----------------------------------------- - + // Event: State Timeout if (_StateTimeout.testOnce()) processStateEvent(getEventContainer().EventPositionalStateTimeout); - + // Event: Punctual State Timeout if (_PunctualStateTimeout.testOnce()) processStateEvent(getEventContainer().EventPunctualStateTimeout); - + // Event: User Timer n Triggered for (uint i=0;i<4;++i) { @@ -280,7 +280,7 @@ void CPersistentStateInstance::updateStateInstance() continue; processStateEvent(getEventContainer().EventUserTimer[i]); } - + // Event logic var changed @@ -297,9 +297,9 @@ void CPersistentStateInstance::updateStateInstance() } _LogicVarChanged = false; } - + // deal with positional state change ------------------------------ - + // if state change requested (and not in punctual state) then setup new state if (_NextState) { @@ -310,27 +310,27 @@ void CPersistentStateInstance::updateStateInstance() oldState = _state; processStateEvent(getEventContainer().EventEndOfState); } - + // switch state & initalise state status flags _state = _NextState; _NextState = NULL; _StateTimeout.disable(); - + if (_PunctualState || _NextPunctualState) return; - + removeExceptForState(_state); processStateEvent(getEventContainer().EventStartOfState); stateChange(oldState, _state); } - + // deal with start of punctual state ------------------------------ - + // if state change requested then setup new state if (_NextPunctualState) { CAIState const* oldState = NULL; - + breakable { if (_PunctualState) @@ -344,21 +344,21 @@ void CPersistentStateInstance::updateStateInstance() break; } } - + // switch state & initalize state status flags _PunctualState = _NextPunctualState; _NextPunctualState = NULL; _CancelPunctualState = false; _PunctualStateTimeout.disable(); - + // initalize new state CAIState const* const newState = _PunctualState; - + removeExceptForState(newState); processStateEvent(getEventContainer().EventStartOfState, newState); stateChange(oldState, newState); } - + // must be done after start of state if (_FirstBotSpawned) { @@ -366,29 +366,29 @@ void CPersistentStateInstance::updateStateInstance() processStateEvent(getEventContainer().EventFirstBotSpawned); } // deal with end of punctual state -------------------------------- - + if (!_CancelPunctualState) return; - + _CancelPunctualState = false; - + // if there was an active punctual state then cancel it if (!_PunctualState) return; - + // switch state & initalise state status flags _PunctualStateTimeout.disable(); _StateTimeout.resume(); // this line just in case timeout suspended during punctual state - + // close down current state CAIState const* const punctualState = _PunctualState; - + processStateEvent(getEventContainer().EventEndOfState, punctualState); _PunctualState = NULL; - + // this removes obj that depends on state affectation existence. removeExceptForState(_state); - + // specialized virtual state change call. stateChange(punctualState, _state); } diff --git a/ryzom/server/src/input_output_service/chat_manager.cpp b/ryzom/server/src/input_output_service/chat_manager.cpp index 7a9f8f76d..186fb8b68 100644 --- a/ryzom/server/src/input_output_service/chat_manager.cpp +++ b/ryzom/server/src/input_output_service/chat_manager.cpp @@ -770,7 +770,7 @@ void CChatManager::chat( const TDataSetRow& sender, const ucstring& ucstr ) string usedlang = senderLang; - if (EnableDeepL && !senderClient.dontSendTranslation(senderLang)) + if (EnableDeepL) { chatType = "dynamic"; if (ucstr[0] == '>') // Sent directly when prefixed by '>', it's the anti-translation code @@ -790,7 +790,7 @@ void CChatManager::chat( const TDataSetRow& sender, const ucstring& ucstr ) source_lang = mongoText.substr(6, 2); string sourceText = mongoText.substr(9, endOfOriginal-9); strFindReplace(sourceText, ")", "}"); - mongoText = "["+source_lang+"](http://chat.ryzom.com/channel/pub-universe-"+source_lang+"? "+sourceText+") "+mongoText.substr(endOfOriginal+4, mongoText.size()-endOfOriginal-4); + mongoText = "["+source_lang+"](http://chat.ryzom.com/channel/pub-uni-"+source_lang+"? "+sourceText+") "+mongoText.substr(endOfOriginal+4, mongoText.size()-endOfOriginal-4); } else { @@ -813,6 +813,11 @@ void CChatManager::chat( const TDataSetRow& sender, const ucstring& ucstr ) chatInGroup( grpId, ucstr.substr(1), sender ); } + else if (senderClient.dontSendTranslation(senderLang)) + { + sendToAllUni = true; + chatInGroup( grpId, ucstr, sender ); + } else { _Log.displayNL("%s|%s|*|%s-*|%s", "universe", fullName.c_str(), senderLang.c_str(), ucstr.toUtf8().c_str()); @@ -1034,7 +1039,7 @@ void CChatManager::chat( const TDataSetRow& sender, const ucstring& ucstr ) if (haveOriginMessage) // Only send untranslated message canSendChat = false; } - else if (!translatedLang.empty() && translatedLang != SM->getLanguageCodeString(co->Language)) + else if (!translatedLang.empty() && co && translatedLang != SM->getLanguageCodeString(co->Language)) canSendChat = false; } @@ -1157,7 +1162,7 @@ void CChatManager::chatInGroup( TGroupId& grpId, const ucstring& ucstr, const TD if (!areOriginal) continue; } - else if (usedlang != SM->getLanguageCodeString(co->Language)) + else if (co == NULL || usedlang != SM->getLanguageCodeString(co->Language)) continue; } @@ -1921,6 +1926,7 @@ void CChatManager::sendFarChat(const string &name, const ucstring& ucstr, const { string usedlang = ""; + string source_lang = ""; string mongoText = ucstr.toUtf8(); string::size_type endOfOriginal = mongoText.find("}@{"); @@ -1940,15 +1946,17 @@ void CChatManager::sendFarChat(const string &name, const ucstring& ucstr, const else if (chan == "universe") { chatId = "FACTION_"+toUpper(usedlang); - rc_channel = "pub-universe-"; + rc_channel = "pub-uni-"; } - string source_lang = usedlang; + if (endOfOriginal != string::npos) { if (mongoText.size() > 9) source_lang = mongoText.substr(6, 2); + else + source_lang = usedlang; string sourceText = mongoText.substr(9, endOfOriginal-9); strFindReplace(sourceText, ")", "}"); mongoText = "["+source_lang+"](http://chat.ryzom.com/channel/"+rc_channel+source_lang+"? "+sourceText+") "+mongoText.substr(endOfOriginal+4, mongoText.size()-endOfOriginal-4); @@ -1985,7 +1993,7 @@ void CChatManager::sendFarChat(const string &name, const ucstring& ucstr, const NLMISC::CEntityId receiverId = TheDataset.getEntityId(dcc->getClient()->getID()); CCharacterInfos* co = IOS->getCharInfos(receiverId); - if (!EnableDeepL || usedlang.empty() || usedlang == SM->getLanguageCodeString(co->Language)) + if (!EnableDeepL || usedlang.empty() || (co != NULL && usedlang == SM->getLanguageCodeString(co->Language))) sendFarChat((CChatGroup::TGroupType)12, dcc->getClient()->getID(), ucstr.substr(startPos), ucstring("~")+ucstring(name), *chanId); dcc = dcc->getNextChannelSession(); // next session in this channel }