Honorable Member Owsap 9575 Posted October 21 Honorable Member Share Posted October 21 (edited) There is an issue in the ComputePoints function for monsters when adding affects and then removing them after a certain time. Normally, we don't typically apply affects to monsters, but there are certain cases where it becomes necessary. What is the issue, exactly? First, let's analyze the SetProto function in the CHARACTER class, which is called when a monster is spawned: void CHARACTER::SetProto(const CMob* pkMob) { if (m_pkMobInst) M2_DELETE(m_pkMobInst); m_pkMobData = pkMob; m_pkMobInst = M2_NEW CMobInstance; m_bPKMode = PK_MODE_FREE; const TMobTable* t = &m_pkMobData->m_table; m_bCharType = t->bType; SetLevel(t->bLevel); SetEmpire(t->bEmpire); SetExp(t->dwExp); SetRealPoint(POINT_ST, t->bStr); SetRealPoint(POINT_DX, t->bDex); SetRealPoint(POINT_HT, t->bCon); SetRealPoint(POINT_IQ, t->bInt); ComputePoints(); SetHP(GetMaxHP()); SetSP(GetMaxSP()); //////////////////// m_pointsInstant.dwAIFlag = t->dwAIFlag; SetImmuneFlag(t->dwImmuneFlag); AssignTriggers(t); ApplyMobAttribute(t); if (IsStone()) { DetermineDropMetinStone(); } if (IsWarp() || IsGoto()) { StartWarpNPCEvent(); } [ more ... ] } In the function above, ComputePoints is called before ApplyMobAttribute, which is responsible for setting the monster's attributes, such as enchantments and resistances. When setting points, they are stored in m_pointsInstant.points. If you call ComputePoints again on the monster, it will reset those points because the function clears them using memset(m_pointsInstant.points, 0, sizeof(m_pointsInstant.points));. Normally, this function is not called on monsters after they spawn. However, if you try to apply affects to monsters and then remove them using RemoveAffect or manually compute the monster's affects, it triggers this bug by removing the monster's attributes. Why is this an the issue? When removing the points added by ApplyMobAttribute, the monster will lose all of its enchantments and resistances, significantly affecting its behavior and balance in the game. Here is the default implementation of the RemoveAffect: bool CHARACTER::RemoveAffect(CAffect* pkAff) { if (!pkAff) return false; // AFFECT_BUF_FIX m_list_pkAffect.remove(pkAff); // END_OF_AFFECT_BUF_FIX ComputeAffect(pkAff, false); // Bug fix for revive invisibility. // This bug occurred when using a buff skill, disguising, and then using a revive (AFFECT_REVIVE_INVISIBLE), // followed by immediate attacking. The issue was caused by ignoring buff effects during disguise. // When the revive was removed, both the disguise and buff effects would be applied. // To avoid unintended side effects, the fix ensures that ComputePoints is only called when necessary. if (AFFECT_REVIVE_INVISIBLE != pkAff->dwType) { ComputePoints(); } CheckMaximumPoints(); [ more ... ] } Solution To fix this bug, modify the condition so that ComputePoints is only called for player characters, not monsters: if (AFFECT_REVIVE_INVISIBLE != pkAff->dwType && IsPC()) { ComputePoints(); } This change ensures that the point recalculation only affects player characters, preventing the unintended removal of attributes from monsters. Edited October 21 by Owsap 5 3 2 7 https://owsap.dev/ / https://osf.owsap.dev/ Link to comment Share on other sites More sharing options...
Leyos 1 Posted October 23 Share Posted October 23 Good work bro Link to comment Share on other sites More sharing options...
Recommended Posts