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