// 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 "phrase_utilities_functions.h" #include "egs_mirror.h" // game share #include "game_share/mode_and_behaviour.h" #include "game_share/tick_event_handler.h" #include "game_share/msg_combat_move_service.h" #include "game_share/characteristics.h" // georges #include "nel/georges/u_form.h" #include "nel/georges/u_form_elm.h" #include "nel/georges/u_form_loader.h" // misc #include "nel/misc/command.h" // std #include // #include "player_manager.h" #include "phrase_manager.h" #include "creature_manager.h" #include "egs_globals.h" extern uint8 CMSIsUp; extern CPlayerManager PlayerManager; extern CCreatureManager CreatureManager; extern CGameItemManager GameItemManager; extern CPhraseManager *PhraseManager; extern bool AllowPVP; extern uint8 EntityForcedDefaultLevel; // 0 by default, it's the level of an entity when it has a level 0 (for tests purposes only) extern CGenericXmlMsgHeaderManager GenericMsgManager; using namespace std; using namespace NLGEORGES; using namespace NLMISC; using namespace NLNET; bool VerboseBrickManagerInfo = false; bool VerboseBrickManagerDbg = false; bool AggroLog = false; NLMISC_COMMAND(verboseBrickManagerInfo,"Turn on or off or check the state of verbose brick manager logging (for info)","") { if(args.size()>1) return false; if(args.size()==1) { if(args[0]==string("on")||args[0]==string("ON")||args[0]==string("true")||args[0]==string("TRUE")||args[0]==string("1")) VerboseBrickManagerInfo=true; if(args[0]==string("off")||args[0]==string("OFF")||args[0]==string("false")||args[0]==string("FALSE")||args[0]==string("0")) VerboseBrickManagerInfo=false; } log.displayNL("VerboseBrickManagerInfo is %s",VerboseBrickManagerInfo?"ON":"OFF"); return true; } // debug msg NLMISC_COMMAND(verboseBrickManagerDbg,"Turn on or off or check the state of verbose brick manager logging (for debug)","") { if(args.size()>1) return false; if(args.size()==1) { if(args[0]==string("on")||args[0]==string("ON")||args[0]==string("true")||args[0]==string("TRUE")||args[0]==string("1")) VerboseBrickManagerDbg=true; if(args[0]==string("off")||args[0]==string("OFF")||args[0]==string("false")||args[0]==string("FALSE")||args[0]==string("0")) VerboseBrickManagerDbg=false; } log.displayNL("VerboseBrickManagerDbg is %s",VerboseBrickManagerDbg?"ON":"OFF"); return true; } // aggro msg NLMISC_COMMAND(aggroLog,"Turn on or off aggro log display or check the state of the flag","") { if(args.size()>1) return false; if(args.size()==1) { if(args[0]==string("on")||args[0]==string("ON")||args[0]==string("true")||args[0]==string("TRUE")||args[0]==string("1")) AggroLog=true; if(args[0]==string("off")||args[0]==string("OFF")||args[0]==string("false")||args[0]==string("FALSE")||args[0]==string("0")) AggroLog=false; } log.displayNL("AggroLog is %s",AggroLog?"ON":"OFF"); return true; } namespace PHRASE_UTILITIES { std::string toString(ERange range) { switch(range) { case POINT_BLANK: return std::string("POINT_BLANK"); case SHORT_RANGE: return std::string("SHORT_RANGE"); case MEDIUM_RANGE: return std::string("MEDIUM_RANGE"); case LONG_RANGE: return std::string("LONG_RANGE"); default: return std::string("UNDEFINED"); }; } typedef set< SLocalisation > TLocalisationSet; /// table of damage localisation (take shield into account) TLocalisationSet LocalisationTable; /// the table giving the localisation adjustement for the specified attacker and defender size sint8 LocalisationAdjustments[CREATURE_SIZE::NB_SIZE][CREATURE_SIZE::NB_SIZE]; static string OrientationStrings[]= { "W", "WSW", "SW", "SSW", "S", "SSE", "SE", "ESE", "E", "ENE", "NE", "NNE", "N", "NNW", "NW", "WNW", }; //-------------------------------------------------------------- // entityPtrFromId() //-------------------------------------------------------------- CEntityBase* entityPtrFromId( const CEntityId &id ) { switch( id.getType() ) { case RYZOMID::player: return PlayerManager.getChar( id ); break; case RYZOMID::npc: case RYZOMID::creature: case RYZOMID::kami: return CreatureManager.getCreature( id ); break; default: nlwarning( " entity type %d unknown", id.getType(), id.toString().c_str() ); return 0; } } //-------------------------------------------------------------- // loadLocalisationTable() //-------------------------------------------------------------- void loadLocalisationTable( const std::string &tableName ) { UFormLoader *loader = UFormLoader::createLoader (); CSmartPtr form = loader->loadForm (tableName.c_str()); if ( !form) { nlwarning(" Failed to load the form %s", tableName.c_str() ); return; } // Get the root node, always exist UFormElm &root = form->getRootNode (); const UFormElm *array = NULL; // lines if (root.getNodeByName (&array, "Lines") && array) { // Get array size uint size; array->getArraySize (size); // Get a array value for (uint i=0; igetArrayNode( &line, i) && line) { SLocalisation localisation; // the localisation number line->getValueByName( localisation.LocalisationNumber, "ValueNumber" ); string shield; // the type of shield line->getValueByName( shield, "ShieldType" ); localisation.ShieldType = SHIELDTYPE::stringToShieldType( shield ); string slot; line->getValueByName( slot, "Localisation" ); localisation.Slot = SLOT_EQUIPMENT::stringToSlotEquipment( slot); line->getValueByName( localisation.ShieldIsEffective, "ProtectionWorks" ); LocalisationTable.insert( localisation ); //nlinfo("loadLocalisationTable : for value %d and shield %s, localisation=%s, shield=%d",localisation.LocalisationNumber, shield.c_str(), slot.c_str(), localisation.ShieldIsEffective); } } } } // loadLocalisationTable // //-------------------------------------------------------------- // loadLocalisationSizeAdjusmentTable() //-------------------------------------------------------------- void loadLocalisationSizeAdjusmentTable( const std::string &tableName ) { UFormLoader *loader = UFormLoader::createLoader (); CSmartPtr form = loader->loadForm (tableName.c_str()); if ( !form) { nlwarning(" Failed to load the form %s", tableName.c_str() ); return; } // Get the root node, always exist UFormElm &root = form->getRootNode (); const UFormElm *array = NULL; // lines if (root.getNodeByName (&array, "Table") && array) { // Get array size uint size; array->getArraySize (size); // Get a array value for (uint i=0; igetArrayNode( &line, i) && line) { string attacker; line->getValueByName( attacker, "AttackerSize" ); CREATURE_SIZE::ECreatureSize attackerSize = CREATURE_SIZE::stringToCreatureSize( attacker ); string defender; line->getValueByName( defender, "DefenderSize" ); CREATURE_SIZE::ECreatureSize defenderSize = CREATURE_SIZE::stringToCreatureSize( defender ); sint8 modifier; line->getValueByName( modifier, "Adjustment" ); if ( attackerSize > CREATURE_SIZE::NB_SIZE || defenderSize > CREATURE_SIZE::NB_SIZE || attackerSize < 0 || defenderSize < 0) { nlwarning(" Invalid line, attacker size = %s, defender size = %s", attacker.c_str(), defender.c_str() ); continue; } /// LocalisationAdjustments[attackerSize][defenderSize] = modifier; } } } } // loadLocalisationSizeAdjusmentTable // //-------------------------------------------------------------- // getSuccessChance() //-------------------------------------------------------------- uint8 getSuccessChance( sint32 playerRelativeLevel ) { // clip delta level to min / max value if( playerRelativeLevel > MAX_DELTA_LVL ) playerRelativeLevel = MAX_DELTA_LVL; if( playerRelativeLevel < MIN_DELTA_LVL ) playerRelativeLevel = MIN_DELTA_LVL; return (uint8) CEntityBaseManager::_SuccessXpTable[ MIDDLE_DELTA_LVL - playerRelativeLevel ].SuccessProbability; } // getSuccessChance // //-------------------------------------------------------------- // getSuccessFactor() // Return SF (Success Factor) > 1 if critical success // Return SF = 1 if success // Return 1 < SF < 0 if partial success // Return SF = 0 if Failure // Return SF < 0 if Critical Failure //-------------------------------------------------------------- float getSucessFactor( uint8 chances, uint8 tirage ) { // Check if critical success if( float(CEntityBaseManager::_SuccessTable.CriticalSuccess * chances) / float( CEntityBaseManager::_SuccessTable.CriticalSuccess + CEntityBaseManager::_SuccessTable.Success ) > float(tirage) ) return 1.1f; // Check if Success if( chances > tirage ) return 1.0f; // Check if Partial Success const uint8 pSChance = (uint8) (float(CEntityBaseManager::_SuccessTable.PartialSuccess) / float(CEntityBaseManager::_SuccessTable.PartialSuccess + CEntityBaseManager::_SuccessTable.Failure + CEntityBaseManager::_SuccessTable.CriticalFailure) * (100.0f-chances)); if ( pSChance > (tirage-chances) ) { return ( float(pSChance - tirage + chances) / float(pSChance)); } // Check if Failure if( ( float(CEntityBaseManager::_SuccessTable.PartialSuccess + CEntityBaseManager::_SuccessTable.Failure ) / float(CEntityBaseManager::_SuccessTable.PartialSuccess + CEntityBaseManager::_SuccessTable.Failure + CEntityBaseManager::_SuccessTable.CriticalFailure ) * (100.0f-chances) ) > float(tirage-chances) ) return 0.0f; // stay Critical Failure return -1.0f; } //-------------------------------------------------------------- // testTargetValidityForCombat() //-------------------------------------------------------------- bool testTargetValidityForCombat( const CEntityId &targetId, string &errorCode ) { switch ( targetId.getType() ) { case RYZOMID::player: break; case RYZOMID::creature: case RYZOMID::kami: case RYZOMID::npc: case RYZOMID::mount: { CCreature* entity = CreatureManager.getCreature( targetId ); if (entity == NULL) { nlwarning(" Invalid entity Id %s", targetId.toString().c_str() ); errorCode = "BS_INVALID_TARGET"; return false; } /* // get creature form const CSheetId &sheet = entity->getType(); const CStaticCreatures *creature = CSheets::getCreaturesForm( sheet ); if ( ! creature) { nlwarning(" can't found CStaticCreature for entity %s", targetId.toString().c_str() ); errorCode = "BS_INVALID_TARGET"; return false; } */ if ( ! entity->getContextualProperty().getValue().attackable() ) { errorCode = "BS_TARGET_NOT_ATTACKABLE"; return false; } } break; default: break; }; return true; } // testTargetValidityForCombat // //-------------------------------------------------------------- // getLocalisation() //-------------------------------------------------------------- TPairSlotShield getLocalisation( SHIELDTYPE::EShieldType shield, sint8 adjustement, SLOT_EQUIPMENT::TSlotEquipment forcedSlot) { TPairSlotShield slotShield; SLocalisation local; if ( forcedSlot == SLOT_EQUIPMENT::UNDEFINED) { sint32 randVal = RandomGenerator.rand() + adjustement; if (randVal < 0) randVal = 0; local.LocalisationNumber = randVal%10 + 1; local.ShieldType = shield; TLocalisationSet::iterator it = LocalisationTable.find( local ); if (it != LocalisationTable.end() ) { slotShield.first = (*it).Slot; slotShield.second = (*it).ShieldIsEffective; } else { slotShield.first = SLOT_EQUIPMENT::UNDEFINED; slotShield.second = false; } } else { TLocalisationSet subTable; TLocalisationSet::iterator it; for (it = LocalisationTable.begin() ; it != LocalisationTable.end() ; ++it) { uint8 val = 0; if ( (*it).ShieldType == shield && (*it).Slot == forcedSlot ) { SLocalisation local; local.LocalisationNumber = ++val; local.ShieldType = shield; local.ShieldIsEffective = (*it).ShieldIsEffective; local.Slot = forcedSlot; subTable.insert( local ); } } if ( subTable.empty() == true ) { slotShield.first = SLOT_EQUIPMENT::UNDEFINED; slotShield.second = false; } else { local.LocalisationNumber = 1 + (uint8)RandomGenerator.rand(subTable.size()-1); local.ShieldType = shield; it = subTable.find( local ); if (it != subTable.end() ) { slotShield.first = (*it).Slot; slotShield.second = (*it).ShieldIsEffective; } else { slotShield.first = SLOT_EQUIPMENT::UNDEFINED; slotShield.second = false; } } } INFOLOG(" with shield %d, with forced slot %d, localisation is slot %d, and shield is %d (0=inactive) (random value is %u)", shield, forcedSlot, slotShield.first, slotShield.second, local.LocalisationNumber ); return slotShield; } // getLocalisation // //-------------------------------------------------------------- // getLocalisationSizeAdjustement() //-------------------------------------------------------------- sint8 getLocalisationSizeAdjustement( const CEntityId &attacker, const CEntityId &defender ) { CREATURE_SIZE::ECreatureSize attackerSize, defenderSize; CEntityBase* entity = entityPtrFromId( attacker ); if (entity == NULL) { nlwarning(" Invalid entity Id %s", attacker.toString().c_str() ); return 0; } attackerSize = entity->getSize(); entity = entityPtrFromId( defender ); if (entity == NULL) { nlwarning(" Invalid entity Id %s", defender.toString().c_str() ); return 0; } defenderSize = entity->getSize(); if ( attackerSize > CREATURE_SIZE::NB_SIZE || defenderSize > CREATURE_SIZE::NB_SIZE || attackerSize < 0 || defenderSize < 0) { return 0; } return LocalisationAdjustments[attackerSize][defenderSize]; } // getLocalisationSizeAdjustement // //-------------------------------------------------------------- // getWeaponDamageFactor() //-------------------------------------------------------------- float getWeaponDamageFactor( WEAPONTYPE::EWeaponType type, uint16 quality, uint16 entityLevel ) { if (quality > 21) quality = 21; if (quality == 0) return float(0); switch(type) { case WEAPONTYPE::LIGHT: case WEAPONTYPE::LIGHT_GUN: { if ( entityLevel > 0 && entityLevel > quality) return TableLightMeleeWeaponGenerics[quality-1].secondaryDamageFactor; else return TableLightMeleeWeaponGenerics[quality-1].damageFactor; } break; case WEAPONTYPE::MEDIUM: case WEAPONTYPE::MEDIUM_GUN: { if ( entityLevel > 0 && entityLevel > quality) return TableMediumMeleeWeaponGenerics[quality-1].secondaryDamageFactor; else return TableMediumMeleeWeaponGenerics[quality-1].damageFactor; } break; case WEAPONTYPE::HEAVY: case WEAPONTYPE::HEAVY_GUN: { if ( entityLevel > 0 && entityLevel > quality) return TableHeavyMeleeWeaponGenerics[quality-1].secondaryDamageFactor; else return TableHeavyMeleeWeaponGenerics[quality-1].damageFactor; } break; case WEAPONTYPE::HANDS: return TableLightMeleeWeaponGenerics[quality-1].damageFactor * (float) HANDS_DAMAGE_FACTOR_MULTIPLIER; default: nlwarning(" Unknown weapon type %d, return 0", type); return 0; }; } // getWeaponDamageFactor // //-------------------------------------------------------------- // getArmorCharacteristics() //-------------------------------------------------------------- TPairUInt8UInt16 getArmorCharacteristics( ARMORTYPE::EArmorType type, uint16 quality ) { if (quality > 21) quality = 21; TPairUInt8UInt16 ret; switch(type) { case ARMORTYPE::LIGHT: ret.first = TableLightArmorGenerics[quality-1].percentProtection; ret.second = TableLightArmorGenerics[quality-1].maxProtection; break; case ARMORTYPE::MEDIUM: ret.first = TableMediumArmorGenerics[quality-1].percentProtection; ret.second = TableMediumArmorGenerics[quality-1].maxProtection; break; case ARMORTYPE::HEAVY: ret.first = TableHeavyArmorGenerics[quality-1].percentProtection; ret.second = TableHeavyArmorGenerics[quality-1].maxProtection; break; default: nlwarning(" Unknown armor type %d, return 0", type); ret.first = 0; ret.second = 0; }; return ret; } // getArmorCharacteristics // //-------------------------------------------------------------- // getEntityLevel() //-------------------------------------------------------------- uint32 getEntityLevel( const CEntityId &entityId, SKILLS::ESkills skill, sint32 skillModifier, float skillMultiplier ) { CEntityBase* entity = entityPtrFromId( entityId ); if (entity == NULL) { nlwarning(" Invalid entity Id %s", entityId.toString().c_str() ); return 0; } sint32 level = 0; // skillModifier += entity->getGlobalSkillModifier(); if ( skill < SKILLS::NUM_SKILLS ) { level = (sint32) ( skillMultiplier * float(entity->getSkills()._Skills[ skill ].Current) ); level += skillModifier; if (level < 0) level = 0; } level = getLevelFromSkill(level); if (level == 0 && EntityForcedDefaultLevel > 0) { DEBUGLOG(" ONLY DEBUG : For entity %s, returns a level of %d instead of 0 for skill %s", entityId.toString().c_str(),EntityForcedDefaultLevel, SKILLS::toString(skill).c_str()); return EntityForcedDefaultLevel; } return (uint32)level; } // getEntityLevel // //-------------------------------------------------------------- // getEntityLevel() //-------------------------------------------------------------- uint32 getEntityLevel( const CEntityId &entityId, SCORES::TScores score, sint32 scoreModifier, float scoreMultiplier ) { CEntityBase* entity = entityPtrFromId( entityId ); if (entity == NULL) { nlwarning(" Invalid entity Id %s", entityId.toString().c_str() ); return 0; } uint32 level = 0; if ( score != SCORES::unknown ) { level = (sint32) ( scoreMultiplier * float(entity->getScores()._PhysicalScores[ score ].Current ) ); level += scoreModifier; if (score < 0) level = 0; } level = getLevelFromScore(level); if (level == 0 && EntityForcedDefaultLevel > 0) { DEBUGLOG(" ONLY DEBUG : For entity %s, returns a level of %d instead of 0 for score %s", entityId.toString().c_str(),EntityForcedDefaultLevel, SCORES::toString(score).c_str() ); return EntityForcedDefaultLevel; } return level; } // getEntityLevel // //-------------------------------------------------------------- // getDistance() //-------------------------------------------------------------- double getDistance( const CEntityId &entity1, const CEntityId &entity2 ) { TDataSetRow entityIndex1 = TheDataset.getDataSetRow( entity1 ); if ( !entityIndex1.isValid() || !TheDataset.isDataSetRowStillValid(entityIndex1) ) return -1; CMirrorPropValueRO posX( TheDataset, entityIndex1, DSPropertyPOSX ); const double playerX = (double)posX / 1000.0f; CMirrorPropValueRO posY( TheDataset, entityIndex1, DSPropertyPOSY ); const double playerY = (double)posY / 1000.0f; double targetX, targetY;//, targetZ; // get second entity position /* if (entity2.Type != RYZOMID::position) {*/ TDataSetRow entityIndex2 = TheDataset.getDataSetRow( entity2 ); if ( !entityIndex2.isValid() || !TheDataset.isDataSetRowStillValid(entityIndex2) ) return -1; CMirrorPropValueRO targX( TheDataset, entityIndex2, DSPropertyPOSX ); targetX = (double)targX() / 1000.0f; CMirrorPropValueRO targY( TheDataset, entityIndex2, DSPropertyPOSY ); targetY = (double)targY() / 1000.0f; // INFOLOG("Player position (in meters) : X = %g, Y = %g", playerX, playerY ); INFOLOG("Target position (in meters) : X = %g, Y = %g", targetX, targetY ); const double d = sqrt( sqr(playerX-targetX) + sqr(playerY-targetY) ); //+sqr (playerZ-targetZ) ); INFOLOG("Distance = %g meters", d); return d; } // getDistance // //-------------------------------------------------------------- // sendUpdateBehaviour() //-------------------------------------------------------------- void sendUpdateBehaviour( const CEntityId &entityId, const MBEHAV::CBehaviour &behaviour, bool forceUpdate ) { MBEHAV::CBehaviour b = behaviour; b.Combat.Time = uint16(CTickEventHandler::getGameCycle() >>3); if (behaviour.Behaviour > MBEHAV::COMBAT_BEHAVIOUR_BEGIN && behaviour.Behaviour < MBEHAV::COMBAT_BEHAVIOUR_END) { INFOLOG(" entity %s param : attackintensity = %u, impact intensity = %u, behaviour %s",entityId.toString().c_str(), behaviour.Combat.AttackIntensity, behaviour.Combat.ImpactIntensity, MBEHAV::behaviourToString(behaviour.Behaviour).c_str() ); } else if (behaviour.Behaviour > MBEHAV::MAGIC_CASTING_BEHAVIOUR_BEGIN && behaviour.Behaviour < MBEHAV::MAGIC_END_CASTING_BEHAVIOUR_END) { INFOLOG(" entity %s param : SpellPower = %u, resist = %d, impact intensity = %u, behaviour %s", entityId.toString().c_str(), behaviour.Magic.TargetResists, behaviour.Magic.SpellPower, behaviour.Magic.ImpactIntensity, MBEHAV::behaviourToString(behaviour.Behaviour).c_str() ); } else { INFOLOG(" entity %s, behaviour %s",entityId.toString().c_str(), MBEHAV::behaviourToString(behaviour.Behaviour).c_str() ); } /* switch( entityId.getType() ) { case RYZOMID::player: { //CMessage msgout("SET_BEHAVIOUR"); //msgout.serial( const_cast (entityId) ); //msgout.serial( b ); //sendMessageViaMirror ("OPS", msgout); } break; case RYZOMID::npc: case RYZOMID::creature: case RYZOMID::kami: { //----------TEMP // CMessage msg("SET_BEHAVIOUR"); // msg.serial( const_cast (entityId) ); // msg.serial( b ); // sendMessageViaMirror ("OPS", msg); //----------TEMP // CMessage msgout("U_FIGHT_BEHAVIOUR"); // msgout.serial( const_cast (entityId) ); // string bes = MBEHAV::behaviourToString( behaviour.Behaviour ); //msgout.serialEnum( behaviour ); // msgout.serial( bes ); // sendMessageViaMirror ("AIS", msgout); } break; default: nlwarning( " entity type %d unknown, fail to send update behaviour msg", entityId.getType() ); } */ CEntityBase* entity = PHRASE_UTILITIES::entityPtrFromId( entityId ); if (entity == NULL) { nlwarning(" Invalid entity Id %s", entityId.toString().c_str() ); return; } entity->setBehaviour( b, forceUpdate ); } // sendUpdateBehaviour // //-------------------------------------------------------------- // sendSimpleMessage() //-------------------------------------------------------------- void sendSimpleMessage( const CEntityId &entityId, const std::string &msgName ) { if ( entityId.getType() != RYZOMID::player && entityId.getType() != RYZOMID::chatGroup && entityId.getType() != RYZOMID::dynChatGroup ) return; CMessage msg("STATIC_STRING"); msg.serial( const_cast (entityId) ); set excluded; msg.serialCont( excluded ); msg.serial( const_cast (msgName) ); sendMessageViaMirror ("IOS", msg); INFOLOG("send %s for entity %s",msgName.c_str(), entityId.toString().c_str()); } // sendSimpleMessage // //-------------------------------------------------------------- // sendMessage() //-------------------------------------------------------------- void sendMessage( const NLMISC::CEntityId &entityId, const std::string &msgName, const ucstring &txt ) { if ( entityId.getType() != RYZOMID::player && entityId.getType() != RYZOMID::chatGroup && entityId.getType() != RYZOMID::dynChatGroup ) return; /// TEMP : convert the uctring to a string const string txtStr = txt.toString(); CMessage msg("STATIC_STRING"); msg.serial( const_cast (entityId) ); set excluded; msg.serialCont( excluded ); msg.serial( const_cast (msgName) ); msg.serial( const_cast (txtStr) ); sendMessageViaMirror ("IOS", msg); INFOLOG("send %s (param %s) for entity %s",msgName.c_str(), txt.toString().c_str(), entityId.toString().c_str()); } // sendMessage // //-------------------------------------------------------------- // sendMessage() //-------------------------------------------------------------- void sendMessage( const NLMISC::CEntityId &entityId, const std::string &msgName, const NLMISC::CEntityId &entityIdForText ) { if ( entityId.getType() != RYZOMID::player && entityId.getType() != RYZOMID::chatGroup && entityId.getType() != RYZOMID::dynChatGroup ) return; CMessage msg("STATIC_STRING"); msg.serial( const_cast (entityId) ); set excluded; msg.serialCont( excluded ); msg.serial( const_cast (msgName) ); msg.serial( const_cast (entityIdForText) ); sendMessageViaMirror ("IOS", msg); INFOLOG("send %s (param entity %s) for entity %s",msgName.c_str(), entityIdForText.toString().c_str(), entityId.toString().c_str()); } // sendMessage // //-------------------------------------------------------------- // sendSimpleDynamicChatMessage() //-------------------------------------------------------------- void sendDynamicChatMessage( const CEntityId &entityId, const string &msgText ) { if ( msgText.empty() ) return; if ( entityId.getType() != RYZOMID::player && entityId.getType() != RYZOMID::chatGroup && entityId.getType() != RYZOMID::dynChatGroup ) return; CMessage msg("CHAT_MESSAGE"); TDataSetRow dsr = TheDataset.getDataSetRow(entityId) msg.serial( dsr ); msg.serial( const_cast (msgText) ); sendMessageViaMirror ("IOS", msg); INFOLOG("send %s for entity %s",msgText.c_str(), entityId.toString().c_str()); } // sendSimpleDynamicChatMessage // //-------------------------------------------------------------- // sendCombatResistMessages() //-------------------------------------------------------------- void sendCombatResistMessages( const NLMISC::CEntityId &aggressorId, const NLMISC::CEntityId &victimId ) { // at least the victim or the agressor must be a player, otherwise do not send any messages if ( (aggressorId.getType() != RYZOMID::player) && ( victimId.getType() != RYZOMID::player )) return; string msgName; if ( victimId.getType() == RYZOMID::player) { msgName ="BS_MISSES_YOU_E"; CMessage msgVictim("STATIC_STRING"); msgVictim.serial( const_cast (victimId) ); set excluded; msgVictim.serialCont( excluded ); msgVictim.serial( msgName ); msgVictim.serial( const_cast (aggressorId) ); sendMessageViaMirror ("IOS", msgVictim); INFOLOG("send BS_MISSES_YOU_E with param e=%s for entity %s",aggressorId.toString().c_str(), victimId.toString().c_str()); } if ( aggressorId.getType() == RYZOMID::player) { msgName ="BS_YOU_MISS_E"; CMessage msgAggressor("STATIC_STRING"); msgAggressor.serial( const_cast (aggressorId) ); set excluded; msgAggressor.serialCont( excluded ); msgAggressor.serial( msgName ); msgAggressor.serial( const_cast (victimId) ); sendMessageViaMirror ("IOS", msgAggressor); INFOLOG("send BS_YOU_MISS with for entity %s", aggressorId.toString().c_str()); } // spectators // Send to 'speech' group msgName = "BS_MISSES_EE"; CEntityId speechGroupId; if ( aggressorId.getType() == RYZOMID::player ) { speechGroupId = aggressorId; } else if ( victimId.getType() == RYZOMID::player ) { speechGroupId = victimId; } else return; speechGroupId.setType( RYZOMID::dynChatGroup ); CMessage msgVictim("STATIC_STRING"); msgVictim.serial( speechGroupId ); set excluded; excluded.insert( aggressorId ); excluded.insert( victimId ); msgVictim.serialCont( excluded ); msgVictim.serial( msgName ); msgVictim.serial( const_cast (aggressorId) ); msgVictim.serial( const_cast (victimId) ); sendMessageViaMirror ("IOS", msgVictim); } // sendCombatResistMessages // //-------------------------------------------------------------- // sendDeathMessages() //-------------------------------------------------------------- void sendDeathMessages( const NLMISC::CEntityId &killerId, const NLMISC::CEntityId &deadId ) { // at least the victim or the agressor must be a player, otherwise do not send any messages if ( (killerId.getType() != RYZOMID::player) && ( deadId.getType() != RYZOMID::player )) return; string msgName; if ( killerId.getType() == RYZOMID::player ) { msgName = "OPS_DEATH_KILLER_E"; CMessage msgAggressor("STATIC_STRING"); msgAggressor.serial( const_cast (killerId) ); set excluded; msgAggressor.serialCont( excluded ); msgAggressor.serial( msgName ); msgAggressor.serial( const_cast (deadId) ); sendMessageViaMirror ("IOS", msgAggressor); } if ( deadId.getType() == RYZOMID::player ) { msgName = "OPS_DEATH_KILLED_E"; CMessage msgVictim("STATIC_STRING"); msgVictim.serial( const_cast (deadId) ); set excluded; msgVictim.serialCont( excluded ); msgVictim.serial( msgName ); msgVictim.serial( const_cast (killerId) ); sendMessageViaMirror ("IOS", msgVictim); } // spectators // Send to 'speech' group msgName = "OPS_DEATH_KILL_EE"; CEntityId speechGroupId; if ( deadId.getType() == RYZOMID::player ) { speechGroupId = deadId; } else { speechGroupId = killerId; } speechGroupId.setType( RYZOMID::dynChatGroup ); CMessage msgSpectators("STATIC_STRING"); msgSpectators.serial( speechGroupId ); set excluded; excluded.insert( deadId ); excluded.insert( killerId ); msgSpectators.serialCont( excluded ); msgSpectators.serial( msgName ); msgSpectators.serial( const_cast (killerId) ); msgSpectators.serial( const_cast (deadId) ); sendMessageViaMirror ("IOS", msgSpectators); } // sendDeathMessages // //-------------------------------------------------------------- // sendHitMessages() //-------------------------------------------------------------- void sendHitMessages( const CEntityId &aggressorId, const CEntityId &victimId, sint32 amount, sint32 lostStamina, sint32 lostSap) { // at least the victim or the agressor must be a player, otherwise do not send any messages if ( (aggressorId.getType() != RYZOMID::player) && ( victimId.getType() != RYZOMID::player )) return; if ( !amount && !lostStamina && !lostSap) return; amount = abs(amount); lostStamina = abs(lostStamina); lostSap = abs(lostSap); string msgName; if ( aggressorId.getType() == RYZOMID::player ) { msgName = "BS_YOU_HIT_EI"; CMessage msgAggressor("STATIC_STRING"); msgAggressor.serial( const_cast (aggressorId) ); set excluded; msgAggressor.serialCont( excluded ); msgAggressor.serial( msgName ); msgAggressor.serial( const_cast (victimId) ); msgAggressor.serial( amount ); sendMessageViaMirror ("IOS", msgAggressor); INFOLOG("send BS_YOU_HIT_EI with param e=%s and i=%i for entity %s",victimId.toString().c_str(), amount, aggressorId.toString().c_str()); // lost stamina if (lostStamina>0) { msgName = "EGS_LOSE_STA_EI"; CMessage msgSta("STATIC_STRING"); msgSta.serial( const_cast (aggressorId) ); msgSta.serialCont( excluded ); msgSta.serial( msgName ); msgSta.serial( const_cast (victimId) ); msgSta.serial( lostStamina ); sendMessageViaMirror ("IOS", msgSta); } // lost sap if (lostSap>0) { msgName = "EGS_LOSE_SAP_EI"; CMessage msgSap("STATIC_STRING"); msgSap.serial( const_cast (aggressorId) ); msgSap.serialCont( excluded ); msgSap.serial( msgName ); msgSap.serial( const_cast (victimId) ); msgSap.serial( lostSap ); sendMessageViaMirror ("IOS", msgSap); } } if ( victimId.getType() == RYZOMID::player ) { msgName = "BS_HITS_YOU_EI"; CMessage msgVictim("STATIC_STRING"); msgVictim.serial( const_cast (victimId) ); set excluded; msgVictim.serialCont( excluded ); msgVictim.serial( msgName ); msgVictim.serial( const_cast (aggressorId) ); msgVictim.serial( amount ); sendMessageViaMirror ("IOS", msgVictim); INFOLOG("send BS_HITS_YOU_EI with param e=%s and i=%i for entity %s",aggressorId.toString().c_str(), amount, victimId.toString().c_str()); // lost stamina if (lostStamina>0) { msgName = "EGS_U_LOSE_STA_EI"; CMessage msgSta("STATIC_STRING"); msgSta.serial( const_cast (victimId) ); msgSta.serialCont( excluded ); msgSta.serial( msgName ); msgSta.serial( const_cast (aggressorId) ); msgSta.serial( lostStamina ); sendMessageViaMirror ("IOS", msgSta); } // lost sap if (lostSap>0) { msgName = "EGS_U_LOSE_SAP_EI"; CMessage msgSap("STATIC_STRING"); msgSap.serial( const_cast (victimId) ); msgSap.serialCont( excluded ); msgSap.serial( msgName ); msgSap.serial( const_cast (aggressorId) ); msgSap.serial( lostSap ); sendMessageViaMirror ("IOS", msgSap); } } // spectators // Send to 'speech' group msgName = "BS_HIT_EEI"; CEntityId speechGroupId; if ( aggressorId.getType() == RYZOMID::player ) { speechGroupId = aggressorId; } else { speechGroupId = victimId; } speechGroupId.setType( RYZOMID::dynChatGroup ); CMessage msgVictim("STATIC_STRING"); msgVictim.serial( speechGroupId ); set excluded; excluded.insert( aggressorId ); excluded.insert( victimId ); msgVictim.serialCont( excluded ); msgVictim.serial( msgName ); msgVictim.serial( const_cast (aggressorId) ); msgVictim.serial( const_cast (victimId) ); msgVictim.serial( amount ); sendMessageViaMirror ("IOS", msgVictim); } // sendHitMessages // //-------------------------------------------------------------- // sendCriticalHitMessage() //-------------------------------------------------------------- void sendCriticalHitMessage( const NLMISC::CEntityId &aggressorId, const NLMISC::CEntityId &victimId ) { // at least the victim or the agressor must be a player, otherwise do not send any messages if ( (aggressorId.getType() != RYZOMID::player) && ( victimId.getType() != RYZOMID::player )) return; string msgName; if ( aggressorId.getType() == RYZOMID::player ) { msgName = "EGS_YOU_CRITICAL_HIT_E"; CMessage msgAggressor("STATIC_STRING"); msgAggressor.serial( const_cast (aggressorId) ); set excluded; msgAggressor.serialCont( excluded ); msgAggressor.serial( msgName ); msgAggressor.serial( const_cast (victimId) ); sendMessageViaMirror ("IOS", msgAggressor); } if ( victimId.getType() == RYZOMID::player ) { msgName = "EGS_CRITICAL_HIT_YOU_E"; CMessage msgVictim("STATIC_STRING"); msgVictim.serial( const_cast (victimId) ); set excluded; msgVictim.serialCont( excluded ); msgVictim.serial( msgName ); msgVictim.serial( const_cast (aggressorId) ); sendMessageViaMirror ("IOS", msgVictim); } // spectators // Send to 'speech' group msgName = "EGS_CRITICAL_HIT_EE"; CEntityId speechGroupId; if ( aggressorId.getType() == RYZOMID::player ) { speechGroupId = aggressorId; } else { speechGroupId = victimId; } speechGroupId.setType( RYZOMID::dynChatGroup ); CMessage msgVictim("STATIC_STRING"); msgVictim.serial( speechGroupId ); set excluded; excluded.insert( aggressorId ); excluded.insert( victimId ); msgVictim.serialCont( excluded ); msgVictim.serial( msgName ); msgVictim.serial( const_cast (aggressorId) ); msgVictim.serial( const_cast (victimId) ); sendMessageViaMirror ("IOS", msgVictim); } // sendCriticalHitMessage // //-------------------------------------------------------------- // sendHitNullMessages() //-------------------------------------------------------------- void sendHitNullMessages( const CEntityId &aggressorId, const CEntityId &victimId ) { // at least the victim or the agressor must be a player, otherwise do not send any messages if ( (aggressorId.getType() != RYZOMID::player) && ( victimId.getType() != RYZOMID::player )) return; string msgName; if ( aggressorId.getType() == RYZOMID::player ) { msgName = "BS_YOU_HIT_NULL_E"; CMessage msgAggressor("STATIC_STRING"); msgAggressor.serial( const_cast (aggressorId) ); set excluded; msgAggressor.serialCont( excluded ); msgAggressor.serial( msgName ); msgAggressor.serial( const_cast (victimId) ); sendMessageViaMirror ("IOS", msgAggressor); INFOLOG("send BS_YOU_HIT_NULL_E with param e=%s for entity %s",victimId.toString().c_str(), aggressorId.toString().c_str()); } if ( victimId.getType() == RYZOMID::player ) { msgName = "BS_HITS_YOU_NULL_E"; CMessage msgVictim("STATIC_STRING"); msgVictim.serial( const_cast (victimId) ); set excluded; msgVictim.serialCont( excluded ); msgVictim.serial( msgName ); msgVictim.serial( const_cast (aggressorId) ); sendMessageViaMirror ("IOS", msgVictim); INFOLOG("send BS_HITS_YOU_EI with param e=%s for entity %s",aggressorId.toString().c_str(), victimId.toString().c_str()); } // spectators // Send to 'speech' group msgName = "BS_HIT_NULL_EE"; CEntityId speechGroupId; if ( aggressorId.getType() == RYZOMID::player ) { speechGroupId = aggressorId; } else { speechGroupId = victimId; } speechGroupId.setType( RYZOMID::dynChatGroup ); CMessage msgVictim("STATIC_STRING"); msgVictim.serial( speechGroupId ); set excluded; excluded.insert( aggressorId ); excluded.insert( victimId ); msgVictim.serialCont( excluded ); msgVictim.serial( msgName ); msgVictim.serial( const_cast (aggressorId) ); msgVictim.serial( const_cast (victimId) ); sendMessageViaMirror ("IOS", msgVictim); } // sendHitNullMessages // //-------------------------------------------------------------- // sendFumbleMessage() //-------------------------------------------------------------- void sendFumbleMessage( const NLMISC::CEntityId &aggressorId, const NLMISC::CEntityId &victimId ) { // at least the victim or the agressor must be a player, otherwise do not send any messages if ( (aggressorId.getType() != RYZOMID::player) && ( victimId.getType() != RYZOMID::player )) return; string msgName; if ( aggressorId.getType() == RYZOMID::player ) { msgName = "EGS_YOU_FUMBLE"; CMessage msgAggressor("STATIC_STRING"); msgAggressor.serial( const_cast (aggressorId) ); set excluded; msgAggressor.serialCont( excluded ); msgAggressor.serial( msgName ); sendMessageViaMirror ("IOS", msgAggressor); } if ( victimId.getType() == RYZOMID::player ) { msgName = "EGS_ENEMY_FUMBLE_E"; CMessage msgVictim("STATIC_STRING"); msgVictim.serial( const_cast (victimId) ); set excluded; msgVictim.serialCont( excluded ); msgVictim.serial( msgName ); msgVictim.serial( const_cast (aggressorId) ); sendMessageViaMirror ("IOS", msgVictim); } // spectators // Send to 'speech' group msgName = "EGS_FUMBLE_E"; CEntityId speechGroupId; if ( aggressorId.getType() == RYZOMID::player ) { speechGroupId = aggressorId; } else { speechGroupId = victimId; } speechGroupId.setType( RYZOMID::dynChatGroup ); CMessage msgVictim("STATIC_STRING"); msgVictim.serial( speechGroupId ); set excluded; excluded.insert( aggressorId ); excluded.insert( victimId ); msgVictim.serialCont( excluded ); msgVictim.serial( msgName ); sendMessageViaMirror ("IOS", msgVictim); } // sendFumbleMessage // //-------------------------------------------------------------- // sendEngageMessages() //-------------------------------------------------------------- void sendEngageMessages( const NLMISC::CEntityId &aggressorId, const NLMISC::CEntityId &victimId ) { // at least the victim or the agressor must be a player, otherwise do not send any messages if ( (aggressorId.getType() != RYZOMID::player) && ( victimId.getType() != RYZOMID::player )) return; string msgName; if ( aggressorId.getType() == RYZOMID::player ) { msgName = "BS_YOU_ATTACK_E"; CMessage msgAggressor("STATIC_STRING"); msgAggressor.serial( const_cast (aggressorId) ); set excluded; msgAggressor.serialCont( excluded ); msgAggressor.serial( msgName ); msgAggressor.serial( const_cast (victimId) ); sendMessageViaMirror ("IOS", msgAggressor); } if ( victimId.getType() == RYZOMID::player ) { msgName = "BS_ATTACKS_YOU_E"; CMessage msgVictim("STATIC_STRING"); msgVictim.serial( const_cast (victimId) ); set excluded; msgVictim.serialCont( excluded ); msgVictim.serial( msgName ); msgVictim.serial( const_cast (aggressorId) ); sendMessageViaMirror ("IOS", msgVictim); } // spectators // Send to 'speech' group msgName = "BS_ATTACKS_EE"; CEntityId speechGroupId; if ( aggressorId.getType() == RYZOMID::player ) { speechGroupId = aggressorId; } else { speechGroupId = victimId; } speechGroupId.setType( RYZOMID::dynChatGroup ); CMessage msgVictim("STATIC_STRING"); msgVictim.serial( speechGroupId ); set excluded; excluded.insert( aggressorId ); excluded.insert( victimId ); msgVictim.serialCont( excluded ); msgVictim.serial( msgName ); msgVictim.serial( const_cast (aggressorId) ); msgVictim.serial( const_cast (victimId) ); sendMessageViaMirror ("IOS", msgVictim); } // sendEngageMessages // //-------------------------------------------------------------- // sendDisengageMessages() //-------------------------------------------------------------- void sendDisengageMessages( const NLMISC::CEntityId &aggressorId, const NLMISC::CEntityId &victimId ) { // at least the victim or the agressor must be a player, otherwise do not send any messages if ( (aggressorId.getType() != RYZOMID::player) && ( victimId.getType() != RYZOMID::player )) return; string msgName; if ( aggressorId.getType() == RYZOMID::player ) { msgName = "BS_YOU_END_ATTACK_E"; CMessage msgAggressor("STATIC_STRING"); msgAggressor.serial( const_cast (aggressorId) ); set excluded; msgAggressor.serialCont( excluded ); msgAggressor.serial( msgName ); msgAggressor.serial( const_cast (victimId) ); sendMessageViaMirror ("IOS", msgAggressor); } if ( victimId.getType() == RYZOMID::player ) { msgName = "BS_END_ATTACKS_YOU_E"; CMessage msgVictim("STATIC_STRING"); msgVictim.serial( const_cast (victimId) ); set excluded; msgVictim.serialCont( excluded ); msgVictim.serial( msgName ); msgVictim.serial( const_cast (aggressorId) ); sendMessageViaMirror ("IOS", msgVictim); } // spectators // Send to 'speech' group msgName = "BS_END_ATTACKS_EE"; CEntityId speechGroupId; if ( aggressorId.getType() == RYZOMID::player ) { speechGroupId = aggressorId; } else { speechGroupId = victimId; } speechGroupId.setType( RYZOMID::dynChatGroup ); CMessage msgVictim("STATIC_STRING"); msgVictim.serial( speechGroupId ); set excluded; excluded.insert( aggressorId ); excluded.insert( victimId ); msgVictim.serialCont( excluded ); msgVictim.serial( msgName ); msgVictim.serial( const_cast (aggressorId) ); msgVictim.serial( const_cast (victimId) ); sendMessageViaMirror ("IOS", msgVictim); } // sendDisengageMessages // //-------------------------------------------------------------- // engageTargetInMelee() //-------------------------------------------------------------- bool engageTargetInMelee( const CEntityId &entityId , const CEntityId &targetId , sint8 mode) { if ( targetId == CEntityId::Unknown ) { return false; } // check target is alive?? // indicate the new engaged target (for player only) if ( entityId.getType() == RYZOMID::player) { CCharacter *ch = PlayerManager.getChar( entityId ); if (ch == NULL) { nlwarning(" Invalid char Id %s", entityId.toString().c_str() ); return false; } ch->setFightingTarget( targetId ); } //CBrickSentenceManager::engageMelee( entityId, targetId ); PhraseManager->engageMelee( TheDataset.getDataSetRow(entityId), TheDataset.getDataSetRow(targetId) ); return true; } // engageTargetInMelee // //-------------------------------------------------------------- // engageTargetRange() //-------------------------------------------------------------- bool engageTargetRange( const CEntityId &entityId , const CEntityId &targetId ) { if ( targetId == CEntityId::Unknown ) { return false; } // check target is alive?? //CBrickSentenceManager::engageRange( entityId, targetId ); PhraseManager->engageRange( TheDataset.getDataSetRow(entityId), TheDataset.getDataSetRow(targetId) ); // INFOLOG(" entity %s engage entity %s in range combat",entityId.toString().c_str(),targetId.toString().c_str() ); // indicate the new engaged target (for player only) if ( entityId.getType() == RYZOMID::player) { CCharacter *ch = PlayerManager.getChar( entityId ); if (ch == NULL) { nlwarning(" Invalid char Id %s", entityId.toString().c_str() ); return false; } ch->setFightingTarget( targetId ); } return true; } // engageTargetRange // //-------------------------------------------------------------- // getImpactIntensity() //-------------------------------------------------------------- INTENSITY_TYPE::TImpactIntensity getImpactIntensity( sint32 impact, const TDataSetRow &victimRowId, SCORES::TScores score ) { if (impact == 0) return INTENSITY_TYPE::IMPACT_NONE; if (impact < 0) impact = impact * (-1); if ( score >= SCORES::NUM_SCORES) { nlwarning(" Unknown score %d", score); return INTENSITY_TYPE::IMPACT_NONE; } CEntityBase* entity = CEntityBaseManager::getEntityBasePtr( victimRowId ); if (entity == NULL) { nlwarning(" Invalid entity row %u", victimRowId.getIndex() ); return INTENSITY_TYPE::IMPACT_NONE; } const sint32 scoreMax = entity->getScores()._PhysicalScores[ score ].Max; // percentage uint32 percent = (uint32) fabs(100 * (double)impact / (double)scoreMax ); if (percent < 2) return INTENSITY_TYPE::IMPACT_INSIGNIFICANT; else if (percent < 5) return INTENSITY_TYPE::IMPACT_VERY_WEAK; else if (percent < 10) return INTENSITY_TYPE::IMPACT_WEAK; else if (percent < 20) return INTENSITY_TYPE::IMPACT_AVERAGE; else if (percent < 30) return INTENSITY_TYPE::IMPACT_STRONG; else if (percent < 40) return INTENSITY_TYPE::IMPACT_VERY_STRONG; else return INTENSITY_TYPE::IMPACT_HUGE; } // getImpactIntensity // //-------------------------------------------------------------- // getAttackIntensity() //-------------------------------------------------------------- INTENSITY_TYPE::TAttackIntensity getAttackIntensity( uint32 attackLevel ) { if (attackLevel < 2) return INTENSITY_TYPE::NONE; else if (attackLevel < 5) return INTENSITY_TYPE::WEAK; else if (attackLevel < 10) return INTENSITY_TYPE::STANDARD; else return INTENSITY_TYPE::STRONG; } // getAttackIntensity // //-------------------------------------------------------------- // getOrientationString() //-------------------------------------------------------------- std::string getOrientationString( const NLMISC::CVector &dir) { return getOrientationString( (sint32)dir.x, (sint32)dir.y ); } // getOrientationString // //-------------------------------------------------------------- // getOrientationString() //-------------------------------------------------------------- std::string getOrientationString( sint32 x, sint32 y) { float angle = (float)(atan2(y, x)); //get the direction uint direction =(uint) ( 8.0f* (angle + Pi)/(Pi) ); if (direction>15) { nlwarning("Direction for compass should never be >15"); return ""; } return OrientationStrings[direction]; } // getOrientationString // //-------------------------------------------------------------- // getEntityCurrentAction() //-------------------------------------------------------------- ENTITY_ACTION::EEntityAction getEntityCurrentAction( const NLMISC::CEntityId &entityId) { // test melee combat TDataSetRow targetRowId = PhraseManager->getEntityEngagedMeleeBy( TheDataset.getDataSetRow(entityId) ); //if (targetId != CEntityId::Unknown ) if (targetRowId.isValid() && TheDataset.isDataSetRowStillValid(targetRowId)) { return ENTITY_ACTION::MELEE_COMBAT; } // test range combat //targetId = CBrickSentenceManager::getEntityEngagedRangeBy( targetId ); targetRowId = PhraseManager->getEntityEngagedRangeBy( TheDataset.getDataSetRow(entityId) ); //if (targetId != CEntityId::Unknown ) if (targetRowId.isValid() && TheDataset.isDataSetRowStillValid(targetRowId)) { return ENTITY_ACTION::RANGE_COMBAT; } /// \todo Malkav : test faber/tracking/casting/walking and running CEntityBase* entity = entityPtrFromId( entityId ); if (entity == NULL) { nlwarning(" Invalid entity Id %s", entityId.toString().c_str() ); return ENTITY_ACTION::IDLE; } const MBEHAV::CBehaviour &behaviour = entity->getBehaviour(); switch( behaviour.Behaviour ) { case MBEHAV::HARVESTING: return ENTITY_ACTION::HARVESTING; break; case MBEHAV::FABER: case MBEHAV::REPAIR: case MBEHAV::REFINE: return ENTITY_ACTION::DOING_FABER; break; default: { /// Problem : how to detect a casting entity when this entity use the suffix tryker brick 'hide' ??? :'( if (behaviour.Behaviour >= MBEHAV::MAGIC_CASTING_BEHAVIOUR_BEGIN && behaviour.Behaviour < MBEHAV::MAGIC_END_CASTING_BEHAVIOUR_BEGIN) return ENTITY_ACTION::CASTING; } break; }; // by default : return IDLE return ENTITY_ACTION::IDLE; } // getEntityCurrentAction // //-------------------------------------------------------------- // testOffensiveActionAllowed //-------------------------------------------------------------- bool testOffensiveActionAllowed( const NLMISC::CEntityId &actorId, const NLMISC::CEntityId &targetId, string &errorCode ) { switch ( targetId.getType() ) { case RYZOMID::player: { if (actorId.getType() == RYZOMID::player) { if (!AllowPVP) errorCode = "EGS_PVP_NOT_ALLOWED"; return AllowPVP; } } break; case RYZOMID::creature: case RYZOMID::mount: case RYZOMID::kami: case RYZOMID::npc: { CEntityBase* entity = CreatureManager.getCreature( targetId ); if (entity == NULL) { nlwarning(" Invalid entity Id %s", targetId.toString().c_str() ); errorCode = "BS_INVALID_TARGET"; return false; } /*// get creature form const CSheetId &sheet = entity->getType(); const CStaticCreatures *creature = CSheets::getCreaturesForm( sheet ); if ( ! creature) { nlwarning(" can't found CStaticCreature for entity %s", targetId.toString().c_str() ); errorCode = "BS_INVALID_TARGET"; return false; } if ( ! creature->properties.attackable() ) { errorCode = "BS_TARGET_NOT_ATTACKABLE"; return false; } */ if (!entity->getContextualProperty().getValue().attackable()) { errorCode = "BS_TARGET_NOT_ATTACKABLE"; return false; } } break; default: break; }; return true; } // testOffensiveActionAllowed // //-------------------------------------------------------------- // sendScoreModifierSpellMessage //-------------------------------------------------------------- void sendScoreModifierSpellMessage( CEntityBase * aggressor, CEntityBase* victim, sint32 value, SCORES::TScores score, ACTNATURE::EActionNature nature ) { nlassert(aggressor); nlassert(victim); // at least the victim or the agressor must be a player, otherwise do not send any messages if ( (aggressor->getId().getType() != RYZOMID::player) && ( victim->getId().getType() != RYZOMID::player )) return; string msgAgressor; string msgVictim; switch (nature ) { case ACTNATURE::OFFENSIVE: switch(score) { case SCORES::sap: msgVictim = "MAGIC_U_SUFFER_OFFENSIVE_SPELL_E_SAP"; msgAgressor = "MAGIC_U_CAST_OFFENSIVE_SPELL_E_SAP"; break; case SCORES::stamina: msgVictim = "MAGIC_U_SUFFER_OFFENSIVE_SPELL_E_STA"; msgAgressor = "MAGIC_U_CAST_OFFENSIVE_SPELL_E_STA"; break; case SCORES::hit_points: msgVictim = "MAGIC_U_SUFFER_OFFENSIVE_SPELL_E_HP"; msgAgressor = "MAGIC_U_CAST_OFFENSIVE_SPELL_E_HP"; break; default: nlwarning(" invalid scrore %s", SCORES::toString(score).c_str() ); } break; case ACTNATURE::DEFENSIVE: switch(score) { case SCORES::sap: msgVictim = "MAGIC_U_SUFFER_HEAL_SPELL_E_SAP"; msgAgressor = "MAGIC_U_CAST_HEAL_SPELL_E_SAP"; break; case SCORES::stamina: msgVictim = "MAGIC_U_SUFFER_HEAL_SPELL_E_STA"; msgAgressor = "MAGIC_U_CAST_HEAL_SPELL_E_STA"; break; case SCORES::hit_points: msgVictim = "MAGIC_U_SUFFER_HEAL_SPELL_E_HP"; msgAgressor = "MAGIC_U_CAST_HEAL_SPELL_E_HP"; break; default: nlwarning(" invalid scrore %s", SCORES::toString(score).c_str() ); } break; }; if ( aggressor->getId().getType() == RYZOMID::player ) { CCharacter::sendMessageToClient(aggressor->getId(),msgAgressor,victim->getId(),(uint32)value ); } if ( victim->getId().getType() == RYZOMID::player ) { CCharacter::sendMessageToClient(victim->getId(),msgVictim,aggressor->getId(),(uint32)value ); } } // sendScoreModifierSpellMessage // //-------------------------------------------------------------- // sendSpellResistMessages() //-------------------------------------------------------------- void sendSpellResistMessages( const TDataSetRow &aggressorRowId, const TDataSetRow &victimRowId ) { if ( !aggressorRowId.isValid() || !TheDataset.isDataSetRowStillValid(aggressorRowId) || !victimRowId.isValid() || !TheDataset.isDataSetRowStillValid(victimRowId) ) return; CEntityId victimId = TheDataset.getEntityId(victimRowId); CEntityId aggressorId = TheDataset.getEntityId(aggressorRowId); // at least the victim or the agressor must be a player, otherwise do not send any messages if ( (aggressorId.getType() != RYZOMID::player) && ( victimId.getType() != RYZOMID::player )) return; string msgName; if ( victimId.getType() == RYZOMID::player) { msgName ="EGS_TARGET_CASTING_RESIST_E"; CMessage msgVictim("STATIC_STRING"); msgVictim.serial( const_cast (victimId) ); set excluded; msgVictim.serialCont( excluded ); msgVictim.serial( msgName ); msgVictim.serial( const_cast (aggressorId) ); sendMessageViaMirror ("IOS", msgVictim); } if ( aggressorId.getType() == RYZOMID::player) { msgName ="EGS_ACTOR_CASTING_RESIST_E"; CMessage msgAggressor("STATIC_STRING"); msgAggressor.serial( const_cast (aggressorId) ); set excluded; msgAggressor.serialCont( excluded ); msgAggressor.serial( msgName ); msgAggressor.serial( const_cast (victimId) ); sendMessageViaMirror ("IOS", msgAggressor); } // send message to spectators // Send to 'speech' group msgName ="EGS_SPECT_CASTING_RESIST_EE"; CEntityId speechGroupId; if ( victimId.getType() == RYZOMID::player ) { speechGroupId = victimId; } else { speechGroupId = aggressorId; } speechGroupId.setType( RYZOMID::dynChatGroup ); CMessage msg("STATIC_STRING"); msg.serial( speechGroupId ); set excluded; excluded.insert( aggressorId ); excluded.insert( victimId ); msg.serialCont( excluded ); msg.serial( msgName ); msg.serial( const_cast (victimId) ); msg.serial( const_cast (aggressorId) ); sendMessageViaMirror ("IOS", msg); } // sendSpellResistMessages // //-------------------------------------------------------------- // sendSpellBeginCastMessages() //-------------------------------------------------------------- void sendSpellBeginCastMessages( const TDataSetRow &aggressorRowId, const TDataSetRow &victimRowId, ACTNATURE::EActionNature nature ) { if ( !aggressorRowId.isValid() || !TheDataset.isDataSetRowStillValid(aggressorRowId) || !victimRowId.isValid() || !TheDataset.isDataSetRowStillValid(victimRowId) ) return; CEntityId victimId = TheDataset.getEntityId(victimRowId); CEntityId aggressorId = TheDataset.getEntityId(aggressorRowId); // at least the victim or the agressor must be a player, otherwise do not send any messages if ( (aggressorId.getType() != RYZOMID::player) && ( victimId.getType() != RYZOMID::player )) return; string msgName; bool self = (aggressorId == victimId); if ( aggressorId.getType() == RYZOMID::player) { switch( nature ) { case ACTNATURE::NEUTRAL: msgName = self ? "EGS_ACTOR_BEGIN_SELFCAST_NEUTRAL" : "EGS_ACTOR_BEGIN_CASTING_NEUTRAL_E"; break; case ACTNATURE::DEFENSIVE: msgName = self ? "EGS_ACTOR_BEGIN_SELFCAST_GOOD" : "EGS_ACTOR_BEGIN_CASTING_GOOD_E"; break; case ACTNATURE::OFFENSIVE: default: msgName ="EGS_ACTOR_BEGIN_CASTING_BAD_E"; }; CMessage msgVictim("STATIC_STRING"); msgVictim.serial( const_cast (aggressorId) ); set excluded; msgVictim.serialCont( excluded ); msgVictim.serial( msgName ); if (!self) msgVictim.serial( const_cast (victimId) ); sendMessageViaMirror ("IOS", msgVictim); } if (self) return; if ( victimId.getType() == RYZOMID::player) { switch( nature ) { case ACTNATURE::NEUTRAL: msgName = "EGS_TARGET_BEGIN_CASTING_NEUTRAL_E"; break; case ACTNATURE::DEFENSIVE: msgName = "EGS_TARGET_BEGIN_CASTING_GOOD_E"; break; case ACTNATURE::OFFENSIVE: default: msgName ="EGS_TARGET_BEGIN_CASTING_BAD_E"; }; CMessage msgAggressor("STATIC_STRING"); msgAggressor.serial( const_cast (victimId) ); set excluded; msgAggressor.serialCont( excluded ); msgAggressor.serial( msgName ); msgAggressor.serial( const_cast (aggressorId) ); sendMessageViaMirror ("IOS", msgAggressor); } // send message to spectators // Send to 'speech' group switch( nature ) { case ACTNATURE::NEUTRAL: msgName = "EGS_SPECT_BEGIN_CASTING_NEUTRAL_EE"; break; case ACTNATURE::DEFENSIVE: msgName = "EGS_SPECT_BEGIN_CASTING_GOOD_EE"; break; case ACTNATURE::OFFENSIVE: default: msgName ="EGS_SPECT_BEGIN_CASTING_BAD_EE"; }; CEntityId speechGroupId; if ( victimId.getType() == RYZOMID::player ) { speechGroupId = victimId; } else { speechGroupId = aggressorId; } speechGroupId.setType( RYZOMID::dynChatGroup ); CMessage msg("STATIC_STRING"); msg.serial( speechGroupId ); set excluded; excluded.insert( aggressorId ); excluded.insert( victimId ); msg.serialCont( excluded ); msg.serial( msgName ); msg.serial( const_cast (aggressorId) ); msg.serial( const_cast (victimId) ); sendMessageViaMirror ("IOS", msg); } // sendSpellBeginCastMessages // //-------------------------------------------------------------- // sendSpellSuccessMessages() //-------------------------------------------------------------- void sendSpellSuccessMessages( const TDataSetRow &aggressorRowId, const TDataSetRow &victimRowId ) { if ( !aggressorRowId.isValid() || !TheDataset.isDataSetRowStillValid(aggressorRowId) || !victimRowId.isValid() || !TheDataset.isDataSetRowStillValid(victimRowId) ) return; CEntityId victimId = TheDataset.getEntityId(victimRowId); CEntityId aggressorId = TheDataset.getEntityId(aggressorRowId); // at least the victim or the agressor must be a player, otherwise do not send any messages if ( (aggressorId.getType() != RYZOMID::player) && ( victimId.getType() != RYZOMID::player )) return; sendSimpleMessage(aggressorRowId, "EGS_ACTOR_CAST_END_SUCCESS"); if ( aggressorRowId == victimRowId) return; sendMessage(victimRowId, "EGS_TARGET_CAST_END_SUCCESS_E", aggressorRowId); // send message to spectators // Send to 'speech' group string msgName ="EGS_SPECT_CAST_END_SUCCESS_EE"; CEntityId speechGroupId; if ( victimId.getType() == RYZOMID::player ) speechGroupId = victimId; else speechGroupId = aggressorId; speechGroupId.setType( RYZOMID::dynChatGroup ); CMessage msg("STATIC_STRING"); msg.serial( speechGroupId ); set excluded; excluded.insert( aggressorId ); excluded.insert( victimId ); msg.serialCont( excluded ); msg.serial( msgName ); msg.serial( const_cast (victimId) ); msg.serial( const_cast (aggressorId) ); sendMessageViaMirror ("IOS", msg); } // sendSpellSuccessMessages // //-------------------------------------------------------------- // sendSpellFailedMessages() //-------------------------------------------------------------- void sendSpellFailedMessages( const TDataSetRow &aggressorRowId, const TDataSetRow &victimRowId ) { if ( !aggressorRowId.isValid() || !TheDataset.isDataSetRowStillValid(aggressorRowId) || !victimRowId.isValid() || !TheDataset.isDataSetRowStillValid(victimRowId) ) return; CEntityId victimId = TheDataset.getEntityId(victimRowId); CEntityId aggressorId = TheDataset.getEntityId(aggressorRowId); // at least the victim or the agressor must be a player, otherwise do not send any messages if ( (aggressorId.getType() != RYZOMID::player) && ( victimId.getType() != RYZOMID::player )) return; sendSimpleMessage(aggressorRowId, "EGS_ACTOR_CAST_END_FAILED"); if ( aggressorRowId == victimRowId) return; sendMessage(victimRowId, "EGS_TARGET_CAST_END_FAILED_E", aggressorRowId); // send message to spectators // Send to 'speech' group string msgName ="EGS_SPECT_CAST_END_FAILED_E"; CEntityId speechGroupId; if ( victimId.getType() == RYZOMID::player ) speechGroupId = victimId; else speechGroupId = aggressorId; speechGroupId.setType( RYZOMID::dynChatGroup ); CMessage msg("STATIC_STRING"); msg.serial( speechGroupId ); set excluded; excluded.insert( aggressorId ); excluded.insert( victimId ); msg.serialCont( excluded ); msg.serial( msgName ); msg.serial( const_cast (aggressorId) ); sendMessageViaMirror ("IOS", msg); } // sendSpellFailedMessages // //-------------------------------------------------------------- // sendSpellFumbleMessages() //-------------------------------------------------------------- void sendSpellFumbleMessages( const TDataSetRow &aggressorRowId, const TDataSetRow &victimRowId ) { if ( !aggressorRowId.isValid() || !TheDataset.isDataSetRowStillValid(aggressorRowId) || !victimRowId.isValid() || !TheDataset.isDataSetRowStillValid(victimRowId) ) return; CEntityId victimId = TheDataset.getEntityId(victimRowId); CEntityId aggressorId = TheDataset.getEntityId(aggressorRowId); // at least the victim or the agressor must be a player, otherwise do not send any messages if ( (aggressorId.getType() != RYZOMID::player) && ( victimId.getType() != RYZOMID::player )) return; sendSimpleMessage(aggressorRowId, "EGS_ACTOR_CAST_END_FUMBLE"); if ( aggressorRowId == victimRowId) return; sendMessage(victimRowId, "EGS_TARGET_CAST_END_FUMBLE_E", aggressorRowId); // send message to spectators // Send to 'speech' group string msgName ="EGS_SPECT_CAST_END_FUMBLE_E"; CEntityId speechGroupId; if ( victimId.getType() == RYZOMID::player ) speechGroupId = victimId; else speechGroupId = aggressorId; speechGroupId.setType( RYZOMID::dynChatGroup ); CMessage msg("STATIC_STRING"); msg.serial( speechGroupId ); set excluded; excluded.insert( aggressorId ); excluded.insert( victimId ); msg.serialCont( excluded ); msg.serial( msgName ); msg.serial( const_cast (aggressorId) ); sendMessageViaMirror ("IOS", msg); } // sendSpellFumbleMessages // }; // namespace PHRASE_UTILITIES