void Map::Attack(Character *from, Direction direction)
{
PacketBuilder builder;
from->direction = direction;
if (from->arena)
{
from->arena->Attack(from, direction);
}
if (this->pk || (this->world->config["GlobalPK"] && !this->world->PKExcept(this->id)))
{
if (this->AttackPK(from, direction))
{
return;
}
}
builder.SetID(PACKET_ATTACK, PACKET_PLAYER);
builder.AddShort(from->player->id);
builder.AddChar(direction);
UTIL_PTR_LIST_FOREACH(this->characters, Character, character)
{
if (*character == from || !from->InRange(*character))
{
continue;
}
character->player->client->SendBuilder(builder);
}
int target_x = from->x;
int target_y = from->y;
int range = 1;
if (this->world->eif->Get(from->paperdoll[Character::Weapon])->subtype == EIF::Ranged)
{
range = static_cast<int>(this->world->config["RangedDistance"]);
}
for (int i = 0; i < range; ++i)
{
switch (from->direction)
{
case DIRECTION_UP:
target_y -= 1;
break;
case DIRECTION_RIGHT:
target_x += 1;
break;
case DIRECTION_DOWN:
target_y += 1;
break;
case DIRECTION_LEFT:
target_x -= 1;
break;
}
if (!this->Walkable(target_x, target_y, true))
{
break;
}
UTIL_PTR_LIST_FOREACH(this->characters, Character, character)
{
UTIL_PTR_VECTOR_FOREACH(this->npcs, NPC, npc)
{
if ((npc->pet || npc->Data()->type == ENF::Pet || npc->Data()->type == ENF::Passive || npc->Data()->type == ENF::Aggressive || from->admin > static_cast<int>(this->world->admin_config["killnpcs"]))
&& npc->alive && npc->x == target_x && npc->y == target_y)
{
if(from->clas == 9)
{
int amount = util::rand(from->mindam + 0, from->maxdam + 0);
double rand = util::rand(0.0, 1.0);
// Checks if target is facing you
bool critical = std::abs(int(npc->direction) - from->direction) != 2 || rand < static_cast<double>(this->world->config["CriticalRate"]);
std::tr1::unordered_map<std::string, double> formula_vars;
from->FormulaVars(formula_vars);
npc->FormulaVars(formula_vars, "target_");
formula_vars["modifier"] = this->world->config["MobRate"];
formula_vars["damage"] = amount;
formula_vars["critical"] = critical;
amount = rpn_eval(rpn_parse(this->world->formulas_config["damage"]), formula_vars);
double hit_rate = rpn_eval(rpn_parse(this->world->formulas_config["hit_rate"]), formula_vars);
if (rand > hit_rate)
{
amount = 0;
}
amount = std::max(amount, 0);
int limitamount = std::min(amount, int(npc->hp));
if (this->world->config["LimitDamage"])
{
amount = limitamount;
}
int itemid, effectid;
for(int i = 0 ; i < static_cast<int>(this->world->effects_config["WAmount"]) ; i++){
itemid = static_cast<int>(this->world->effects_config[util::to_string(i+1) + ".ItemID"]);
effectid = static_cast<int>(this->world->effects_config[util::to_string(i+1) + ".EffectID"]);
if(from->paperdoll[Character::Weapon] == itemid){
npc->Effect(from, effectid, amount);
}
}
npc->Damage(from, amount);
}
else if(from->clas != 9)
{
int amount = util::rand(from->mindam, from->maxdam);
double rand = util::rand(0.0, 1.0);
// Checks if target is facing you
bool critical = std::abs(int(npc->direction) - from->direction) != 2 || rand < static_cast<double>(this->world->config["CriticalRate"]);
std::tr1::unordered_map<std::string, double> formula_vars;
from->FormulaVars(formula_vars);
npc->FormulaVars(formula_vars, "target_");
formula_vars["modifier"] = this->world->config["MobRate"];
formula_vars["damage"] = amount;
formula_vars["critical"] = critical;
amount = rpn_eval(rpn_parse(this->world->formulas_config["damage"]), formula_vars);
double hit_rate = rpn_eval(rpn_parse(this->world->formulas_config["hit_rate"]), formula_vars);
if (rand > hit_rate)
{
amount = 0;
}
amount = std::max(amount, 0);
int limitamount = std::min(amount, int(npc->hp));
if (this->world->config["LimitDamage"])
{
amount = limitamount;
}
int itemid, effectid;
for(int i = 0 ; i < static_cast<int>(this->world->effects_config["WAmount"]) ; i++){
itemid = static_cast<int>(this->world->effects_config[util::to_string(i+1) + ".ItemID"]);
effectid = static_cast<int>(this->world->effects_config[util::to_string(i+1) + ".EffectID"]);
if(from->paperdoll[Character::Weapon] == itemid){
npc->Effect(from, effectid, amount);
}
}
npc->Damage(from, amount);
return;
}
}
}
}
}
}