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;
}