bool CPC::SetHandicapState(Condition condition, CCharacter* target, int permil, int preDelayTime, int duration, bool isMagic, bool isFixedDelayTime /*only used for sleep from GM_SANDMAN*/) { auto class_ = CLASS_NONE; target->GetParameterValue(VAR_CLASS, &class_); auto job = JT_NOVICE; target->GetParameterValue(VAR_JOB, &tarJob); auto effectstate = target->GetEffectState(); auto bodystate = target->GetBodyState(); auto healthstate = target->GetHealthState(); if (class_ == NPC_CLASS_BOSS || class_ == NPC_CLASS_GUARDIAN || class_ == NPC_CLASS_BATTLEFIELD || job == JT_EMPELIUM || target->GetState() == CHARACTER_STATE_DEAD || (effectstate&EFFECTSTATE_SPECIALHIDING)) return false; int clv=0, str=0, vit=0, int_=0, luk=0, mdef=0, tolerance=(int)condition; target->GetParameterValue(VAR_CLEVEL, &clv); target->GetParameterValue(VAR_STR, &str); target->GetParameterValue(VAR_VIT, &vit); target->GetParameterValue(VAR_INT, &int_); target->GetParameterValue(VAR_LUK, &luk); target->GetParameterValue(VAR_MAGICITEMDEFPOWER, &mdef); target->GetParameterValue(VAR_TOLERACE, &tolerance); bool isMagicImmune = false; if (isMagic) target->GetParameterValue(VAR_ISMAGICIMMUNE, &isMagicImmune); switch (condition) { case BODY_STONECURSE: if (target->IsRightProperty(PROPERTY_UNDEAD)) return false; if (bodystate == BODYSTATE_STONECURSE_ING || bodystate == BODYSTATE_STONECURSE) { g_characterMgr.SendMsg(this, target, CM_TIME_BODYSTATE, 0, 0, 0, 0); return true; } if (bodystate || isMagicImmune) return false; permil += GetCharacterInfo()->clevel - permil * mdef / 100 - luk - clv; permil -= permil * tolerance / 100; if (GetServerRandom(0, 20000) % 1000 >= rate) return false; /* if the source of the efst isn't a PC, it's the following: time = 6000 time += preDelayTime + 100*srcLUK - time*tarMDEF/100 */ g_characterMgr.SendMsg(this, target, CM_TIME_BODYSTATE, preDelayTime, 20*1000, BODYSTATE_STONECURSE, 0); return true; case BODY_FREEZING: if (bodystate == BODYSTATE_FREEZING || bodystate || target->IsRightProperty(PROPERTY_UNDEAD) || isMagicImmune) return false; if (!duration) duration = 12*1000; permil += GetCharacterInfo()->clevel - permil * mdef / 100 - luk - clv; permil -= permil * tolerance / 100; if (GetServerRandom(0, 20000) % 1000 >= rate) return false; // note it's srcLUK not target LUK if (duration != 9999) duration += preDelayTime + 10*GetLukValue() - duration * mdef / 100; g_characterMgr.SendMsg(this, target, CM_TIME_BODYSTATE, preDelayTime, duration, BODYSTATE_FREEZING, 0); return true; case BODY_STUN: if (bodystate == BODYSTATE_STUN) return false; if (!duration) duration = 5*1000; permil += GetCharacterInfo()->clevel - permil * vit / 100 - luk - clv; permil -= permil * tolerance / 100; if (GetServerRandom(0, 20000) % 1000 >= rate) return false; // note that it's tarLUK subtracting from here on if (duration != 9999) duration += preDelayTime - 10 * luk - duration * vit / 100; Trace("BODY_STUN: %d\n", rate); Trace("BODY_STUN time: %d\n", duration); g_characterMgr.SendMsg(this, target, CM_TIME_BODYSTATE, preDelayTime, duration, BODYSTATE_STUN, 0); return true; case BODY_SLEEP: if (bodystate == BODYSTATE_SLEEP) return false; if (!duration) duration = 30*1000; permil += GetCharacterInfo()->clevel - permil * int_ / 100 - luk - clv; permil -= permil * tolerance / 100; if (GetServerRandom(0, 20000) % 1000 >= rate && !isFixedDelayTime) return false if (duration != 9999 && !isFixedDelayTime) duration += preDelayTime - duration*int_/100 - 10 * luk; Trace("BODY_SLEEP: %d\n", rate); g_characterMgr.SendMsg(this, target, CM_TIME_BODYSTATE, preDelayTime, duration, BODYSTATE_SLEEP, 0); return true; case HEALTH_POISON: // NPCs don't have code for applying HEAVYPOISON if (healthstate(&HEALTHSTATE_HEAVYPOISON|HEALTHSTATE_POISON)) return false; permil += GetCharacterInfo()->clevel - permil * vit / 100 - luk - clv; permil -= permil * tolerance/100; if (GetServerRandom(0, 20000) % 1000 >= rate) return false; if (duration != 9999) { if (target->GetType() == PC_TYPE) duration = (20*1000 - vit*200) + 10*1000; else duration = (55*1000 - 10000*luk/100 - vit*450) + 5*1000; duration += preDelayTime; } // when NPC is causing poison, default time is 30s // time += preDelayTime - time*VIT/100 - 10*LUK g_characterMgr.SendMsg(this, target, CM_TIME_HEALTHSTATE, preDelayTime, duration, HEALTHSTATE_POISON, 0); return true; case HEALTH_HEAVYPOISON: // NPCs don't have code for applying HEAVYPOISON permil += GetCharacterInfo()->clevel - permil * vit / 100 - luk - clv; permil -= permil * tolerance/100; if (GetServerRandom(0, 20000) % 1000 >= rate) return false; if (duration != 9999) { if (target->GetType() == PC_TYPE) duration = (20*1000 - vit*200) + 10*1000; else duration = (55*1000 - 10*1000*luk/100 - vit*450) + 5*1000; duration += preDelayTime; } g_characterMgr.SendMsg(this, target, CM_TIME_HEALTHSTATE, preDelayTime, duration, HEALTHSTATE_HEAVYPOISON, 0); return true; case HEALTH_BLIND: if (healthstate&HEALTHSTATE_BLIND) return false; if (!duration) duration = 30*1000; permil += GetCharacterInfo()->clevel - permil * (int_ + vit) / 200 - luk - clv; permil -= permil * tolerance/100; if (GetServerRandom(0, 20000) % 1000 >= rate) return false; if (duration != 9999) duration += preDelayTime - 10*luk - duration * (int_ + vit)/200; g_characterMgr.SendMsg(this, target, CM_TIME_HEALTHSTATE, preDelayTime, duration, HEALTHSTATE_BLIND, 0); return true; case HEALTH_SILENCE: if (healthstate&HEALTHSTATE_SILENCE) return false; if (!duration) duration = 30*1000; permil += GetCharacterInfo()->clevel - permil * vit / 100 - luk - clv; permil -= permil * tolerance/100; if (GetServerRandom(0, 20000) % 1000 >= rate) return false; if (duration != 9999) duration += preDelayTime - 10*luk - duration * vit/100; g_characterMgr.SendMsg(this, target, CM_TIME_HEALTHSTATE, preDelayTime, duration, HEALTHSTATE_SILENCE, 0); return true; case HEALTH_CURSE: if (healthstate&HEALTHSTATE_CURSE || !luk) return false; if (!duration) duration = 30*1000; permil += GetCharacterInfo()->clevel - permil * luk / 100 - luk; permil -= permil * tolerance/100; if (GetServerRandom(0, 20000) % 1000 >= rate) return false; if (duration != 9999) duration += preDelayTime - 10*luk - duration * vit/100; g_characterMgr.SendMsg(this, target, CM_TIME_HEALTHSTATE, preDelayTime, duration, HEALTHSTATE_CURSE, 0); if (target->GetType() != NPC_MOB_TYPE || !duration) return true; ((CNPC*)target)->SetATKPercentInfo(SKID_CR_GRANDCROSS, duration, -25); return true; case HEALTH_CONFUSION: if (healthstate&HEALTHSTATE_CONFUSION) { preDelayTime = 0; duration = 0; } else { if (!duration) duration = 30*1000; permil += clv + luk - GetCharacterInfo()->clevel - permil * (str + int_) / 200; permil -= permil * tolerance/100; if (GetServerRandom(0, 20000) % 1000 >= rate) return false; if (duration != 9999) duration += preDelayTime - 10*luk - duration * (str + int_)/ 200; } g_characterMgr.SendMsg(this, target, CM_TIME_HEALTHSTATE, preDelayTime, duration, HEALTHSTATE_CONFUSION, 0); return true; case HEALTH_BLOODING: if (!duration) duration = 60*2*1000 permil += GetCharacterInfo()->clevel - permil * vit / 100 - luk - clv; permil -= permil * tolerance/100; if (GetServerRandom(0, 20000) % 1000 >= rate) return false; if (duration != 9999) { duration -= duration * vit/100; duration -= 10*luk; } g_characterMgr.SendMsg(this, target, CM_TIME_HEALTHSTATE, 0, duration, HEALTHSTATE_BLOODING, 0); g_characterMgr.SendMsg(this, target, CM_SETEFFECTIVE, EFST_BLOODING, duration, 1, 0); return true; } return false; }