bool CChar::NPC_FightMayCast(bool fCheckSkill) const { ADDTOCALLSTACK("CChar::NPC_FightMayCast"); // This NPC could cast spells if they wanted to ? // check mana and anti-magic // Dont check for skill if !fCheckSkill if (!m_pNPC) return false; if (fCheckSkill && !const_cast<CChar*>(this)->Skill_GetMagicRandom(300)) return false; if ( m_pArea && m_pArea->IsFlag(REGION_ANTIMAGIC_DAMAGE|REGION_FLAG_SAFE) ) return false; if ( Stat_GetVal(STAT_INT) < 5 ) return false; return true; }
bool CChar::Use_EatQty( CItem * pFood, short iQty ) { ADDTOCALLSTACK("CChar::Use_EatQty"); // low level eat ASSERT(pFood); if ( iQty <= 0 ) return false; if ( iQty > pFood->GetAmount() ) iQty = pFood->GetAmount(); short iRestore = 0; if ( pFood->m_itFood.m_foodval ) iRestore = static_cast<short>(pFood->m_itFood.m_foodval); else iRestore = pFood->Item_GetDef()->GetVolume(); // some food should have more value than other ! if ( iRestore < 1 ) iRestore = 1; short iSpace = Stat_GetMax(STAT_FOOD) - Stat_GetVal(STAT_FOOD); if ( iSpace <= 0 ) return false; if ( iQty > 1 && (iRestore * iQty > iSpace) ) iQty = maximum(1, iSpace / iRestore); switch ( pFood->GetType() ) { case IT_FRUIT: case IT_FOOD: case IT_FOOD_RAW: case IT_MEAT_RAW: if ( pFood->m_itFood.m_poison_skill ) // was the food poisoned? SetPoison(pFood->m_itFood.m_poison_skill * 10, 1 + (pFood->m_itFood.m_poison_skill / 50), this); default: break; } UpdateDir(pFood); EatAnim(pFood->GetName(), iRestore * iQty); pFood->ConsumeAmount(iQty); return true; }
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; }
void CChar::Use_Drink( CItem * pItem ) { ADDTOCALLSTACK("CChar::Use_Drink"); // IT_POTION: // IT_DRINK: // IT_PITCHER: // IT_WATER_WASH: // IT_BOOZE: if ( !CanMove(pItem) ) { SysMessageDefault(DEFMSG_DRINK_CANTMOVE); return; } const CItemBase *pItemDef = pItem->Item_GetDef(); ITEMID_TYPE idbottle = static_cast<ITEMID_TYPE>(RES_GET_INDEX(pItemDef->m_ttDrink.m_idEmpty)); if ( pItem->IsType(IT_BOOZE) ) { // Beer wine and liquor. vary strength of effect. int iAlcohol = Calc_GetRandVal(4); CItem *pDrunkLayer = LayerFind(LAYER_FLAG_Drunk); if ( !pDrunkLayer ) pDrunkLayer = Spell_Effect_Create(SPELL_Liquor, LAYER_FLAG_Drunk, 0, 5 * TICK_PER_SEC, this); pDrunkLayer->m_itSpell.m_spellcharges += iAlcohol; if ( pDrunkLayer->m_itSpell.m_spellcharges > 60 ) pDrunkLayer->m_itSpell.m_spellcharges = 60; } if ( pItem->IsType(IT_POTION) ) { // Time limit on using potions. if ( LayerFind(LAYER_FLAG_PotionUsed) ) { SysMessageDefault(DEFMSG_DRINK_POTION_DELAY); return; } // Convey the effect of the potion. int iSkillQuality = pItem->m_itPotion.m_skillquality; if ( g_Cfg.m_iFeatureAOS & FEATURE_AOS_UPDATE_B ) { int iEnhance = static_cast<int>(GetDefNum("EnhancePotions", false)); if ( iEnhance ) iSkillQuality += IMULDIV(iSkillQuality, iEnhance, 100); } OnSpellEffect(static_cast<SPELL_TYPE>(RES_GET_INDEX(pItem->m_itPotion.m_Type)), this, iSkillQuality, pItem); // Give me the marker that i've used a potion. Spell_Effect_Create(SPELL_NONE, LAYER_FLAG_PotionUsed, iSkillQuality, 15 * TICK_PER_SEC, this); } if ( pItem->IsType(IT_DRINK) && IsSetOF(OF_DrinkIsFood) ) { short iRestore = 0; if ( pItem->m_itDrink.m_foodval ) iRestore = static_cast<short>(pItem->m_itDrink.m_foodval); else iRestore = static_cast<short>(pItem->Item_GetDef()->GetVolume()); if ( iRestore < 1 ) iRestore = 1; if ( Stat_GetVal(STAT_FOOD) >= Stat_GetMax(STAT_FOOD) ) { SysMessageDefault(DEFMSG_DRINK_FULL); return; } Stat_SetVal(STAT_FOOD, Stat_GetVal(STAT_FOOD) + iRestore); if ( pItem->m_itFood.m_poison_skill ) SetPoison(pItem->m_itFood.m_poison_skill * 10, 1 + (pItem->m_itFood.m_poison_skill / 50), this); } //Sound(sm_DrinkSounds[Calc_GetRandVal(COUNTOF(sm_DrinkSounds))]); UpdateAnimate(ANIM_EAT); pItem->ConsumeAmount(); // Create the empty bottle ? if ( idbottle != ITEMID_NOTHING ) ItemBounce(CItem::CreateScript(idbottle, this), false); }
bool CChar::Use_Eat( CItem * pItemFood, short iQty ) { ADDTOCALLSTACK("CChar::Use_Eat"); // What we can eat should depend on body type. // How much we can eat should depend on body size and current fullness. // // ??? monsters should be able to eat corpses / raw meat // IT_FOOD or IT_FOOD_RAW // NOTE: Some foods like apples are stackable ! if ( !CanMove(pItemFood) ) { SysMessageDefault(DEFMSG_FOOD_CANTMOVE); return false; } if ( Stat_GetMax(STAT_FOOD) == 0 ) { SysMessageDefault(DEFMSG_FOOD_CANTEAT); return false; } // Is this edible by me ? if ( !Food_CanEat(pItemFood) ) { SysMessageDefault(DEFMSG_FOOD_RCANTEAT); return false; } if ( Stat_GetVal(STAT_FOOD) >= Stat_GetMax(STAT_FOOD) ) { SysMessageDefault(DEFMSG_FOOD_CANTEATF); return false; } Use_EatQty(pItemFood, iQty); LPCTSTR pMsg; int index = IMULDIV(Stat_GetVal(STAT_FOOD), 5, Stat_GetMax(STAT_FOOD)); switch ( index ) { case 0: pMsg = g_Cfg.GetDefaultMsg(DEFMSG_FOOD_FULL_1); break; case 1: pMsg = g_Cfg.GetDefaultMsg(DEFMSG_FOOD_FULL_2); break; case 2: pMsg = g_Cfg.GetDefaultMsg(DEFMSG_FOOD_FULL_3); break; case 3: pMsg = g_Cfg.GetDefaultMsg(DEFMSG_FOOD_FULL_4); break; case 4: pMsg = g_Cfg.GetDefaultMsg(DEFMSG_FOOD_FULL_5); break; case 5: default: pMsg = g_Cfg.GetDefaultMsg(DEFMSG_FOOD_FULL_6); break; } SysMessage(pMsg); return true; }