varargs string do_damage(object me, object target, mixed type,
int damage, int percent, mixed final)
{
mapping my;
object weapon;
object cloth;
int apply;
int armor;
int wound;
int jiali;
int bonus;
mixed foo;
string msg;
string skill;
string *limbs;
string limb;
string damage_type;
string result;
int str;
int damage_bonus;
mapping prepare;
mapping fight = ([]);
mapping defend = ([]);
string attack_skill;
if (environment(me) != environment(target))
{
me->remove_enemy(target);
target->remove_enemy(me);
return "";
}
// Am I use weapon
if (type == WEAPON_ATTACK)
{
apply = me->query_temp("apply/damage");
weapon = me->query_temp("weapon");
} else
if (type == UNARMED_ATTACK)
{
apply = me->query_temp("apply/unarmed_damage");
weapon = 0;
} else
{
apply = 0;
weapon = 0;
}
prepare = me->query_skill_prepare();
if (! prepare) prepare = ([]);
if (weapon)
skill = weapon->query("skill_type");
else
{
switch (sizeof(prepare))
{
case 0: attack_skill = "unarmed"; break;
case 1:
case 2: attack_skill = (keys(prepare))[0]; break;
}
}
if (skill == "pin") skill = "sword";
attack_skill = me->query_skill_mapped(skill);
if (SKILLS_D->skill_query_power_point(attack_skill))
fight = SKILLS_D->skill_query_power_point(attack_skill);
// Check the target's armor
armor = target->query_temp("apply/armor");
damage += apply;
msg = "";
foo_after_hit = 0;
while (type == UNARMED_ATTACK || type == WEAPON_ATTACK)
{
// Let parry skill take its special effort
if (skill = target->query_skill_mapped("parry"))
{
if (foo = SKILL_D(skill)->valid_damage(me, target, damage, weapon))
{
if (defend = SKILLS_D->skill_query_power_point(skill))
{
if (! undefinedp(defend["parry"]) && defend["parry"] > 119)
{
if (! fight || fight["attack"] - defend["parry"] < 30)
{
if (stringp(foo)) msg += foo; else
if (intp(foo)) damage += foo; else
if (mapp(foo))
{
msg += foo["msg"];
damage += foo["damage"];
}
}
}
}
}
}
// Let dodge skill take its special effort
if (skill = target->query_skill_mapped("dodge"))
{
if (foo = SKILL_D(skill)->valid_damage(me, target, damage, weapon))
{
if (defend = SKILLS_D->skill_query_power_point(skill))
{
if (! undefinedp(defend["dodge"]) && defend["dodge"] > 119)
{
if (! fight || fight["attack"] - defend["dodge"] < 30)
{
if (stringp(foo)) msg += foo; else
if (intp(foo)) damage += foo; else
if (mapp(foo))
{
msg += foo["msg"];
damage += foo["damage"];
}
}
}
}
}
}
if (damage < 1) break;
// Let cloth & armor take its special effort
if (cloth = target->query_temp("armor/armor"))
{
foo = cloth->valid_damage(me, target, damage, weapon);
if (stringp(foo)) msg += foo; else
if (intp(foo)) damage += foo; else
if (mapp(foo))
{
msg += foo["msg"];
damage += foo["damage"];
}
} else
if (cloth = target->query_temp("armor/cloth"))
{
foo = cloth->valid_damage(me, target, damage, weapon);
if (stringp(foo)) msg += foo; else
if (intp(foo)) damage += foo; else
if (mapp(foo))
{
msg += foo["msg"];
damage += foo["damage"];
}
}
// Finish
break;
}
while (damage > 0)
{
if (target->is_busy()) target->interrupt_me(target, 4 + random(4));
// Let weapon/unarmed attack take its special effort
if (type == WEAPON_ATTACK && objectp(weapon))
// weapon attack
foo = weapon->hit_ob(me, target, damage);
else
if (type == UNARMED_ATTACK)
// unarmed attack
foo = me->hit_ob(me, target, damage);
else
if (objectp(type))
// special item attack
foo = type->hit_ob(me, target, damage);
if (stringp(foo)) msg += foo; else
if (intp(foo)) damage += foo; else
if (mapp(foo))
{
msg += foo["msg"];
damage += foo["damage"];
}
// do enforce effect
my = me->query_entire_dbase();
if ((jiali = my["jiali"]) > 0 && my["neili"] >= jiali)
{
// eforced
my["neili"] -= jiali;
if (type == REMOTE_ATTACK)
{
damage_bonus = jiali * damage / 200;
} else
{
damage_bonus = jiali * damage / 300;
// check special force effort
skill = target->query_skill_mapped("force");
if (stringp(skill))
{
foo = SKILL_D(skill)->valid_damage(me, target, damage_bonus);
if (stringp(foo)) msg += foo; else
if (intp(foo)) damage_bonus += foo; else
if (mapp(foo))
{
msg += foo["msg"];
damage_bonus += foo["damage"];
}
}
damage += damage_bonus;
}
}
// do str effect
str = me->query_str() + me->query_temp("str");
if (str < 20)
damage += damage * str / 50;
else
if (str < 40)
damage += damage * ((str - 20) / 2 + 20) / 50;
else
damage += damage * ((str - 40) / 4 + 30) / 50;
if (damage < 1) break;
// recalculate damage
if (damage > 1500)
damage = (damage - 1500) / 4 + 1000;
else
if (damage > 500)
damage = (damage - 500) / 2 + 500;
// do damage
target->receive_damage("qi", damage, me);
wound = (damage - random(armor)) * percent / 100;
if (target->query("character") == "光明磊落")
wound -= wound * 20 / 100;
if (wound > 0) target->receive_wound("qi", wound, me);
if (functionp(final)) final = evaluate(final);
if (stringp(final))
{
if (sscanf(final, "%s@%s", final, limb) == 2)
{
if (sscanf(final, "%s:%s", result, damage_type) != 2)
{
result = HIR "這招打了個正中!";
damage_type = final;
}
if (sscanf(limb, "?%*s"))
{
// auto select limb
limbs = target->query("limbs");
if (! arrayp(limbs))
{
limbs = ({ "身體" });
target->set("limbs", limbs);
}
limb = limbs[random(sizeof(limbs))];
}
// indicate damage type & limb
final = replace_string(damage_msg(damage, damage_type), "$l", limb);
final = replace_string(final, "$n", "$n" HIR);
final = replace_string(final, "$N", "$N" HIR);
final = replace_string(final, "$p", "$p" HIR);
final = replace_string(final, "$P", "$P" HIR);
if (weapon)
final = replace_string(final, "$w", weapon->name() + HIR);
final = result + HIR + final + NOR;
}
msg += final;
msg += "( $n" + status_msg(target->query("qi") * 100 / target->query("max_qi")) + ")\n";
}
break;
}
if (foo_after_hit) msg += foo_after_hit;
if (foo_before_hit) msg = foo_before_hit + msg;
// Clear the special message info after damage info
foo_before_hit = 0;
foo_after_hit = 0;
return msg;
}