int CChar::NPC_GetAttackContinueMotivation( CChar * pChar, int iMotivation ) const { ADDTOCALLSTACK("CChar::NPC_GetAttackContinueMotivation"); // I have seen fit to attack them. // How much do i want to continue an existing fight ? cowardice ? // ARGS: // iMotivation = My base motivation toward this creature. // // RETURN: // -101 = ? dead meat. (run away) // // 0 = I'm have no interest. // 50 = even match. // 100 = he's a push over. if ( !m_pNPC ) return 0; if ( pChar->IsStatFlag( STATF_DEAD | STATF_INVUL | STATF_Stone )) return( -100 ); if ( m_pNPC->m_Brain == NPCBRAIN_GUARD ) return( 100 ); if ( m_pNPC->m_Brain == NPCBRAIN_BERSERK ) return( iMotivation + 80 - GetDist( pChar )); // less interested the further away they are // Try to stay on one target. if ( Fight_IsActive() && m_Act_Targ == pChar->GetUID()) iMotivation += 8; // Less interested the further away they are. iMotivation -= GetDist( pChar ); if ( !g_Cfg.m_fMonsterFear ) return( iMotivation ); // I'm just plain stronger. iMotivation += ( Stat_GetAdjusted(STAT_STR) - pChar->Stat_GetAdjusted(STAT_STR)); // I'm healthy. int iTmp = GetHealthPercent() - pChar->GetHealthPercent(); if ( iTmp < -50 ) iMotivation -= 50; else if ( iTmp > 50 ) iMotivation += 50; // I'm smart and therefore more cowardly. (if injured) iMotivation -= Stat_GetAdjusted(STAT_INT) / 16; return( iMotivation ); }
int CChar::NPC_GetAttackMotivation(CChar *pChar) const { ADDTOCALLSTACK("CChar::NPC_GetAttackMotivation"); // Some sort of monster. // Am I stronger than he is ? Should I continue fighting ? // Take into consideration AC, health, skills, etc.. // RETURN: // < 0 = dead meat. (run away) // 0 = I'm have no interest. // 50 = even match. // 100 = he's a push over. if ( !m_pNPC || !pChar || !pChar->m_pArea ) return 0; if ( pChar->m_pArea->IsFlag(REGION_FLAG_SAFE) ) return 0; int iMotivation = NPC_GetHostilityLevelToward(pChar); if ( iMotivation <= 0 ) return iMotivation; if ( !pChar->Fight_IsAttackable() ) return 0; if ( (m_pNPC->m_Brain == NPCBRAIN_BERSERK) || (m_pNPC->m_Brain == NPCBRAIN_GUARD) ) return 100; // Try to stay on one target if ( Fight_IsActive() && (m_Act_Targ == pChar->GetUID()) ) iMotivation += 10; // Less interested the further away they are iMotivation -= GetDist(pChar); if ( g_Cfg.m_fMonsterFear ) { if ( GetHealthPercent() < 50 ) iMotivation -= 50 + (Stat_GetAdjusted(STAT_INT) / 16); } return iMotivation; }
int CChar::NPC_GetAttackMotivation( CChar * pChar, int iMotivation ) const { ADDTOCALLSTACK("CChar::NPC_GetAttackMotivation"); // Some sort of monster. // Am I stronger than he is ? Should I continue fighting ? // Take into consideration AC, health, skills, etc.. // RETURN: // <-1 = dead meat. (run away) // 0 = I'm have no interest. // 50 = even match. // 100 = he's a push over. if ( !m_pNPC || !pChar || !pChar->m_pArea ) return 0; if ( Stat_GetVal(STAT_STR) <= 0 ) return -1; // I'm dead // Is the target interesting ? if ( pChar->m_pArea->IsFlag( REGION_FLAG_SAFE )) // universal return 0; if ( pChar->IsStatFlag(STATF_DEAD) && pChar->m_pNPC && pChar->m_pNPC->m_bonded ) return 0; // If the area is guarded then think better of this. if ( pChar->m_pArea->IsGuarded() && m_pNPC->m_Brain != NPCBRAIN_GUARD ) // too smart for this. { iMotivation -= Stat_GetAdjusted(STAT_INT) / 20; } // Owned by or is one of my kind ? iMotivation += NPC_GetHostilityLevelToward( pChar ); if ( iMotivation > 0 ) { // Am i injured etc ? iMotivation = NPC_GetAttackContinueMotivation( pChar, iMotivation ); } return iMotivation; }
bool CChar::Use_Item_Web( CItem * pItemWeb ) { ADDTOCALLSTACK("CChar::Use_Item_Web"); // IT_WEB // IT_EQ_STUCK // Try to break out of the web. // Or just try to damage it. // // RETURN: true = held in place. // false = walk thru it. if ( GetDispID() == CREID_GIANT_SPIDER || !pItemWeb || !pItemWeb->IsTopLevel() || IsStatFlag(STATF_DEAD|STATF_Insubstantial) || IsPriv(PRIV_GM) ) return false; // just walk through it // Try to break it. int iStr = pItemWeb->m_itWeb.m_Hits_Cur; if ( iStr == 0 ) iStr = pItemWeb->m_itWeb.m_Hits_Cur = 60 + Calc_GetRandVal(250); // Since broken webs become spider silk, we should get out of here now if we aren't in a web. CItem *pFlag = LayerFind(LAYER_FLAG_Stuck); if ( CanMove(pItemWeb, false) ) { if ( pFlag ) pFlag->Delete(); return false; } if ( pFlag ) { if ( pFlag->IsTimerSet() ) // don't allow me to try to damage it too often return true; } int iDmg = pItemWeb->OnTakeDamage(Stat_GetAdjusted(STAT_STR), this); switch ( iDmg ) { case 0: // damage blocked case 1: // web survived default: // unknown if ( GetTopPoint() == pItemWeb->GetTopPoint() ) // is character still stuck on the web? break; case 2: // web turned into silk case INT_MAX: // web destroyed if ( pFlag ) pFlag->Delete(); return false; } // Stuck in it still. if ( !pFlag ) { if ( iDmg < 0 ) return false; // First time message. pFlag = CItem::CreateBase(ITEMID_WEB1_1); ASSERT(pFlag); pFlag->SetAttr(ATTR_DECAY); pFlag->SetType(IT_EQ_STUCK); pFlag->m_uidLink = pItemWeb->GetUID(); pFlag->SetTimeout(pItemWeb->GetTimerDAdjusted()); LayerAdd(pFlag, LAYER_FLAG_Stuck); } else { if ( iDmg < 0 ) { pFlag->Delete(); return false; } SysMessagef(g_Cfg.GetDefaultMsg(DEFMSG_ITEMUSE_SWEB_STUCK), pItemWeb->GetName()); } return true; }
int CChar::NPC_GetHostilityLevelToward( const CChar * pCharTarg ) const { ADDTOCALLSTACK("CChar::NPC_GetHostilityLevelToward"); // What is my general hostility level toward this type of creature ? // // based on: // npc vs player, (evil npc's don't like players regurdless of align, xcept in town) // karma (we are of different alignments) // creature body type. (allie groups) // hunger, (they could be food) // memories of this creature. // // DO NOT consider: // strength, he is far stronger or waeker than me. // health, i may be near death. // location (guarded area), (xcept in the case that evil people like other evils in town) // loot, etc. // // RETURN: // 100 = extreme hatred. // 0 = neutral. // -100 = love them // if ( !pCharTarg || !m_pNPC ) return 0; int iHostility = 0; // if it is a pet - register it the same as it's master. CChar * pCharOwn = pCharTarg->NPC_PetGetOwner(); if ( pCharOwn != NULL && pCharOwn != this ) { static int sm_iReentrant = 0; if (sm_iReentrant > 32) { DEBUG_ERR(("Too many owners (circular ownership?) to continue acquiring hostility level towards %s uid=0%lx\n", pCharOwn->GetName(), pCharOwn->GetUID().GetPrivateUID())); return 0; } ++sm_iReentrant; iHostility = NPC_GetHostilityLevelToward( pCharOwn ); --sm_iReentrant; return iHostility; } int iKarma = Stat_GetAdjusted(STAT_KARMA); bool fDoMemBase = false; if ( Noto_IsEvil() && // i am evil. (m_pArea && !m_pArea->IsGuarded()) && // we are not in an evil town. pCharTarg->m_pPlayer ) // my target is a player. { // If i'm evil i give no benefit to players with bad karma. // I hate all players. // Unless i'm in a guarded area. then they are cool. iHostility = 51; } else if ( m_pNPC->m_Brain == NPCBRAIN_BERSERK ) // i'm beserk. { // beserks just hate everyone all the time. iHostility = 100; } else if ( pCharTarg->m_pNPC && // my target is an NPC pCharTarg->m_pNPC->m_Brain != NPCBRAIN_BERSERK && // ok to hate beserks. ! g_Cfg.m_fMonsterFight ) // monsters are not supposed to fight other monsters ! { iHostility = -50; fDoMemBase = true; // set this low in case we are defending ourselves. but not attack for hunger. } else { // base hostillity on karma diff. int iKarmaTarg = pCharTarg->Stat_GetAdjusted(STAT_KARMA); if ( Noto_IsEvil()) { // I'm evil. if ( iKarmaTarg > 0 ) { iHostility += ( iKarmaTarg ) / 1024; } } else if ( iKarma > 300 ) { // I'm good and my target is evil. if ( iKarmaTarg < -100 ) { iHostility += ( -iKarmaTarg ) / 1024; } } } // Based on just creature type. if ( ! fDoMemBase ) { if ( pCharTarg->m_pNPC ) { // Human NPC's will attack humans . if ( GetDispID() == pCharTarg->GetDispID()) { // I will never attack those of my own kind...even if starving iHostility -= 100; } else if ( NPC_GetAllyGroupType( GetDispID()) == NPC_GetAllyGroupType(pCharTarg->GetDispID())) { iHostility -= 50; } else if ( pCharTarg->m_pNPC->m_Brain == m_pNPC->m_Brain ) // My basic kind { // Won't attack other monsters. (unless very hungry) iHostility -= 30; } } else { // Not immediately hostile if looks the same as me. if ( ! IsPlayableCharacter() && NPC_GetAllyGroupType( GetDispID()) == NPC_GetAllyGroupType(pCharTarg->GetDispID())) { iHostility -= 51; } } } // I have been attacked/angered by this creature before ? CItemMemory * pMemory = Memory_FindObjTypes( pCharTarg, MEMORY_FIGHT|MEMORY_HARMEDBY|MEMORY_IRRITATEDBY|MEMORY_SAWCRIME|MEMORY_AGGREIVED ); if ( pMemory ) { iHostility += 50; } #ifdef _ALPHASPHERE /* foes or allies? Defined by tag.ff_group, tag.ff_foe and/or tag.ff_ally */ CVarDefCont *pVar, *pVarTarg; int iffCounter=0, iffGroup=0; pVarTarg = pCharTarg->m_TagDefs.GetKey("FF_GROUP"); if ( pVarTarg ) { iffGroup = pVarTarg->GetValNum(); pVar = m_TagDefs.GetKey("FF_FOE"); if ( pVar ) { iffCounter = pVar->GetValNum(); if ( iffCounter & iffGroup ) { // is an enemy iHostility += 70; } } else { pVar = m_TagDefs.GetKey("FF_ALLY"); if ( pVar ) { iffCounter = pVar->GetValNum(); if ( iffCounter & iffGroup ) { // is an ally iHostility -= 70; } } } if ( iHostility > 100 ) iHostility = 100; else if ( iHostility < -100 ) iHostility = -100; TCHAR *pszTmp = Str_GetTemp(); sprintf(pszTmp,"char = %s, target = %s, iHostility = %d, iffGroup = %d, iffCounter = %d\n",GetName(),pCharTarg->GetName(),iHostility,iffGroup,iffCounter); DEBUG_WARN((pszTmp)); } #endif return( iHostility ); }