// Ryzom - MMORPG Framework // 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 . #include "stdpch.h" #include "nel/misc/variable.h" #include "nel/misc/path.h" #include "string_manager.h" #include "input_output_service.h" #include "game_share/skills.h" #include "game_share/body.h" #include "game_share/scores.h" #include "game_share/characteristics.h" #include "game_share/damage_types.h" #include "game_share/power_types.h" #include "game_share/ecosystem.h" #include "game_share/people.h" #include "game_share/roles.h" #include "game_share/fame.h" #include "game_share/ryzom_mirror_properties.h" using namespace STRING_MANAGER; using namespace NLMISC; using namespace NLNET; using namespace std; extern CVariable VerboseStringManager; #define LOG if (!VerboseStringManager) {} else nlinfo const char *OperatorNames[] = { "equal", "notEqual", "greater", "greaterEqual", "less", "lessEqual", "nop" }; // --------------- ParameterTraits class ------------------- void CStringManager::CParameterTraits::fillBitMemStream( const CCharacterInfos *charInfo,TLanguages language, const TReplacement &rep, NLMISC::CBitMemStream &bms) { const CStringManager::CEntityWords &ew = SM->getEntityWords(language, ParamId.Type); std::string rowName = NLMISC::strlwr(getParameterId()); uint32 stringId; stringId = ew.getStringId(rowName, rep.Format); bms.serial(stringId); } bool CStringManager::CParameterTraits::eval(CStringManager::TLanguages lang,const CCharacterInfos *charInfo, const TCondition &cond) const { // Default eval only check in words column as property const CStringManager::CEntityWords &ew = SM->getEntityWords(lang, ParamId.Type); uint32 colIndex = ew.getColumnId(cond.Property); if (colIndex == 0xffffffff) { nlwarning("The column %s is unknown in words file for %s", cond.Property.c_str(), getParameterId().c_str()); return false; } // ok, this column exist, retrieve the row uint32 rowIndex = ew.getRowId(NLMISC::strlwr(getParameterId())); if (rowIndex == 0xffffffff) { nlwarning("The entry in table for %s is unknown in words.", getParameterId().c_str()); return false; } uint32 stringId = ew.getStringId(rowIndex, colIndex); const std::string &str = SM->getString(stringId).toString(); NLMISC::strlwr(str); LOG("SM : (paramTraits) eval condition for property %s [%s] %s [%s]", cond.Property.c_str(), str.c_str(), OperatorNames[cond.Operator], cond.ReferenceStr.c_str()); switch(cond.Operator) { case equal: return str == cond.ReferenceStr; case notEqual: return str != cond.ReferenceStr; case greater: return str > cond.ReferenceStr; case greaterEqual: return str >= cond.ReferenceStr; case less: return str < cond.ReferenceStr; case lessEqual: return str <= cond.ReferenceStr; default: nlwarning("Operator %s is not applicable to property %s", OperatorNames[cond.Operator], cond.Property.c_str()); return false; } } class CParameterTraitsEntity : public CStringManager::CParameterTraits { public: CStringManager::CParameterTraits *clone() { return new CParameterTraitsEntity(STRING_MANAGER::entity, "entity"); } CParameterTraitsEntity(STRING_MANAGER::TParamType type, const std::string &typeName) : CParameterTraits(type, typeName) {} bool extractFromMessage(NLNET::CMessage &message, bool debug) { TParam param; if (param.serialParam(debug, message, ParamId.Type)) { EId = param.getEId(); _AIAlias = param.getAIAlias(); return true; } else { EId = CEntityId::Unknown; _AIAlias = 0; return false; } } const std::string &getParameterId() const { static std::string empty; // special case for fauna entity if (EId.getType() == RYZOMID::creature || EId.getType() == RYZOMID::npc) { const NLMISC::CSheetId &sheetId = SM->getSheetId(EId); if (sheetId == NLMISC::CSheetId::Unknown) { nlwarning("The sheet id for creature entity %s is unknown !", EId.toString().c_str()); return empty; } const CStringManager::TSheetInfo &si = SM->getSheetInfo(sheetId); return si.SheetName; } // TODO : We need to found the name of the entity. return empty; } // just a wrapper to base class bool eval(CStringManager::TLanguages lang,const CCharacterInfos *charInfo, const CStringManager::TCondition &cond) const { // Test unknown entity if ((cond.ReferenceInt == 0) && (cond.Property.empty())) { if (cond.Operator == CStringManager::equal) return EId.isUnknownId(); else if (cond.Operator == CStringManager::notEqual) return !EId.isUnknownId(); } // test on race const NLMISC::CSheetId &sheetId = SM->getSheetId(EId); if (sheetId == NLMISC::CSheetId::Unknown) { nlwarning("The sheet id for entity entity %s is unknown !", EId.toString().c_str()); return false; } const CStringManager::TSheetInfo &si = SM->getSheetInfo(sheetId); std::string op1; if (cond.Property == "race") { op1 = si.Race; } else if (cond.Property == "gender") { CCharacterInfos *playerInfo = IOS->getCharInfos(EId); if (playerInfo != 0) { op1 = GSGENDER::toString(playerInfo->getGender()); } } else { return CParameterTraits::eval(lang, charInfo, cond); } NLMISC::strlwr(op1); LOG("SM : (entity) eval condition for property %s [%s] %s [%s]", cond.Property.c_str(), op1.c_str(), OperatorNames[cond.Operator], cond.ReferenceStr.c_str()); switch(cond.Operator) { case CStringManager::equal: return op1 == cond.ReferenceStr; case CStringManager::notEqual: return op1 != cond.ReferenceStr; case CStringManager::less: return op1 < cond.ReferenceStr; case CStringManager::lessEqual: return op1 <= cond.ReferenceStr; case CStringManager::greater: return op1 > cond.ReferenceStr; case CStringManager::greaterEqual: return op1 >= cond.ReferenceStr; default: nlwarning("Operator %s not applicable to creature property %s", OperatorNames[cond.Operator], cond.Property.c_str()); return false; } nlerror("This point of code can never be reach !"); return CParameterTraits::eval(lang, charInfo, cond); } void fillBitMemStream( const CCharacterInfos *charInfo,CStringManager::TLanguages language, const CStringManager::TReplacement &rep, NLMISC::CBitMemStream &bms) { if ( EId == CEntityId::Unknown && _AIAlias != 0) { CAIAliasManager& aiAliasMgr = IOS->getAIAliasManager(); if (aiAliasMgr.is(_AIAlias)) { static const string NAME("name"); CSString format = rep.Format; if (format.left(4) != NAME) { // can't replace this parameter, write a del char const static string s("\010"); uint32 index = SM->storeString(s); bms.serial(index); return; } else { uint32 index ; index = aiAliasMgr.getShortNameIndex(_AIAlias); if (index) { bms.serial(index); return; } index = aiAliasMgr.getTitleIndex(_AIAlias, language); if (index) { bms.serial(index); return; } } // No translated title or translated phrase found send '' // ucstring temp(EId.toString()); const ucstring NoName("''"); uint32 index = SM->storeString(NoName); bms.serial(index); return; } } if (EId.getType() == RYZOMID::player || EId.getType() == RYZOMID::npc) { CCharacterInfos *playerInfo = IOS->getCharInfos(EId); if (playerInfo != 0) { static const string NAME("name"); CSString format = rep.Format; if (format.left(4) != NAME) { // can't replace this parameter, write a del char const static string s("\010"); uint32 index = SM->storeString(s); bms.serial(index); return; } else { if (!playerInfo->ShortName.empty()) { uint32 index = playerInfo->ShortNameIndex; bms.serial(index); return; } if (!playerInfo->Title.empty()) { uint32 index = SM->translateTitle(playerInfo->Title, language); // we must match this index against the function table bms.serial(index); return; } } } } // special case fauna entity or unnamed npc (i.e. npc not registered with a character name, like fauna in npc state machine) if (EId.getType() == RYZOMID::creature || EId.getType() == RYZOMID::npc) { // a big FAKE STRING_MANAGER::TParamType realType = ParamId.Type; ParamId.Type = STRING_MANAGER::creature; CParameterTraits::fillBitMemStream(charInfo, language, rep, bms); // restore normal type ParamId.Type = realType; return; } // no info on the name, just send the EID as string. // ucstring temp(EId.toString()); const ucstring NoName("''"); uint32 index = SM->storeString(NoName); bms.serial(index); } void setDefaultValue() { EId = NLMISC::CEntityId::Unknown; _AIAlias = 0; } }; class CParameterTraitsEnum : public CStringManager::CParameterTraits { public: CParameterTraitsEnum(STRING_MANAGER::TParamType type, const std::string &typeName) : CParameterTraits(type, typeName) {} bool extractFromMessage(NLNET::CMessage &message, bool debug) { TParam param; if (param.serialParam(debug, message, ParamId.Type)) { Enum = param.Enum; return true; } else { setDefaultValue(); return false; } } }; class CParameterTraitsIdentifier : public CStringManager::CParameterTraits { public: CParameterTraitsIdentifier(STRING_MANAGER::TParamType type, const std::string &typeName) : CParameterTraits(type, typeName) {} bool extractFromMessage(NLNET::CMessage &message, bool debug) { TParam param; if (param.serialParam(debug, message, ParamId.Type)) { Identifier = param.Identifier; return true; } else { setDefaultValue(); return false; } } const std::string &getParameterId() const { return Identifier; } void setDefaultValue() { Identifier.clear(); } }; class CParameterTraitsSheet : public CStringManager::CParameterTraits { public: CParameterTraitsSheet(STRING_MANAGER::TParamType type, const std::string &typeName) : CParameterTraits(type, typeName) {} bool extractFromMessage(NLNET::CMessage &message, bool debug) { TParam param; if (param.serialParam(debug, message, ParamId.Type)) { SheetId = param.SheetId; return true; } else { setDefaultValue(); return false; } // message.serial(SheetId); } const std::string &getParameterId() const { // const CStringManager::TSheetInfo &si = SM->getSheetInfo(SheetId); static string sheetName; sheetName = SheetId.toString(); sheetName = CFile::getFilenameWithoutExtension(sheetName); return sheetName; } void setDefaultValue() { SheetId = NLMISC::CSheetId::Unknown; } }; class CParameterTraitsItem : public CParameterTraitsSheet { public: CParameterTraitsItem() : CParameterTraitsSheet(STRING_MANAGER::item, "item") {} CStringManager::CParameterTraits *clone() { return new CParameterTraitsItem(); } /// fill overloaded to deals with ring user defined item with custom names void fillBitMemStream( const CCharacterInfos *charInfo, CStringManager::TLanguages language, const CStringManager::TReplacement &rep, NLMISC::CBitMemStream &bms) { // check if SheetId if in the table or user item const CStringManager::TRingUserItemInfos &itemInfos = SM->getUserItems(); CStringManager::TRingUserItemInfos::const_iterator it(itemInfos.find(SheetId)); if (it != itemInfos.end() && !it->second.empty()) { // this item has some user name, check the aiInstance const vector &userItemInfos = it->second; for (uint i=0; iAIInstance) { // ok, this item is renamed ! // use the user name for a list a predefined column : // name, named, nameda, p, pd if ( rep.Format == "name" || rep.Format == "named" || rep.Format == "nameda" || rep.Format == "p" || rep.Format == "pd") { nlWrite(bms, serial, userItemInfos[i].ItemNameId); } else { // not a valid replacement, return a 'backspace' character static uint32 noString = SM->storeString(ucstring()+ucchar(8)); bms.serial(noString); } /// return here --------------------- return; } } } // normal item name, use the base function instead CParameterTraitsSheet::fillBitMemStream( charInfo, language, rep, bms); } }; class CParameterTraitsSPhrase : public CParameterTraitsSheet { public: CParameterTraitsSPhrase() : CParameterTraitsSheet(STRING_MANAGER::sphrase, "sphrase") {} CStringManager::CParameterTraits *clone() { return new CParameterTraitsSPhrase(); } }; class CParameterTraitsBotName : public CParameterTraitsIdentifier { public: CParameterTraitsBotName() : CParameterTraitsIdentifier(STRING_MANAGER::bot_name, "bot_name") {} CStringManager::CParameterTraits *clone() { return new CParameterTraitsBotName(); } void fillBitMemStream( const CCharacterInfos *charInfo, CStringManager::TLanguages language, const CStringManager::TReplacement &rep, NLMISC::CBitMemStream &bms) { uint32 nameId1 = SM->storeString(Identifier); uint32 nameId2 = SM->translateShortName(nameId1); const ucstring &name = SM->getString(nameId2); if (!name.empty() && name[0] == '$') { // this name is a generic name, translate the title ucstring title = name.substr(1, name.size()-2); nameId2 = SM->translateTitle(title.toString(), language); } // serial the string ID bms.serial(nameId2); } }; class CParameterTraitsPlace : public CParameterTraitsIdentifier { public: CParameterTraitsPlace() : CParameterTraitsIdentifier(STRING_MANAGER::place, "place") {} CStringManager::CParameterTraits *clone() { return new CParameterTraitsPlace(); } }; class CParameterTraitsCreature : public CParameterTraitsEntity { public: CStringManager::CParameterTraits *clone() { return new CParameterTraitsCreature(); } CParameterTraitsCreature() : CParameterTraitsEntity(STRING_MANAGER::creature, "creature") {} const std::string &getParameterId() const { const NLMISC::CSheetId &sheetId = SM->getSheetId(EId); if (sheetId == NLMISC::CSheetId::Unknown) { nlwarning("The sheet id for creature entity %s is unknown !", EId.toString().c_str()); static std::string empty; return empty; } const CStringManager::TSheetInfo &si = SM->getSheetInfo(sheetId); return si.SheetName; // return si.Race; } bool eval(CStringManager::TLanguages lang, const CCharacterInfos *charInfo, const CStringManager::TCondition &cond) const { // Test unknown entity if ((cond.ReferenceInt == 0) && (cond.Property.empty())) { if (cond.Operator == CStringManager::equal) return EId.isUnknownId(); else if (cond.Operator == CStringManager::notEqual) return !EId.isUnknownId(); } // creature can test model name, model gender // 1st, I need to retreive the sheetId from the mirror const NLMISC::CSheetId &sheetId = SM->getSheetId(EId); if (sheetId == NLMISC::CSheetId::Unknown) { nlwarning("The sheet id for creature entity %s is unknown !", EId.toString().c_str()); return false; } const CStringManager::TSheetInfo &si = SM->getSheetInfo(sheetId); std::string op1; if (cond.Property == "name") { op1 = NLMISC::toLower(si.SheetName); } else if (cond.Property == "gender") { op1 = NLMISC::toLower(GSGENDER::toString(si.Gender)); } else { return CParameterTraitsEntity::eval(lang,charInfo, cond); } LOG("SM : (creature) eval condition for property %s [%s] %s [%s]", cond.Property.c_str(), op1.c_str(), OperatorNames[cond.Operator], cond.ReferenceStr.c_str()); switch(cond.Operator) { case CStringManager::equal: return op1 == cond.ReferenceStr; case CStringManager::notEqual: return op1 != cond.ReferenceStr; case CStringManager::less: return op1 < cond.ReferenceStr; case CStringManager::lessEqual: return op1 <= cond.ReferenceStr; case CStringManager::greater: return op1 > cond.ReferenceStr; case CStringManager::greaterEqual: return op1 >= cond.ReferenceStr; default: nlwarning("Operator %s not applicable to creature property %s", OperatorNames[cond.Operator], cond.Property.c_str()); return false; } nlerror("This point of code can never be reach !"); } /* void fillBitMemStream(CStringManager::TLanguages language, const CStringManager::TReplacement &rep, NLMISC::CBitMemStream &bms) { // need to evaluate the name of the creature : name from the sheet id ucstring temp; NLMISC::CSheetId sid = SM->getSheetId(EId); if (sid != NLMISC::CSheetId::Unknown) { const CStringManager::TSheetInfo &si = SM->getSheetInfo(sid); temp = si.DisplayName; if (!temp.empty()) { uint32 index = SM->storeString(temp); bms.serial(index); return; } } // hum, no name available CParameterTraitsEntity::fillBitMemStream(charInfo, rep, bms); } */ }; class CParameterTraitsSkill : public CParameterTraitsEnum { public: CStringManager::CParameterTraits *clone() { return new CParameterTraitsSkill(); } CParameterTraitsSkill() : CParameterTraitsEnum(STRING_MANAGER::skill, "skill") {} const std::string &getParameterId() const { return SKILLS::toString(SKILLS::ESkills(Enum)); } void setDefaultValue() { Enum = SKILLS::unknown; } }; class CParameterTraitsBodyPart : public CParameterTraitsEnum { public: CStringManager::CParameterTraits *clone() { return new CParameterTraitsBodyPart(); } CParameterTraitsBodyPart() : CParameterTraitsEnum(STRING_MANAGER::body_part, "bodypart") {} const std::string &getParameterId() const { return BODY::toString(BODY::TBodyPart(Enum)); } void setDefaultValue() { Enum = BODY::UnknownBodyPart; } }; class CParameterTraitsScore : public CParameterTraitsEnum { public: CStringManager::CParameterTraits *clone() { return new CParameterTraitsScore(); } CParameterTraitsScore() : CParameterTraitsEnum(STRING_MANAGER::score, "score") {} const std::string &getParameterId() const { return SCORES::toString(SCORES::TScores(Enum)); } void setDefaultValue() { Enum = SCORES::unknown; } }; class CParameterTraitsCharacteristic : public CParameterTraitsEnum { public: CStringManager::CParameterTraits *clone() { return new CParameterTraitsCharacteristic(); } CParameterTraitsCharacteristic() : CParameterTraitsEnum(STRING_MANAGER::characteristic, "characteristic") {} const std::string &getParameterId() const { return CHARACTERISTICS::toString(CHARACTERISTICS::TCharacteristics(Enum)); } void setDefaultValue() { Enum = CHARACTERISTICS::Unknown; } }; class CParameterTraitsDamageType : public CParameterTraitsEnum { public: CStringManager::CParameterTraits *clone() { return new CParameterTraitsDamageType(); } CParameterTraitsDamageType() : CParameterTraitsEnum(STRING_MANAGER::damage_type, "damagetype") {} const std::string &getParameterId() const { return DMGTYPE::toString(DMGTYPE::EDamageType(Enum)); } void setDefaultValue() { Enum = DMGTYPE::UNDEFINED; } }; class CParameterTraitsClassificationType : public CParameterTraitsEnum { public: CStringManager::CParameterTraits *clone() { return new CParameterTraitsClassificationType (); } CParameterTraitsClassificationType () : CParameterTraitsEnum(STRING_MANAGER::classification_type, "classificationtype") {} const std::string &getParameterId() const { return DMGTYPE::toString(DMGTYPE::EDamageType(Enum)); } void setDefaultValue() { Enum = EGSPD::CClassificationType::Unknown; } }; class CParameterTraitsPowerType : public CParameterTraitsEnum { public: CStringManager::CParameterTraits *clone() { return new CParameterTraitsPowerType(); } CParameterTraitsPowerType() : CParameterTraitsEnum(STRING_MANAGER::power_type, "powertype") {} const std::string &getParameterId() const { return POWERS::toString(POWERS::TPowerType(Enum)); } void setDefaultValue() { Enum = POWERS::UnknownType; } }; class CParameterTraitsRole : public CParameterTraitsEnum { public: CStringManager::CParameterTraits *clone() { return new CParameterTraitsRole(); } CParameterTraitsRole() : CParameterTraitsEnum(STRING_MANAGER::role, "role") {} const std::string &getParameterId() const { return ROLES::toString(ROLES::ERole(Enum)); } void setDefaultValue() { // TODO : set a default value Enum = ROLES::role_unknown; } }; /* class CParameterTraitsCareer : public CParameterTraitsEnum { public: CStringManager::CParameterTraits *clone() { return new CParameterTraitsCareer(); } CParameterTraitsCareer() : CParameterTraitsEnum(STRING_MANAGER::career, "career") {} const std::string &getParameterId() const { // TODO : use the career enum when it exist ! return ROLES::toString(ROLES::ERole(Enum)); } void setDefaultValue() { Enum = ROLES::role_unknown; } }; */ /* class CParameterTraitsJob : public CParameterTraitsEnum { public: CStringManager::CParameterTraits *clone() { return new CParameterTraitsJob(); } CParameterTraitsJob() : CParameterTraitsEnum(STRING_MANAGER::job, "job") {} const std::string &getParameterId() const { return JOBS::toString(JOBS::TJob(Enum)); } void setDefaultValue() { Enum = JOBS::Unknown; } }; */ class CParameterTraitsEcosystem : public CParameterTraitsEnum { public: CStringManager::CParameterTraits *clone() { return new CParameterTraitsEcosystem(); } CParameterTraitsEcosystem() : CParameterTraitsEnum(STRING_MANAGER::ecosystem, "ecosystem") {} const std::string &getParameterId() const { return ECOSYSTEM::toString(ECOSYSTEM::EECosystem(Enum)); } void setDefaultValue() { Enum = ECOSYSTEM::unknown; } }; class CParameterTraitsRace : public CParameterTraitsEnum { public: CStringManager::CParameterTraits *clone() { return new CParameterTraitsRace(); } CParameterTraitsRace() : CParameterTraitsEnum(STRING_MANAGER::race, "race") {} const std::string &getParameterId() const { return EGSPD::CPeople::toString(EGSPD::CPeople::TPeople(Enum)); } void setDefaultValue() { Enum = EGSPD::CPeople::EndPeople; } }; class CParameterTraitsBrick : public CParameterTraitsSheet { public: CParameterTraitsBrick() : CParameterTraitsSheet(STRING_MANAGER::sbrick, "sbrick") {} CStringManager::CParameterTraits *clone() { return new CParameterTraitsBrick(); } }; class CParameterTraitsOutpostWord : public CParameterTraitsSheet { public: CParameterTraitsOutpostWord() : CParameterTraitsSheet(STRING_MANAGER::outpost, "outpost") {} CStringManager::CParameterTraits *clone() { return new CParameterTraitsOutpostWord(); } const std::string &getParameterId() const { static string sheetName; sheetName = SheetId.toString(); return sheetName; } }; /* class CParameterTraitsBrick : public CParameterTraitsEnum { public: CStringManager::CParameterTraits *clone() { return new CParameterTraitsBrick(); } CParameterTraitsBrick() : CParameterTraitsEnum(STRING_MANAGER::sbrick, "sbrick") {} const std::string &getParameterId() const { // return BRICK_FAMILIES::toString(BRICK_FAMILIES::TBrickFamily(Enum)); return SheetId.toString(); } void setDefaultValue() { Enum = BRICK_FAMILIES::Unknown; } }; */ class CParameterTraitsFaction : public CParameterTraitsEnum { public: CStringManager::CParameterTraits *clone() { return new CParameterTraitsFaction(); } CParameterTraitsFaction() : CParameterTraitsEnum(STRING_MANAGER::faction, "faction") {} const std::string &getParameterId() const { return CStaticFames::getInstance().getFactionName(Enum); } void setDefaultValue() { // TODO : set a default value Enum = 0; } }; class CParameterTraitsGuild : public CParameterTraitsEntity { public: CStringManager::CParameterTraits *clone() { return new CParameterTraitsGuild(); } CParameterTraitsGuild() : CParameterTraitsEntity(STRING_MANAGER::guild, "guild") {} }; class CParameterTraitsPlayer : public CParameterTraitsEntity { public: CStringManager::CParameterTraits *clone() { return new CParameterTraitsPlayer(); } CParameterTraitsPlayer() : CParameterTraitsEntity(STRING_MANAGER::player, "player") {} bool eval(CStringManager::TLanguages lang, const CCharacterInfos *charInfo, const CStringManager::TCondition &cond) const { // Test unknown entity if ((cond.ReferenceInt == 0) && (cond.Property.empty())) { if (cond.Operator == CStringManager::equal) return EId.isUnknownId(); else if (cond.Operator == CStringManager::notEqual) return !EId.isUnknownId(); } // player can test model name, entity name, entity gender // 1st, I need to retrieve the sheetId from the mirror std::string op1; if (cond.Property == "name") { const NLMISC::CSheetId &sheetId = SM->getSheetId(EId); if (sheetId == NLMISC::CSheetId::Unknown) { nlwarning("The sheet id for creature entity %s is unknown !", EId.toString().c_str()); return false; } const CStringManager::TSheetInfo &si = SM->getSheetInfo(sheetId); op1 = NLMISC::toLower(si.SheetName); } else if (cond.Property == "gender") { CCharacterInfos *charInfo = IOS->getCharInfos(EId); if (charInfo == NULL) { nlwarning("Could not find character info for EId %s to check property %s", EId.toString().c_str(), cond.Property.c_str()); return false; } op1 = NLMISC::toLower(GSGENDER::toString(charInfo->getGender())); } else { return CParameterTraitsEntity::eval(lang,charInfo, cond); } LOG("SM : (player) eval condition for property %s [%s] %s [%s]", cond.Property.c_str(), op1.c_str(), OperatorNames[cond.Operator], cond.ReferenceStr.c_str()); switch(cond.Operator) { case CStringManager::equal: return op1 == cond.ReferenceStr; case CStringManager::notEqual: return op1 != cond.ReferenceStr; case CStringManager::less: return op1 < cond.ReferenceStr; case CStringManager::lessEqual: return op1 <= cond.ReferenceStr; case CStringManager::greater: return op1 > cond.ReferenceStr; case CStringManager::greaterEqual: return op1 >= cond.ReferenceStr; default: nlwarning("Operator %s not applicable to player property %s", OperatorNames[cond.Operator], cond.Property.c_str()); return false; } nlerror("This point of code can never be reach !"); } void fillBitMemStream( const CCharacterInfos *charInfo,CStringManager::TLanguages language, const CStringManager::TReplacement &rep, NLMISC::CBitMemStream &bms) { ucstring temp; CCharacterInfos *playerInfo = IOS->getCharInfos(EId); if (playerInfo != 0) { if (!playerInfo->ShortName.empty()) { uint32 index = playerInfo->ShortNameIndex; bms.serial(index); return; } } // hum, no name available CParameterTraitsEntity::fillBitMemStream(charInfo,language, rep, bms); } }; class CParameterTraitsBot : public CParameterTraitsEntity { public: CStringManager::CParameterTraits *clone() { return new CParameterTraitsBot(); } CParameterTraitsBot() : CParameterTraitsEntity(STRING_MANAGER::bot, "bot") {} bool eval(CStringManager::TLanguages lang, const CCharacterInfos *charInfo, const CStringManager::TCondition &cond) const { // Test unknown entity if ((cond.ReferenceInt == 0) && (cond.Property.empty())) { if (cond.Operator == CStringManager::equal) return EId.isUnknownId(); else if (cond.Operator == CStringManager::notEqual) return !EId.isUnknownId(); } // bot can test career and role // 1st, I need to retrieve the sheetId from the mirror // TODO : reuse sheet server when AI fill in correctly ! const NLMISC::CSheetId &sheetId = SM->getSheetServerId(EId); if (sheetId == NLMISC::CSheetId::Unknown) { nlwarning("The sheet id for creature bot %s is unknown !", EId.toString().c_str()); return false; } LOG("Bot %s use server sheet %s", EId.toString().c_str(), sheetId.toString().c_str()); const CStringManager::TSheetInfo &si = SM->getSheetInfo(sheetId); std::string op1; if (cond.Property == "career") { op1 = si.Profile; } else if (cond.Property == "role") { op1 = NLMISC::toLower(si.ChatProfile); } else if (cond.Property == "title") { // we need to retrieve the charInfo CCharacterInfos *ci = IOS->getCharInfos(EId); if (ci != NULL) op1 = NLMISC::toLower(ci->Title); else { nlwarning("No character info for bot %s, can't test property 'title' !", EId.toString().c_str()); return false; } } else { return CParameterTraitsEntity::eval(lang, charInfo, cond); } LOG("SM : (bot) eval condition for property %s [%s] %s [%s]", cond.Property.c_str(), op1.c_str(), OperatorNames[cond.Operator], cond.ReferenceStr.c_str()); switch(cond.Operator) { case CStringManager::equal: return op1 == cond.ReferenceStr; case CStringManager::notEqual: return op1 != cond.ReferenceStr; case CStringManager::less: return op1 < cond.ReferenceStr; case CStringManager::lessEqual: return op1 <= cond.ReferenceStr; case CStringManager::greater: return op1 > cond.ReferenceStr; case CStringManager::greaterEqual: return op1 >= cond.ReferenceStr; default: nlwarning("Operator %s not applicable to player property %s", OperatorNames[cond.Operator], cond.Property.c_str()); return false; } nlerror("This point of code can never be reach !"); } void fillBitMemStream( const CCharacterInfos *charInfo,CStringManager::TLanguages language, const CStringManager::TReplacement &rep, NLMISC::CBitMemStream &bms) { // need to evaluate the name of the bot : should be in the charinfo ucstring temp; CCharacterInfos *botInfo = IOS->getCharInfos(EId); if (botInfo != 0) { if (!botInfo->ShortName.empty()) { uint32 index = botInfo->ShortNameIndex; bms.serial(index); return; } if (!botInfo->Title.empty()) { uint32 index = SM->translateTitle(botInfo->Title, language); bms.serial(index); return; } } // hum, no name available CParameterTraitsEntity::fillBitMemStream(charInfo, language, rep, bms); } }; class CParameterTraitsInteger : public CStringManager::CParameterTraits { public: CStringManager::CParameterTraits *clone() { return new CParameterTraitsInteger(); } CParameterTraitsInteger() : CParameterTraits(STRING_MANAGER::integer, "integer") {} bool extractFromMessage(NLNET::CMessage &message, bool debug) { TParam param; if (param.serialParam(debug, message, ParamId.Type)) { Int = param.Int; return true; } else { setDefaultValue(); return false; } // message.serial(Int); } void fillBitMemStream( const CCharacterInfos *charInfo,CStringManager::TLanguages language, const CStringManager::TReplacement &rep, NLMISC::CBitMemStream &bms) { bms.serial(Int); } const std::string &getParameterId() const { nlstopex(("Never call this !")); static std::string temp = ""; return temp; } bool eval(CStringManager::TLanguages lang, const CCharacterInfos *charInfo, const CStringManager::TCondition &cond) const { switch(cond.Operator) { case CStringManager::equal: return Int == cond.ReferenceInt; case CStringManager::notEqual: return Int != cond.ReferenceInt; case CStringManager::greater: return Int > cond.ReferenceInt; case CStringManager::greaterEqual: return Int >= cond.ReferenceInt; case CStringManager::less: return Int < cond.ReferenceInt; case CStringManager::lessEqual: return Int <= cond.ReferenceInt; default: nlwarning("Operator not valid (%d)", cond.Operator); return false; } } void setDefaultValue() { Int = 0; } }; class CParameterTraitsTime : public CStringManager::CParameterTraits { public: CStringManager::CParameterTraits *clone() { return new CParameterTraitsTime(); } CParameterTraitsTime() : CParameterTraits(STRING_MANAGER::time, "time") {} bool extractFromMessage(NLNET::CMessage &message, bool debug) { TParam param; if (param.serialParam(debug, message, ParamId.Type)) { Time = param.Time; return true; } else { setDefaultValue(); return false; } // message.serial(Time); } void fillBitMemStream( const CCharacterInfos *charInfo,CStringManager::TLanguages language, const CStringManager::TReplacement &rep, NLMISC::CBitMemStream &bms) { bms.serial(Time); } const std::string &getParameterId() const { nlstopex(("Never call this !")); static std::string temp = ""; return temp; } bool eval(CStringManager::TLanguages lang, const CCharacterInfos *charInfo, const CStringManager::TCondition &cond) const { nlwarning("Time parameter can't be conditional"); return false; } void setDefaultValue() { Time = 0; } }; class CParameterTraitsMoney : public CStringManager::CParameterTraits { public: CStringManager::CParameterTraits *clone() { return new CParameterTraitsMoney(); } CParameterTraitsMoney() : CParameterTraits(STRING_MANAGER::money, "money") {} bool extractFromMessage(NLNET::CMessage &message, bool debug) { TParam param; if (param.serialParam(debug, message, ParamId.Type)) { Money = param.Money; return true; } else { setDefaultValue(); return false; } // message.serial(Money); } void fillBitMemStream( const CCharacterInfos *charInfo,CStringManager::TLanguages language, const CStringManager::TReplacement &rep, NLMISC::CBitMemStream &bms) { // TODO : serial only 48 bits bms.serial(Money); } const std::string &getParameterId() const { nlstopex(("Never call this !")); static std::string temp = ""; return temp; } bool eval(CStringManager::TLanguages lang, const CCharacterInfos *charInfo, const CStringManager::TCondition &cond) const { nlwarning("Money parameter can't be conditional"); return false; } void setDefaultValue() { Money = 0; } }; class CParameterTraitsCompass : public CParameterTraitsEnum { public: CStringManager::CParameterTraits *clone() { return new CParameterTraitsCompass(); } CParameterTraitsCompass() : CParameterTraitsEnum(STRING_MANAGER::compass, "compass") {} const std::string &getParameterId() const { // TODO : add an enum for compass dir in game_share static std::string temp = ""; return temp; } void setDefaultValue() { // TODO : set a default value Enum = 0; } }; class CParameterTraitsStringId : public CStringManager::CParameterTraits { public: CStringManager::CParameterTraits *clone() { return new CParameterTraitsStringId(); } CParameterTraitsStringId() : CParameterTraits(STRING_MANAGER::string_id, "string_id") {} bool extractFromMessage(NLNET::CMessage &message, bool debug) { TParam param; if (param.serialParam(debug, message, ParamId.Type)) { StringId = param.StringId; return true; } else { setDefaultValue(); return false; } // message.serial(StringId); } void fillBitMemStream( const CCharacterInfos *charInfo,CStringManager::TLanguages language, const CStringManager::TReplacement &rep, NLMISC::CBitMemStream &bms) { bms.serial(StringId); } const std::string &getParameterId() const { nlstop; static std::string temp = ""; return temp; } bool eval(CStringManager::TLanguages lang, const CCharacterInfos *charInfo, const CStringManager::TCondition &cond) const { switch(cond.Operator) { case CStringManager::equal: return StringId == uint32(cond.ReferenceInt); case CStringManager::notEqual: return StringId != uint32(cond.ReferenceInt); default: nlwarning("Operator %s not applicable to self property %s", OperatorNames[cond.Operator], cond.Property.c_str()); return false; } } void setDefaultValue() { StringId = 0; } }; class CParameterTraitsdyn_string_id : public CStringManager::CParameterTraits { public: CStringManager::CParameterTraits *clone() { return new CParameterTraitsdyn_string_id(); } CParameterTraitsdyn_string_id() : CParameterTraits(STRING_MANAGER::dyn_string_id, "dyn_string_id") {} bool extractFromMessage(NLNET::CMessage &message, bool debug) { TParam param; if (param.serialParam(debug, message, ParamId.Type)) { StringId = param.StringId; return true; } else { setDefaultValue(); return false; } // message.serial(StringId); } void fillBitMemStream( const CCharacterInfos *charInfo,CStringManager::TLanguages language, const CStringManager::TReplacement &rep, NLMISC::CBitMemStream &bms) { bms.serial(StringId); } const std::string &getParameterId() const { nlstop; static std::string temp = ""; return temp; } bool eval(CStringManager::TLanguages lang, const CCharacterInfos *charInfo, const CStringManager::TCondition &cond) const { switch(cond.Operator) { case CStringManager::equal: return StringId == uint32(cond.ReferenceInt); case CStringManager::notEqual: return StringId != uint32(cond.ReferenceInt); default: nlwarning("Operator %s not applicable to self property %s", OperatorNames[cond.Operator], cond.Property.c_str()); return false; } } void setDefaultValue() { StringId = 0; } }; class CParameterTraitsSelf : public CParameterTraitsEntity { public: CStringManager::CParameterTraits *clone() { return new CParameterTraitsSelf(); } CParameterTraitsSelf() : CParameterTraitsEntity(STRING_MANAGER::self, "self") {} bool extractFromMessage(NLNET::CMessage &message, bool debug) { nlwarning("CParameterTraitsSelf can't be received !"); return false; } const std::string &getParameterId() const { // TODO : retreive the entity name... static std::string temp = ""; return temp; } bool eval(CStringManager::TLanguages lang, const CCharacterInfos *charInfo, const CStringManager::TCondition &cond) const { if ( !charInfo ) return false; std::string value; // check if checked property is gender or name if (cond.Property == "gender") { value = NLMISC::toLower(GSGENDER::toString(charInfo->getGender())); } else if (cond.Property == "name") { value = NLMISC::toLower(charInfo->ShortName.toString()); } else { return CParameterTraitsEntity::eval(lang,charInfo, cond); } LOG("SM : (self) eval condition for property %s [%s] %s [%s]", cond.Property.c_str(), value.c_str(), OperatorNames[cond.Operator], cond.ReferenceStr.c_str()); switch(cond.Operator) { case CStringManager::equal: return value == cond.ReferenceStr; case CStringManager::notEqual: return value != cond.ReferenceStr; case CStringManager::less: return value < cond.ReferenceStr; case CStringManager::lessEqual: return value <= cond.ReferenceStr; case CStringManager::greater: return value > cond.ReferenceStr; case CStringManager::greaterEqual: return value >= cond.ReferenceStr; default: nlwarning("Operator %s not applicable to self property %s", OperatorNames[cond.Operator], cond.Property.c_str()); return false; } } void fillBitMemStream( const CCharacterInfos *charInfo,CStringManager::TLanguages language, const CStringManager::TReplacement &rep, NLMISC::CBitMemStream &bms) { // need to evaluate the name of the bot : should be in the charinfo ucstring temp; if (charInfo != 0) { if (!charInfo->Name.empty()) { uint32 index = charInfo->ShortNameIndex; bms.serial(index); return; } } // hum, no name available CParameterTraitsEntity::fillBitMemStream(charInfo, language, rep, bms); } }; class CParameterTraitsCreatureModel : public CParameterTraitsSheet { public: CParameterTraitsCreatureModel() : CParameterTraitsSheet(STRING_MANAGER::creature_model, "creature") {} CStringManager::CParameterTraits *clone() { return new CParameterTraitsItem(); } }; class CParameterTraitsLiteral : public CStringManager::CParameterTraits { public: CParameterTraitsLiteral() : CParameterTraits(STRING_MANAGER::literal, "literal") {} CStringManager::CParameterTraits *clone() { return new CParameterTraitsLiteral(); } /// Return parameter id, ie, the name that is use to identity the data row in the csv file. virtual const std::string &getParameterId() const { nlstop; static const string s; return s; } /// Extract the parameter value from a message. virtual bool extractFromMessage(NLNET::CMessage &message, bool debug) { TParam param; if (param.serialParam(debug, message, ParamId.Type)) { Literal = param.Literal; return true; } else { setDefaultValue(); return false; } } /// Fill a bitmem strean with the parameter value. virtual void fillBitMemStream( const CCharacterInfos *charInfo, CStringManager::TLanguages language, const CStringManager::TReplacement &rep, NLMISC::CBitMemStream &bms) { uint32 id = SM->storeString(Literal); bms.serial(id); } /// Eval a condition with this parameter. // virtual bool eval(TLanguages lang, const CCharacterInfos *charInfo, const TCondition &cond) const; /// set a default value virtual void setDefaultValue() { Literal = ucstring(); } }; class CParameterTraitsTitle : public CParameterTraitsIdentifier { public: CParameterTraitsTitle() : CParameterTraitsIdentifier(STRING_MANAGER::title, "title") {} CStringManager::CParameterTraits *clone() { return new CParameterTraitsTitle(); } }; class CParameterTraitsEventFaction : public CParameterTraitsIdentifier { public: CParameterTraitsEventFaction() : CParameterTraitsIdentifier(STRING_MANAGER::event_faction, "event_faction") {} CStringManager::CParameterTraits *clone() { return new CParameterTraitsEventFaction(); } void fillBitMemStream( const CCharacterInfos *charInfo, CStringManager::TLanguages language, const CStringManager::TReplacement &rep, NLMISC::CBitMemStream &bms) { uint32 eventFactionId = SM->translateEventFaction(Identifier); // serial the string ID bms.serial(eventFactionId); } }; /** * WARNING: the order in this array is very important, and MUST match exactly * the order in the TParamType enum declared in string_manager_sender.h */ std::vector CStringManager::CParameterTraits::_Models; void CStringManager::CParameterTraits::init() { _Models.push_back(new CParameterTraitsItem()); _Models.push_back(new CParameterTraitsPlace()); _Models.push_back(new CParameterTraitsCreature()); _Models.push_back(new CParameterTraitsSkill()); _Models.push_back(new CParameterTraitsRole()); _Models.push_back(new CParameterTraitsEcosystem()); _Models.push_back(new CParameterTraitsRace()); _Models.push_back(new CParameterTraitsBrick()); _Models.push_back(new CParameterTraitsFaction()); _Models.push_back(new CParameterTraitsGuild()); _Models.push_back(new CParameterTraitsPlayer()); _Models.push_back(new CParameterTraitsBot()); _Models.push_back(new CParameterTraitsInteger()); _Models.push_back(new CParameterTraitsTime()); _Models.push_back(new CParameterTraitsMoney()); _Models.push_back(new CParameterTraitsCompass()); _Models.push_back(new CParameterTraitsStringId()); _Models.push_back(new CParameterTraitsdyn_string_id()); _Models.push_back(new CParameterTraitsSelf()); _Models.push_back(new CParameterTraitsCreatureModel()); _Models.push_back(new CParameterTraitsEntity(STRING_MANAGER::entity, "entity")); _Models.push_back(new CParameterTraitsBodyPart()); _Models.push_back(new CParameterTraitsScore()); _Models.push_back(new CParameterTraitsSPhrase()); _Models.push_back(new CParameterTraitsCharacteristic()); _Models.push_back(new CParameterTraitsDamageType()); _Models.push_back(new CParameterTraitsBotName()); _Models.push_back(new CParameterTraitsPowerType()); _Models.push_back(new CParameterTraitsLiteral()); _Models.push_back(new CParameterTraitsTitle()); _Models.push_back(new CParameterTraitsEventFaction()); _Models.push_back(new CParameterTraitsClassificationType()); _Models.push_back(new CParameterTraitsOutpostWord()); } CStringManager::CParameterTraits *CStringManager::CParameterTraits::createParameterTraits(STRING_MANAGER::TParamType type) { for (uint i=0; i<_Models.size(); ++i) { if (_Models[i]->ParamId.Type == type) return _Models[i]->clone(); } nlstop; return 0; } std::vector > CStringManager::CParameterTraits::getParameterTraitsNames() { std::vector > ret; for (uint i=0; i<_Models.size(); ++i) { ret.push_back(std::make_pair(_Models[i]->ParamId.Type, _Models[i]->TypeName)); } return ret; }