// combatd.c
//#pragma optimize
#include <ansi.h>
#include <skill.h>
#include <weapon.h>
#include <combat.h>
#include "/cmds/std/valid_kill.h"

inherit F_DBASE;

int victim_lose(object killer,object victim,string killerid);
void victim_penalty(object victim);
int nk_gain(object killer, object victim);
string chinese_daoxing(int gain);
int CheckExp2(object killer,object victim,int multi);
int check_family(string fam);
int querypgwin(object killer,object victim);
string attack_skill, force_skill, martial_skill, dodge_skill, parry_skill;
//this mapping indicates whether this family class is
//xian or yao.
mapping family=([
        "方寸山三星洞"  :1,
        "南海普陀山"    :1,
        "天蓬帅府"      :1,
        "将军府"        :1,
        "五庄观"        :1,
        "武当派"        :1,
        "武圣门"        :1,
        "蜀山派"        :1,
        "少林派"        :1,
        "神剑山庄"      :1,
        
        "阎罗地府"      :0,
        "天空界"        :0,
        "月宫"          :0,
        "灵界"          :0,
        "东海龙宫"      :0,
        "龙宫"          :0,
        "移花宫"        :0,
        
        "盘丝洞"        :-1,
        "大雪山"        :-1,
        "魔教"          :-1,
        "火云洞"        :-1,
        "轩辕古墓"      :-1,//修改完毕
        "翠云山芭蕉洞"  :-1,//暂不开放
        "陷空山无底洞"  :-1,
        "乱石山碧波潭"  :-1, 
]);

string *guard_msg = ({
        CYN"$N"CYN"注视着$n"CYN"的行动，企图寻找机会出手。\n" NOR,
        CYN"$N"CYN"正盯着$n"CYN"的一举一动，随时准备发动攻势。\n" NOR,
        CYN"$N"CYN"缓缓地移动脚步，想要找出$n"CYN"的破绽。\n" NOR,
        CYN"$N"CYN"目不转睛地盯着$n"CYN"的动作，寻找进攻的最佳时机。\n" NOR,
        CYN"$N"CYN"慢慢地移动着脚步，伺机出手。\n" NOR,
});

string *catch_hunt_msg = ({
        HIW"$N"HIW"和$n"HIW"仇人相见份外眼红，立刻打了起来！\n" NOR,
        HIW"$N"HIW"对着$n"HIW"大喝：「可恶，又是你！」\n" NOR,
        HIW"$N"HIW"和$n"HIW"一碰面，二话不说就打了起来！\n" NOR,
        HIW"$N"HIW"一眼瞥见$n"HIW"，「哼」的一声冲了过来！\n" NOR,
        HIW"$N"HIW"一见到$n"HIW"，愣了一愣，大叫：「我宰了你！」\n" NOR,
        HIW"$N"HIW"喝道：「$n"HIW"，我们的帐还没算完，看招！」\n" NOR,
        HIW"$N"HIW"喝道：「$n"HIW"，看招！」\n" NOR,
});

string *winner_msg = ({
        CYN"\n$N"CYN"哈哈大笑，说道：承让了！\n\n" NOR,
        CYN"\n$N"CYN"双手一拱，笑着说道：承让！\n\n" NOR,
        CYN"\n$N"CYN"胜了这招，向后跃开三尺，笑道：承让！\n\n" NOR,
        CYN"\n$n"CYN"脸色微变，说道：佩服，佩服！\n\n" NOR,
        CYN"\n$n"CYN"向后退了几步，说道：这场比试算我输了，佩服，佩服！\n\n" NOR,
        CYN"\n$n"CYN"向后一纵，躬身做揖说道：阁下武艺不凡，果然高明！\n\n" NOR,
});

void create()
{
        seteuid(getuid());
        set("name", "战斗精灵");
        set("id", "combatd");
}

//加入参数brief
//0 如常
//1 只返回受伤数值
varargs string damage_msg(int damage, string type,int brief)
{
        string str;
        if( brief )
                return "造成 "HIR + damage + NOR" 点" + type + "。\n";
        if( damage==0 ) 
                return "结果没有造成任何伤害。\n";
        switch( type ) 
        {
                case "擦伤":
                case "抓伤":
                case "割伤":
                        if( damage < 10 ) return "结果只是轻轻地划破$p的皮肉。\n";
                        else if( damage < 20 ) return "结果在$p$l划出一道细长的血痕。\n";
                        else if( damage < 40 ) return "结果「嗤」地一声划出一道伤口！\n";
                        else if( damage < 80 ) return "结果「嗤」地一声划出一道血淋淋的伤口！\n";
                        else if( damage < 160 ) return "结果「嗤」地一声划出一道又长又深的伤口，溅得$N满脸鲜血！\n";
                        else return "结果只听见$n一声惨嚎，$p的$l被划出一道深及见骨的可怕伤口！\n";
                        break;
                case "砍伤":
                case "劈伤":
                        if( damage < 10 ) return "结果只是在$n的皮肉上碰了碰，跟蚊子叮差不多。\n";
                        else if( damage < 20 ) return "结果在$n$l砍出一道细长的血痕。\n";
                        else if( damage < 40 ) return "结果「噗嗤」一声劈出一道血淋淋的伤口！\n";
                        else if( damage < 80 ) return "结果只听「噗」地一声，$n的$l被劈得血如泉涌，痛得$p咬牙切齿！\n";
                        else if( damage < 160 ) return "结果「噗」地一声砍出一道又长又深的伤口，溅得$N满脸鲜血！\n";
                        else return "结果只听见$n一声惨嚎，$p的$l被劈开一道深及见骨的可怕伤口！\n";
                        break;
                case "枪伤":
                case "刺伤":
                        if( damage < 10 ) return "结果只是轻轻地刺破$p的皮肉。\n";
                        else if( damage < 20 ) return "结果在$p$l刺出一个创口。\n";
                        else if( damage < 40 ) return "结果「噗」地一声刺入了$n$l寸许！\n";
                        else if( damage < 80 ) return "结果「噗」地一声刺进$n的$l，使$p不由自主地退了步！\n";
                        else if( damage < 160 ) return "结果「噗嗤」地一声，$w已在$p$l刺出一个血肉模糊的血窟窿！\n";
                        else return "结果只听见$n一声惨嚎，$w已在$p的$l对穿而出，鲜血溅得满地！\n";
                        break;
                case "筑伤":
                        if( damage < 10 ) return "结果只是轻轻地一触，在$n的皮肤上留下一点白痕。\n";
                        else if( damage < 20 ) return "结果在$p的$l留下几道血痕。\n";
                        else if( damage < 40 ) return "结果一下子筑中，$n的$l顿时出现几个血孔！\n";
                        else if( damage < 80 ) return "结果一下子筑中，$n立刻血流如注！\n";
                        else if( damage < 120 ) return "结果「哧」地一声，$n顿时鲜血飞溅！\n";
                        else if( damage < 160 ) return "结果这一下「哧」地一声，$n被筑得浑身是血！\n";
                        else return "结果「哧」重重地砸中，$n被筑得千疮白孔，血肉四处横飞！\n";
                        break;
                case "掌伤":
                case "拳伤":
                case "瘀伤":
                        if( damage < 10 ) return "结果只是轻轻地碰到，比拍苍蝇稍微重了点。\n";
                        else if( damage < 20 ) return "结果在$p的$l造成一处瘀青。\n";
                        else if( damage < 40 ) return "结果一击命中，$n的$l登时肿了一块老高！\n";
                        else if( damage < 80 ) return "结果一击命中，$n闷哼了一声显然吃了不小的亏！\n";
                        else if( damage < 120 ) return "结果「砰」地一声，$n退了两步！\n";
                        else if( damage < 160 ) return "结果这一下「砰」地一声打得$n连退了好几步，差一点摔倒！\n";
                        else if( damage < 240 ) return "结果重重地击中，$n「哇」地一声吐出一口鲜血！\n";
                        else return "结果只听见「砰」地一声巨响，$n像一捆稻草般飞了出去！\n";
                        break;
                case "撞伤":
                case "砸伤":
                        if( damage < 10 ) return "结果只是轻轻地碰到，等于给$n搔了一下痒。\n";
                        else if( damage < 20 ) return "结果在$p的$l砸出一个小臌包。\n";
                        else if( damage < 40 ) return "结果砸个正着，$n的$l登时肿了一块老高！\n";
                        else if( damage < 80 ) return "结果砸个正着，$n闷哼一声显然吃了不小的亏！\n";
                        else if( damage < 120 ) return "结果「砰」地一声，$n疼得连腰都弯了！\n";
                        else if( damage < 160 ) return "结果这一下「轰」地一声砸得$n眼冒金星，差一点摔倒！\n";
                        else if( damage < 240 ) return "结果重重地砸中，$n眼前一黑，「哇」地一声吐出一口鲜血！\n";
                        else return "结果只听见「轰」地一声巨响，$n被砸得血肉模糊，惨不忍睹！\n";
                        break;
                case "震伤":
                case "内伤":
                        if( damage < 20 ) return "结果在$n身上一触即逝，等于给$n搔了一下痒。\n";
                        else if( damage < 40 ) return "结果$n晃了一晃，吃了点小亏。\n";
                        else if( damage < 80 ) return "结果$n气息一窒，显然有点呼吸不畅！\n";
                        else if( damage < 120 ) return "结果$n体内一阵剧痛，看起来内伤不轻！\n";
                        else if( damage < 160 ) return "结果「嗡」地一声$n只觉得眼前一黑，双耳轰鸣不止！\n";
                        else return "结果只听见「嗡」地一声巨响，$n「哇」地一声吐出一口鲜血，五脏六腑都错了位！\n";
                        break;
                case "鞭伤":
                case "抽伤":
                        if( damage < 10 ) return "结果只是在$n的皮肉上碰了碰，跟蚊子叮差不多。\n";
                        else if( damage < 20 ) return "结果在$n$l抽出一道轻微的紫痕。\n";
                        else if( damage < 40 ) return "结果「啪」地一声在$n$l抽出一道长长的血痕！\n";
                        else if( damage < 80 ) return "结果只听「啪」地一声，$n的$l被抽得皮开肉绽，痛得$p咬牙切齿！\n";
                        else if( damage < 160 ) return "结果「啪」地一声爆响！这一下好厉害，只抽得$n皮开肉绽，血花飞溅！\n";
                        else return "结果只听见$n一声惨嚎，$w重重地抽上了$p的$l，$n顿时血肉横飞，十命断了九条！\n";
                        break;
                case "点伤":
                        if( damage < 10 ) return "结果$n痛哼一声，在$p的$l造成一处淤青。\n";
                        else if( damage < 20 ) return "结果一击命中，$N点中了$n$l上的穴道，$n只觉一阵麻木！\n";
                        else if( damage < 40 ) return "结果$n闷哼了一声，脸上一阵青一阵白，登时觉得$l麻木！\n";
                        else if( damage < 80 ) return "结果$n脸色一下变得惨白，被$N点中$l的穴道,一阵疼痛遍布整个$l！\n";
                        else if( damage < 160 ) return "结果$n一声大叫，$l的穴道被点中,疼痛直入心肺！\n";
                        else return "结果只听见$n一声惨叫，一阵剧痛夹杂着麻痒游遍全身，跟着直挺挺的倒了下去！\n";
                        break;                  
                default: 
                        if( !type ) type = "伤害";
                        if( damage < 10 ) str =  "结果只是勉强造成一处轻微";
                        else if( damage < 20 ) str = "结果造成轻微的";
                        else if( damage < 30 ) str = "结果造成一处";
                        else if( damage < 50 ) str = "结果造成一处严重";
                        else if( damage < 80 ) str = "结果造成颇为严重的";
                        else if( damage < 120 ) str = "结果造成相当严重的";
                        else if( damage < 170 ) str = "结果造成十分严重的";
                        else if( damage < 230 ) str = "结果造成极其严重的";
                        else    str =  "结果造成非常可怕的严重";
                        return str + type + "！\n";
        }
}

string eff_status_msg(int ratio)
{
        if( ratio==100 ) return HIG "看起来气血充盈，并没有受伤。" NOR;
        if( ratio > 95 ) return HIG "似乎受了点轻伤，不过光从外表看不大出来。" NOR;
        if( ratio > 90 ) return HIY "看起来可能受了点轻伤。" NOR;
        if( ratio > 80 ) return HIY "受了几处伤，不过似乎并不碍事。" NOR;
        if( ratio > 60 ) return HIY "受伤不轻，看起来状况并不太好。" NOR;
        if( ratio > 40 ) return HIR "气息粗重，动作开始散乱，看来所受的伤着实不轻。" NOR;
        if( ratio > 30 ) return HIR "已经伤痕累累，正在勉力支撑着不倒下去。" NOR;
        if( ratio > 20 ) return HIR "受了相当重的伤，只怕会有生命危险。" NOR;
        if( ratio > 10 ) return RED "伤重之下已经难以支撑，眼看就要倒在地上。" NOR;
        if( ratio > 5  ) return RED "受伤过重，已经奄奄一息，命在旦夕了。" NOR;
        return RED "受伤过重，已经有如风中残烛，随时都可能断气。" NOR;
}

string status_msg(int ratio)
{
        if( ratio==100 ) return HIG "看起来充满活力，一点也不累。" NOR;
        if( ratio > 95 ) return HIG "似乎有些疲惫，但是仍然十分有活力。" NOR;
        if( ratio > 90 ) return HIY "看起来可能有些累了。" NOR;
        if( ratio > 80 ) return HIY "动作似乎开始有点不太灵光，但是仍然有条不紊。" NOR;
        if( ratio > 60 ) return HIY "气喘嘘嘘，看起来状况并不太好。" NOR;
        if( ratio > 40 ) return HIR "似乎十分疲惫，看来需要好好休息了。" NOR;
        if( ratio > 30 ) return HIR "已经一副头重脚轻的模样，正在勉力支撑着不倒下去。" NOR;
        if( ratio > 20 ) return HIR "看起来已经力不从心了。" NOR;
        if( ratio > 10 ) return RED "摇头晃脑、歪歪斜斜地站都站不稳，眼看就要倒在地上。" NOR;
        return RED "已经陷入半昏迷状态，随时都可能摔倒晕去。" NOR;
}

//report_shen messages
string sen_status_msg(int ratio)
{
        if( ratio==100 ) return HIG "看起来头脑清醒，一点也不迷糊。" NOR;
        if( ratio > 90 ) return HIG "拍了拍自己的脑袋，似乎有点不太得劲。" NOR;
        if( ratio > 80 ) return HIY "看起来有些迷糊了。" NOR;
        if( ratio > 60 ) return HIY "的确有点迷糊了，但还辨得出东西南北。" NOR;
        if( ratio > 40 ) return HIR "两眼发直，口角流涎，神智开始混乱。" NOR;
        if( ratio > 20 ) return HIR "迷迷糊糊，摇摇晃晃，已经辨不出东西南北了。" NOR;
        if( ratio > 10 ) return RED "神智已经处在极度混乱中。" NOR;
        return RED "心智已经完全迷失，随时都有可能背过气去。" NOR;
}

varargs void report_status(object ob, int effective)
{
        string str;
        if( effective ) 
                str = sprintf("( $N%s )\n",
                        eff_status_msg((int)ob->query("eff_kee") * 100 /(1+(int)ob->query("max_kee"))) );
        else    str = sprintf("( $N%s )\n",
                        status_msg((int)ob->query("kee") * 100/(1+(int)ob->query("max_kee")) ) );
	message_vision(str,ob);			
}

varargs void report_sen_status(object ob, int effective)
{
        message_vision( "( $N" + sen_status_msg((int)ob->query("sen") * 100 /(1+(int)ob->query("max_sen")) ) + " )\n", ob);
}

// This function calculates the combined skill/combat_exp power of a certain
// skill. This value is used for A/(A+B) probability use.
varargs int skill_power(object ob, string skill, int usage)
{
        int status, level, power;
        if( !living(ob) ) return 0;
        
        level = ob->query_skill(skill);
       
        switch(usage) 
        {
                case SKILL_USAGE_ATTACK:
                        level = ob->eff_skill_level(level, SKILL_USAGE_ATTACK);
                        level += ob->query_temp("apply/attack");
                        break;
                case SKILL_USAGE_DEFENSE:
                        level = ob->eff_skill_level(level, SKILL_USAGE_DEFENSE);
                        level += ob->query_temp("apply/defense");
                        break;
        }
        if( !level ) 
                return (int)ob->query("combat_exp") / 2;
        
        if( level>30 )
                power =  level/30*level*level;            
        else if( level>10 )             
                power =  level/10*level/3*level;
        else    power =  level*level*level/30;
        if( (status = ob->query("max_sen")) > 0 )  
        {
                if( power > 100000 )
                        power = power / status * (int)ob->query("sen");
                else    power = power * (int)ob->query("sen") / status;
        }
        power +=  ob->query("combat_exp")/10;
        return power;
}

/*战斗底层
me              攻击者
victim          被攻击者
weapon          攻击者的武器
attack_type     攻击类型，见/include/combat.h
result          攻击信息，无则引用ACTION["action"]
limb            攻击部位，无则引用LIMBS
da_msg          受伤信息, 无则引用damage_msg函数返回值
*/
varargs int do_attack(object me, object victim, object weapon, int attack_type,string result,string limb,string da_msg)
{
        mapping my, your, action, victim_action;
        string *limbs, fail_hit_msg,hit_ob_msg,s_msg;
        mixed foo;
        int ap, dp, pp, afp, vfp;   //afp: attacker->force power, vfp: victim->force power
        int damage, damage_bonus, defense_factor,force_adj;
        int wounded = 0;
        int mod_val;
    
        if( !me || !victim ) 
                return 0;
        //防止因bug导致异地攻击或安全区战斗
        //同时允许特殊攻击，比如程咬金试三板那样滴 snowtu 2008
        if( environment(me)!=environment(victim)
         && attack_type!=TYPE_SUPER )  
        {
                me->remove_killer(victim);
                victim->remove_killer(me);
                return 1;
        }
        
        s_msg = NOR"$N攻击$n，"NOR;
        my = me->query_entire_dbase();
        your = victim->query_entire_dbase();

//(1) Find out what action the offenser will take.
        action = me->query("actions");
        if( !mapp(action) ) 
        {
                me->reset_action();
                action = me->query("actions");
                if( !mapp(action) )
                {
                        CHANNEL_D->do_channel( this_object(), "sys",sprintf("%s(%s): bad action = %O",me->name(1), me->query("id"), me->query("actions", 1)));
                        return 0;
                }
        }
        if( action["name"])
                me->set_temp("action_name",action["name"]);
        if( !result || !stringp(result) || strlen(result)<1 )
                result = "\n" + action["action"] + "！\n";
        //取得me用什么兵器的数据   
        if( objectp(weapon) )
        {
                if( weapon->query("use_apply_skill") )
                        attack_skill = weapon->query("apply/skill_type");
                else    attack_skill = weapon->query("skill_type");
        }
        else    attack_skill = "unarmed";
        
        limbs = victim->query("limbs");
        if( !limb || !stringp(limb) )
                limb = limbs[random(sizeof(limbs))];
    
       //(2) 加上特殊内功的防御能力 added by yeahsi
        if( victim && victim->query_temp("jldl") && living(victim) )       //如果敌人运用了jldl,而且不是晕的                          
        {
                afp = skill_power(me, "force", SKILL_USAGE_ATTACK);
                if( afp < 1) afp = 1;
                vfp = skill_power(victim, "force", SKILL_USAGE_DEFENSE);
                if( vfp < 1 ) vfp = 1;
                mod_val = 0;
                mod_val -= random(25);
                if(!victim->query_temp("weapon")) 
                        mod_val += 10;
                if( vfp > 1000000 )     
                        mod_val = vfp / 100 * (100 + mod_val);
                else    mod_val = (100 + mod_val) * vfp / 100;
                if( mod_val < 1 ) mod_val = 1;
                force_adj=random(afp + vfp);
        }
        else 
        {
                force_adj=1;
                mod_val=1;
        }
    // (3) Fight!
    //     Give us a chance of AP/(AP+DP) to "hit" our opponent. Since both
    //     AP and DP are greater than zero, so we always have chance to hit
    //     or be hit.
    //
        if( force_adj < mod_val )
        {
                foo = "/daemon/class/puti/wuxiangforce/jldl"->jldl_result(victim, me, mod_val, force_adj,action);
                if( foo && stringp(foo) )
                        result += foo;
                damage = RESULT_FORCE;
                s_msg+= NOR"$n使用了"NOR HIR"借力打力 "NOR;    
        }
        else 
        {//Prepare AP, DP for checking if hit.
                ap = skill_power(me, attack_skill, SKILL_USAGE_ATTACK);
                if( ap < 1) ap = 1;
                dp = skill_power(victim, "dodge", SKILL_USAGE_DEFENSE);
                if( living(victim) ) 
                        dodge_skill = victim->query_skill_mapped("dodge");
                else    dodge_skill = 0;
                mod_val = 0;
                if( dodge_skill )
                {
                        victim_action = SKILL_D(dodge_skill)->query_action();
                        if( victim_action && victim_action["dodge_power"] )
                                mod_val = victim_action["dodge_power"];
                }
                if( victim->is_busy() ) dp /= 3;
                if( dp < 1 ) dp = 1;
                if( action["dodge"] )  
                        mod_val += action["dodge"];
                if( dp > 1000000 )
                        mod_val = dp / 100 * (100 + mod_val);
                else    mod_val = (100 + mod_val) * dp / 100;
                if( mod_val < 1 ) mod_val = 1;
                if( random(ap + dp) < mod_val )
                {       // Does the victim dodge this hit?
                        s_msg+= NOR"$n成功闪避 ";
                        if( !dodge_skill )
                        {
                                dodge_skill = "dodge"; 
                                result += (string)SKILL_D(dodge_skill)->query_dodge_msg(limb);
                        }
                        else
                        {
                                if( victim_action && victim_action["dodge_action"] )
                                        result += (string)victim_action["dodge_action"];
                                else    result += (string)SKILL_D(dodge_skill)->query_dodge_msg(limb);
                                //snowtu加入特殊dodge闪避时出特殊效果
                                foo = SKILL_D(dodge_skill)->on_hit(victim,me);
                                if( foo && stringp(foo) && strlen(foo)>1 )
                                        result+= foo;
                                //end                                   
                        }
                        //snowtu加入特殊NPC闪避时出特殊效果
                        foo = victim->dodge_on_hit(victim,me);
                        if( foo && stringp(foo) )
                                result+= foo;  
                        //end                                             
                        if( dp < ap && (!userp(victim) || !userp(me)) 
                         && random(sizeof(victim->query_enemy())) < 4
                         &&  random(your["sen"]*100/your["max_sen"] + your["int"]*your["cps"]) > 150 )
                        {
                                your["combat_exp"] += 1;
                                victim->improve_skill("dodge", 1);
                        }
                        // This is for NPC only. NPC have chance to get exp when fail to hit.
                        if( (ap < dp) && !userp(me) )
                        {
                                if( random(my["int"]) > 15 ) 
                                        my["combat_exp"] += 1;
                                me->improve_skill(attack_skill, random(my["int"]));
                        }
                        damage = RESULT_DODGE;
                }
                else
                {
                        //(4) Check if the victim can parry this attack.
                        if( victim->query_temp("weapon") )
                        {
                                pp = skill_power(victim, "parry", SKILL_USAGE_DEFENSE);
                                if( !weapon ) pp *= 2;
                                parry_skill = victim->query_skill_mapped("parry");
                        }
                        else
                        {
                                if( weapon ) pp = 0;
                                else pp = skill_power(victim, "unarmed", SKILL_USAGE_DEFENSE);
                                parry_skill = victim->query_skill_mapped("unarmed");
                        }
                        if( victim->is_busy() ) pp /= 3;
                        if( pp < 1 ) pp = 1;
                        mod_val = 0;
                        if( action["parry"] )
                                mod_val = action["parry"];
                        if( pp > 1000000 )
                                mod_val = pp / 100 * (100 + mod_val);
                        else    mod_val = (100 + mod_val) * pp / 100;
                        if(mod_val < 1)  mod_val = 1;
                        if( random(ap + pp)< mod_val )
                        {       //parry_skill = victim->query_skill_mapped("parry");
                                s_msg+= NOR"$n成功招架 "NOR;
                                if( !parry_skill ) parry_skill = "parry";
                                // change to SKILL_D(parry_skill) after added parry msg to those
                                // martial arts that can parry.
                                // because of number of local variable limit, here use
                                // dodge_skill
                                dodge_skill = SKILL_D(parry_skill)->query_parry_msg(weapon);
                                if( dodge_skill )       
                                        result += (string)dodge_skill;
                                else    result += (string)SKILL_D("parry")->query_parry_msg(weapon);
                                //snowtu加入特殊NPC,特殊parry招架时出特殊效果
                                foo = victim->parry_on_hit(victim,me);
                                if( foo && stringp(foo) )
                                        result+= foo;
                                if( pp < ap && (!userp(victim) || !userp(me)) 
                                 && random(sizeof(victim->query_enemy())) < 4
                                 && random(your["sen"]*100/your["max_sen"] + your["int"]*your["cps"]) > 150 )
                                {
                                        your["combat_exp"] += 1;
                                        victim->improve_skill("parry", 1);
                                }
                                damage = RESULT_PARRY;
                        }
                        else
                        {
                                //  (5) We hit the victim and the victim failed to parry
                                damage = me->query_temp("apply/damage");
                                damage = (damage + random(damage)) / 2;
                                if( action["damage"] )
                                        damage += action["damage"] * damage / 100;
                                damage_bonus = me->query_str();
                                // Let force skill take effect.
                                if( my["force_factor"] && (my["force"] > my["force_factor"]) )
                                {
                                        if( force_skill = me->query_skill_mapped("force") )
                                        {
                                                foo = SKILL_D(force_skill)->hit_ob(me, victim, damage_bonus, my["force_factor"]);
                                                if( stringp(foo) ) result += foo;
                                                else if( intp(foo) ) damage_bonus += foo;
                                        }
                                }
                                if( action["force"] )
                                        damage_bonus += action["force"] * damage_bonus / 100;
                                if( martial_skill = me->query_skill_mapped(attack_skill) )
                                {
                                        foo = SKILL_D(martial_skill)->hit_ob(me, victim, damage_bonus);
                                        if( stringp(foo) ) result += foo;
                                        else if(intp(foo) ) damage_bonus += foo;
                                }
                                // Let weapon or monster have their special damage.
                                if( weapon )
                                {
                                        foo = weapon->hit_ob(me, victim, damage_bonus);
                                        if( stringp(foo) ) result += foo;
                                        else if(intp(foo) ) damage_bonus += foo;
                                }
                                else
                                {
                                        foo = me->hit_ob(me, victim, damage_bonus);
                                        if( stringp(foo) ) result += foo;
                                        else if(intp(foo) ) damage_bonus += foo * 3 / 4;
                                }
                                if( damage_bonus > 0 )
                                        damage += (damage_bonus + random(damage_bonus))/2;
                                if( damage < 0 ) damage = 0;
                                // Let combat exp take effect
                                defense_factor = your["combat_exp"];
                                while( random(defense_factor) > my["combat_exp"] )
                                {
                                        reset_eval_cost();       // 加大执行时间
                                        damage -= damage / 3;
                                        defense_factor /= 2;
                                }
                                //(6) Inflict the damage.
                                damage = victim->receive_damage("kee", damage, me );
                                s_msg+= NOR"造成 "NOR HIR+damage+NOR" 点气血减少"NOR;
                                if( (me->is_killing(victim) || weapon)
                                 && random(damage) > (int)victim->query_temp("apply/armor") )
                                {
                                        // We are sure that damage is greater than victim's armor here.
                                        victim->receive_wound("kee",damage - (int)victim->query_temp("apply/armor"), me);
                                        if( (damage - (int)victim->query_temp("apply/armor"))>0 )
                                        s_msg+= "，同时造成"+(int)(damage - (int)victim->query_temp("apply/armor"))+" 点气血损伤"NOR;
                                        wounded = 1;
                                }
                                if(me->query_temp("ldlh")) 
                                        result = "\n" + action["action"] + "！\n";
                                if( da_msg && stringp(da_msg) )
                                        result+= da_msg;                                        
                                else    result+= damage_msg(damage, action["damage_type"]);
           
                                //(7) Give experience
                                if( !userp(me) || !userp(victim) )
                                {
                                        if( (ap < dp) && (random(my["sen"]*100/my["max_sen"] + my["int"]*my["cps"]) > 150) )
                                        {
                                                my["combat_exp"] += 1;
                                                if( my["potential"] - my["learned_points"] < 100 )
                                                        my["potential"] += 1;
                                                me->improve_skill(attack_skill, 1);
                                        }
                                        if( random(your["max_kee"] + your["kee"]) < damage )
                                        {
                                                your["combat_exp"] += 1;
                                                if( your["potential"] - your["learned_points"] < 100 )
                                                        your["potential"] += 1;
                                        }
                                }
                        }
                }
        }
        s_msg+= NOR"\n";
        result = replace_string( result, "$l", limb );
        if( stringp(action["weapon"]) )
                result = replace_string( result, "$w", action["weapon"] );
        else if( objectp(weapon) )
                result = replace_string( result, "$w", weapon->name() );
        if( objectp(victim->query_temp("weapon")) )
                result = replace_string( result, "$W",victim->query_temp("weapon")->name() );
        if( (damage != RESULT_DODGE) && (damage != RESULT_PARRY) )
        {
                //描述分类0,2,3=全,无，受伤
                if( me->query("env/brief_message")==3 || victim->query("env/brief_message")==3 )
                        message_vision("",me,victim);           
                else if( me->query("env/brief_message")==2 || victim->query("env/brief_message")==2 )
                        message_vision(s_msg,me,victim);
                else    message_vision(result, me, victim );                    
                if( damage == RESULT_FORCE && me->query("eff_kee")<0 && random(5)==3 )
                {
                        CHANNEL_D->do_channel(victim, "rumor",me->name()+"中了"+victim->name()+"的拨转招式之法，自己把自己打死了。");
                        victim->delete_temp("last_channel_msg");
                        me->heart_beat();
                 }
        }
        else
        {
                if( me->query("env/brief_message")==3 || victim->query("env/brief_message")==3 )
                        message_vision("",me,victim);
                else if( me->query("env/brief_message")==2 || victim->query("env/brief_message")==2 )
                        message_vision(s_msg,me,victim);
                else if( (!me->query("env/brief_message")&& !victim->query("env/brief_message"))
                      || (me->query_temp("ldlh") || victim->query_temp("ldlh")) )
                        message_vision(result, me, victim );
                if( martial_skill = me->query_skill_mapped(attack_skill) )
                {
                        fail_hit_msg = SKILL_D(martial_skill)->fail_hit(me, victim);
                        if( fail_hit_msg && stringp(fail_hit_msg)) 
                                message_vision(fail_hit_msg,me,victim);
                }
        }

        if( me && wizardp(me) && (string)me->query("env/combat")=="verbose" )
        {
                if( damage > 0 )
                        tell_object(me, sprintf( GRN "AP：%d，DP：%d，PP：%d，Mod：%d，伤害力：%d\n" NOR,
                                                ap/100, dp/100, pp/100, mod_val/100, damage));
                else
                        tell_object(me, sprintf( GRN "AP：%d，DP：%d，PP：%d，Mod：%d\n" NOR,
                                                ap/100, dp/100, pp/100, mod_val/100));
        }
        if( wizardp(victim) && (string)victim->query("env/combat")=="verbose" )
        {
                if( damage > 0 )
                        tell_object(victim, sprintf( GRN "AP：%d，DP：%d，PP：%d，Mod：%d，伤害力：%d\n" NOR,
                                                ap/100, dp/100, pp/100, mod_val/100, damage));
                else
                        tell_object(victim, sprintf( GRN "AP：%d，DP：%d，PP：%d，Mod：%d\n" NOR,
                                                ap/100, dp/100, pp/100, mod_val/100));
         }

         if( damage > 0 )
         {
                report_status(victim, wounded);
                if( martial_skill = me->query_skill_mapped(attack_skill) )
                {
                        hit_ob_msg=SKILL_D(martial_skill)->hit_ob_msg(me, victim);
                        if(stringp(hit_ob_msg)) message_vision(hit_ob_msg,me,victim);
                }
        
                if( me->query_temp("zxzx") == 1 )
                {
                "/daemon/class/yaomo/wudidong/qixiu-jian/zxzx"->zxzx_effect(me,victim);
                }
        
                if( victim->is_busy() ) victim->interrupt_me(me);
                if( (!me->is_killing(your["id"])) && (!victim->is_killing(my["id"])) )
                {
                        // fight until one side's kee is < 50%
                        if( victim->query("kee") < victim->query("max_kee") * 50 / 100)
                        {
                                me->remove_enemy(victim);
                                victim->remove_enemy(me);
                                message_vision( winner_msg[random(sizeof(winner_msg))], me, victim);
                        }
                }
         }
         else if( me && me->query_temp("pfmxue") == 1 )
              {         
                    "/daemon/class/kunlun/huntian-jian/xue"->pfmxue_effect(me,victim);
              } 

        if( functionp(action["post_action"]) )
                evaluate( action["post_action"], me, victim, weapon, damage);

        if( damage > 0 && attack_type != TYPE_QUICK && me->query_temp("perf_quick") && me->is_fighting(victim) )
        {
                if( me->query_temp("weapon") && me->query_temp("perf_quick/"+me->query_temp("weapon")->query("skill_type")) )
                {
                        if( me->query_temp("perf_quick/msg") )
                                message_vision(CYN+ me->query_temp("perf_quick/msg") +NOR, me, victim);
                        else
                                message_vision(CYN+ "$N得势不饶人，对$n展开连续攻击。"+NOR, me, victim);
                        do_attack(me, victim, me->query_temp("weapon"), TYPE_QUICK);
                        return 1;
                }
        }

        // See if the victim can make a riposte.
        if( attack_type==TYPE_REGULAR &&  damage < 1 &&  victim->query_temp("guarding") )
        {
                victim->set_temp("guarding", 0);
                if( random(my["cps"]) < 5 )
                {
                        message_vision("$N一击不中，露出了破绽！\n", me);
                        do_attack(victim, me, victim->query_temp("weapon"), TYPE_QUICK);
                } 
                else
                {
                        message_vision("$N见$n攻击失误，趁机发动攻击！\n", victim, me);
                        do_attack(victim, me, victim->query_temp("weapon"), TYPE_RIPOSTE);
                }
        }
        return damage;
}

//  fight()
//
//  This is called in the attack() defined in F_ATTACK, which handles fighting
//  in the heart_beat() of all livings. Be sure to optimize it carefully.
//
void fight(object me, object victim)
{
        if( !living(me) ) return;
        if( me->query_temp("netdead") && !me->query_temp("pkmeet/begin") )  
                return;
        if( victim->query_temp("netdead") && !victim->query_temp("pkmeet/begin"))   
        {
                if( member_array( me, victim->query_netdead_enemy() ) == -1 )
                        return;     // can't start fight if the victim is already netdead
        }
        if( !me->visible(victim)
         && (random(100 + (int)me->query_skill("perception")) < 100) )
                return;
    // If victim is busy or unconcious, always take the chance to make an attack.
    // added: if victim is in "no_move", similar to "is_busy".
        if( victim->is_busy() || (victim->query_temp("no_move")) 
         || !living(victim) ) 
        {
                me->set_temp("guarding", 0);
                if( !victim->is_fighting(me) ) 
                        victim->fight_ob(me);
                do_attack(me, victim, me->query_temp("weapon"), TYPE_QUICK);
        // Else, see if we are brave enough to make an aggressive action.
        } 
        else if( random( (int)victim->query("cps") * 3 ) < ((int)me->query("cor") + (int)me->query("bellicosity") / 50) ) 
        {
                me->set_temp("guarding", 0);
                if( !victim->is_fighting(me) ) victim->fight_ob(me);
                        do_attack(me, victim, me->query_temp("weapon"), TYPE_REGULAR);
        // Else, we just start guarding.
        } 
        else if( !me->query_temp("guarding") ) 
        {
                me->set_temp("guarding", 1);
                message_vision( guard_msg[random(sizeof(guard_msg))], me, victim);
                return;
        } 
        else    return;
}

//  auto_fight()
//  This function is to start an automatically fight. Currently this is
//  used in "aggressive", "vendetta", "hatred", "berserk" fight.
void auto_fight(object me, object obj, string type)
{
        // Don't let NPC autofight NPC.
        if( !userp(me) && !userp(obj) ) return;
        if( me->query_temp("looking_for_trouble") ) 
                return;
        me->set_temp("looking_for_trouble", 1);
        // This call_out gives victim a chance to slip trough the fierce guys.
        call_out( "start_" + type, 0, me, obj);
}

void start_berserk(object me, object obj)
{
        int bellicosity;
        if( !me ) return;// Are we still exist( not becoming a corpse )?
        me->set_temp("looking_for_trouble", 0);
        if( !obj ) return;

        if( wizardp(obj) ) return;  
        if( me->is_fighting(obj)                // Are we busy fighting?
         || !living(me)                         // Are we capable for a fight?
         || environment(me)!=environment(obj)   // Are we still in the same room?
         || environment(me)->query("no_fight") ) // Are we in a peace room?
                return;
        bellicosity = (int)me->query("bellicosity");
        message_vision("$N用一种异样的眼神扫视着在场的每一个人。\n", me);
        if( (int)me->query("force") > (random(bellicosity) + bellicosity)/50 ) 
                return;
        if( bellicosity > (int)me->query("score") &&  !wizardp(obj) ) 
        {
                // auto kill, mark my_killer_list. -- mon 9/23/98
                if(userp(me) && userp(obj)) 
                {
                        set_my_killer_list(me, obj);
                }
                message_vision("$N对着$n喝道：" + RANK_D->query_self_rude(me)+ "看你实在很不顺眼，去死吧。\n", me, obj);
                me->set_temp("kill/target/"+obj->query("id"),1); 
                me->kill_ob(obj);
        } 
        else 
        {
                message_vision("$N对着$n喝道：喂！" + RANK_D->query_rude(obj)+ "，" + RANK_D->query_self_rude(me) + "正想找人打架，陪我玩两手吧！\n",me, obj);
                me->fight_ob(obj);
        }
}

void start_hatred(object me, object obj)
{
        if( !me ) return;               // Are we still exist( not becoming a corpse )?
        me->set_temp("looking_for_trouble", 0);
        if( !obj )      return;
        if( me->is_fighting(obj)                // Are we busy fighting?
         || !living(me)                         // Are we capable for a fight?
         || environment(me)!=environment(obj)   // Are we still in the same room?
         || environment(me)->query("no_fight") )  // Are we in a peace room?
                return;
        // We found our hatred! Charge!
        message_vision( catch_hunt_msg[random(sizeof(catch_hunt_msg))], me, obj);
        me->kill_ob(obj);
}

void start_vendetta(object me, object obj)
{
        if( !me ) 
                return;               // Are we still exist( not becoming a corpse )?
        me->set_temp("looking_for_trouble", 0);
        if( !obj )      return; 
        if( me->is_fighting(obj)                // Are we busy fighting?
         || !living(me)                         // Are we capable for a fight?
         || environment(me)!=environment(obj)   // Are we still in the same room?
         || environment(me)->query("no_fight") ) // Are we in a peace room?
                return;
        me->kill_ob(obj);
}

void start_aggressive(object me, object obj)
{
        if( !me ) return;               // Are we still exist( not becoming a corpse )?
        me->set_temp("looking_for_trouble", 0);
        if( !obj )      return;
        if( me->is_fighting(obj)                // Are we busy fighting?
         || !living(me)                         // Are we capable for a fight?
         || environment(me)!=environment(obj)   // Are we still in the same room?
         || environment(me)->query("no_fight") ) // Are we in a peace room?
                return;
        me->kill_ob(obj);
}

//add by yesi 
void start_pkmeet(object me, object obj)
{
        if( !me ) return; 
        me->set_temp("looking_for_trouble", 0);
        if( !obj )      return;
        if( me->is_fighting(obj)                // Are we busy fighting?
         || !living(me)                         // Are we capable for a fight?
         || environment(me)!=environment(obj)   // Are we still in the same room?
         || environment(me)->query("no_pkmeet") ) // Are we in a peace room?
                return;
        me->kill_ob(obj);
}    
        
// This function is to announce the special events of the combat.
// This should be moved to another daemon in the future.
void announce(object ob, string event, string msg)
{
        if( !ob )
                return;
        if( ob->query_temp("pkgame") ) 
                return;
        switch(event) 
        {
                case "dead":
                        message_vision("\n$N「啪」的一声倒在地上，挣扎着抽动了几下就死了。\n\n", ob);
                        break;
                case "unconcious":
                        message_vision("\n$N神志迷糊，脚下一个不稳，倒在地上昏了过去。\n\n", ob);
                        break;
                case "revive":
                         if(ob->query("blind") || ob->query("race") != "人类")
                             message_vision("\n$N身子一颤，扭动了几下，清醒了过来。\n\n", ob);
                        else if(ob->query("mute"))
                             message_vision("\n$N慢慢清醒了过来，睁开眼睛站起来摇了摇头。\n\n", ob);
                        else message_vision("\n$N身子动了动，口中呻吟了几声，清醒过来。\n\n", ob);
                        break;
                case "death_rumor":
                        CHANNEL_D->do_channel(this_object(),"rumor",msg);
                        break;
        }
}

void winner_reward(object killer, object victim)
{
        killer->defeated_enemy(victim);
}

void killer_reward(object killer, object victim)
{
        int i,bls,exp, pot, score,level;
        int iRealDie ; // add by canoe for Start PkGame ?
        string vmark,killmsg,rkmsg;
        int gain,gain1,lose;
        string str,killerid;
        object weapon,*oUser,*fire; //add by take for CS
  
        // Call the mudlib killer apply.
        killer->killed_enemy(victim);
        if( userp(victim) )  // victim is user.
        {            
                string *my_killer_list;
                int init_killer;
                int no_pk;
                // edit by canoe for PkGame 02-1-17 12:11
	        iRealDie =  "/cmds/usr/pkgame"->query_pk() ;
         if ( iRealDie && userp(killer) && (killer->query_temp("pkgame") || victim->query_temp("pkgame")))
	   {
	   	if ( killer != victim )
	   	{
	   		switch ( random(4) )
	   		{
	   			case 0 : killmsg = "$o光荣牺牲于$t的手下。" ;	
	   				 break ;
	   			case 1 : killmsg = "$t神勇无敌，将$o斩于马下。";
	   				 break ;
	   			case 2 : killmsg = "惨叫声中，$t已将$o首级提在手中。";
	   				 break ;
	   			default : killmsg = "一声惨叫，$o已经被$t送去西天。";
	   		}
	   		rkmsg = victim->query("name")+"（"+victim->query("id")+"）" ;
	   		killmsg = replace_string ( killmsg, "$o", rkmsg ); 
	   		rkmsg = killer->query("name")+"（"+killer->query("id")+"）" ;
	   		killmsg = replace_string ( killmsg, "$t", rkmsg );
	   		if ((killer->query_temp("pkgame"))==(victim->query_temp("pkgame"))) killer->add_temp( "pgwin" , -1 );  // 对cs系统的限制
	   		if ((killer->query_temp("pkgame"))!=(victim->query_temp("pkgame"))) 
			{
				killer->add_temp( "pgwin" ,querypgwin(killer,victim));   // 同上
				victim->add_temp( "pgwin" ,-1 );   // 同上
			}
			//暂时注释掉,cac 7.3
	   		//if (!victim->query_temp("pkgame") && userp(victim)) killer->die(); //同上
	   		CHANNEL_D->do_channel ( this_object() , "rumor" , killmsg );
	   	}else if ( killer == victim )
	   	{
	   		CHANNEL_D->do_channel ( this_object() , "rumor" , "由于ｃｓ大赛过于激烈"HIW+victim->query("name")+HIM"不堪承受强大的对手所带来的压力，身心憔悴死在安全区。" );
	   		if ( killer->query_temp("pkgame") ) killer->add_temp( "pgwin" , -2 );
	   	}
	      	victim->clear_condition();
		victim->delete_temp("last_fainted_from");	
		killer->remove_all_killer();
		victim->remove_all_killer();
		if ( killer != victim )
		message_vision(HIR"\n\n眼见$N不敌，被$n一脚踹到CS休息室去了。\n"NOR,victim,killer);
	        else if ( killer == victim )
	        message_vision(HIR"\n\n$N太胆小了，还是先去休息室喘口气再来吧。\n"NOR,victim);
	        if (victim->query_temp("pkgame")) victim->move("/u/cloud/cs/waitpk");
	        oUser = users();
		for ( i = 0 ; i < sizeof(oUser) ; i ++ ) 
        	{
        		if ((oUser[i]->query_temp("pkgame")==victim->query_temp("pkgame")) && (environment(oUser[i])->query("short") != HIR"CS休息室"NOR))
        			i = sizeof(oUser)+1;
                }
        	if ( i == sizeof(oUser) )
        	{
        		if ( killer == victim )
        		{
        			if ( (killer->query_temp("pkgame") == "t") && (sizeof(fire) == 0) )
        			{
        				message( "system", BLINK HIR"\n【 CS 大赛】： 本局结束，此局比赛"+HIY"大侠"+BLINK HIR"组获胜,请各位准备5秒钟后开始下一局比赛。。。。。。\n" NOR, users() );
       					"/cmds/usr/pkgame"->over();
       					"/cmds/usr/pkgame"->query_Win("ct");
       				}
        			if ( killer->query_temp("pkgame") == "ct" )
        			{
       					message( "system", BLINK HIR"\n【 CS 大赛】： 本局结束，此局比赛"+HIY"纵火犯"+BLINK HIR"组获胜,请各位准备5秒钟后开始下一局比赛。。。。。。\n" NOR, users() );
       					"/cmds/usr/pkgame"->over();
       					"/cmds/usr/pkgame"->query_Win("t");
       				}
       			}
       			if ( killer != victim )
       			{
       				if ( killer->query_temp("pkgame") == "t")
        			{
       					message( "system", BLINK HIR"\n【 CS 大赛】： 本局结束，此局比赛"+HIY"纵火犯"+BLINK HIR"组获胜,请各位准备5秒钟后开始下一局比赛。。。。。。\n" NOR, users() );
       					"/cmds/usr/pkgame"->over();
       					"/cmds/usr/pkgame"->query_Win("t");
       				}	
       				fire = children ("/d/dntg/sky/obj/fire");
       				if ( (killer->query_temp("pkgame") == "ct") && (sizeof(fire) == 0) )
        			{
        				message( "system", BLINK HIR"\n【 CS 大赛】： 本局结束，此局比赛"+HIY"大侠"+BLINK HIR"组获胜,请各位准备5秒钟后开始下一局比赛。。。。。。\n" NOR, users() );
       					"/cmds/usr/pkgame"->over();
       					"/cmds/usr/pkgame"->query_Win("ct");
       				}
       			}
              	 }
         return ; // by take for cs 2002.2.1 17:56
        }
        else 
        {
                killer->add("PKS", 1);
                killer->add("PKD", 1);
           
                killerid=killer->query("id");
//增加死亡记录、仇人名、日期  by LitChi
                victim->set("kill/killer_name",killer->query("name"));
//By tianlin@mhxy for 2002.1.23修改litchi做的时间加入pker id.
                victim->set("kill/killer_id",killer->query("id"));
//                  victim->set("kill/killer_date",BJTIME_D->chinese_time(1, time()) ); 
//add by snowtu
                        victim->set("death/mud_age",victim->query("mud_age"));
                        victim->add("death/die",1);        
// mon 8/4/98
// to see whether the killer has init the kill on me.
// if yes, then this is PK. (init_killer!=-1)
// if no, (means the victim init the kill and got killed),
// then treat this as normal death. (init_killer==-1)
                my_killer_list=victim->query_temp("my_killer_list");
                victim->delete_temp("my_killer_list");
                if(!my_killer_list) init_killer=-1;
                else init_killer = member_array(killerid, my_killer_list);
                
                no_pk = killer->query_condition("no_pk_time");
                if(no_pk>10) init_killer=1;
          } // killed by a player who
           // has PK record, then this is PK.
           // regardless who init it.
///////////////////////////////////////////////////////////////////////
                killmsg = killer->query_temp("kill_msg");
                if(killmsg)
                {
                        switch (killmsg)
                        {
                                case "slash": rkmsg="斩";break;
                                case "slice": rkmsg="砍";break;
                                case "chop":  
                                case "hack":  rkmsg="劈";break;
                                case "thruse":
                                case "pierce":rkmsg="刺";break;
                                case "wave":  rkmsg="鞭";break;
                                case "whip":  rkmsg="抽";break;
                                case "impale":rkmsg="戳";break;
                                case "rake":  rkmsg="筑";break;
                                case "bash":  
                                case "crush": rkmsg="砸";break;
                                case "slam":  rkmsg="挫";break;
                                case "throw": 
                                case "shoot": rkmsg="射";break;
                                /***************** Cast **********************/
                                //wzg
                                case "cast_zhenhuo": rkmsg="太乙真火";break;
                                case "cast_baxian":  rkmsg="八仙大阵";break;
                		case "cast_feng"  :  rkmsg="乾坤封咒";break;
                                //putuo
                                case "cast_bighammer":rkmsg="大力降魔杵";break;
                                case "cast_jingang":  rkmsg="召唤金刚";break;
                                case "cast_jinguzhou":rkmsg="紧箍咒";break;
                                case "cast_fochang":  rkmsg="我佛梵唱";break;
                                //pansi
                                case "cast_love":     rkmsg="此情可待";break;
                                case "cast_wuzhishan":rkmsg="五指山";break;
                                case "cast_ziqi":     rkmsg="氤氲紫气";break;
                                //moon
                                case "cast_arrow":    rkmsg="落日神箭";break;
                                case "cast_shiyue":   rkmsg="蚀月咒";break;
                                case "cast_mihun":    rkmsg="迷魂咒";break;
                                case "cast_huimeng":  rkmsg="回梦咒";break;
                                case "cast_qingwang": rkmsg="情网";break;
                                case "cast_hufa":     rkmsg="召唤护法";break;
                                //fc
                                case "cast_thunder":  rkmsg="五雷咒";break;
                                case "cast_invocation":rkmsg="召唤天将";break;
                                case "cast_fenshen":  rkmsg="分身术";break;
                                case "cast_dingshen": rkmsg="定身法";break;
                                case "cast_light":    rkmsg="苍灵箭";break;
                                case "cast_preach":   rkmsg="三清布道";break;
                                case "cast_taijitu":  rkmsg="太极无形";break;
                                //xs
                                case "cast_jieti":    rkmsg="天魔解体大法";break;
                                case "cast_tuntian":  rkmsg="魔兽吞天";break;
                                case "cast_juanbi":   rkmsg="白象卷鼻";break;
                                //hell
                                case "cast_gouhun":
                                case "cast_curse" :   rkmsg="勾魂术";break;
                                case "cast_animate":  rkmsg="复活鬼魂";break;
                                case "cast_heiwu":    rkmsg="炼狱黑雾";break;
                                case "cast_hunfei":   rkmsg="魂飞魄散";break;
                                case "cast_necromancy":rkmsg="召唤骷髅";break;
                                case "cast_shibao":   rkmsg="腐尸爆裂";break;
                                case "cast_zhuang":   if( killer->query_skill_mapped("spells")=="gouhunshu" )
								rkmsg="元神冲撞";
                                                      else      rkmsg="平天大法";break;
                                //sea
                                case "cast_freez":    rkmsg="雪舞风灵";break;
                                case "cast_dragonfire":rkmsg="真龙神火";break;
                                case "cast_water":    rkmsg="龙神水柱";break;
                                //hyd
                                case "cast_niushi":   rkmsg="无边牛虱";break;
                                case "cast_sanmei":   rkmsg="三味真火";break;
                                //wdd
                                case "cast_bite":     rkmsg="白毛玉鼠";break;
                                //shushan
                                case "cast_fu":       rkmsg="天师符法";break;
                                case "cast_jiushen":  rkmsg="酒神";break;
                                case "cast_jianshen": rkmsg="剑神";break;
                                case "cast_yizhi":    rkmsg="乾坤一掷";break;
                                //tianpeng
                                case "cast_yading":   rkmsg="天猪压顶";break;
                                //shenjian
                                case "cast_sword":    rkmsg="剑中剑";break;
                                //tkj
                                case "cast_pdzs":    rkmsg="普渡众生";break;
                                case "cast_zhonglixin":    rkmsg="重力心";break;
                                case "cast_heijie":    rkmsg="暗黑结界";break;
                                //lingjie
                                case "cast_lingguang": rkmsg="一线灵光";break;
                                case "cast_nine":      rkmsg="九字真言";break;
                                //mojiao
                                case "cast_lei":      rkmsg="紫靓神雷";break;
                                case "cast_fog":      rkmsg="云淡风清";break;
                                case "cast_moshen":      rkmsg="魔啸";break;
                                /***************** Perform **********************/                         
                                case "perform_sanban": rkmsg="无敌三板斧";break;
                                case "perform_haotan": rkmsg="痴情八叹";break;
                                case "perform_hongyan":rkmsg="红颜白发";break;  
                                case "perform_zplw":   rkmsg="猪耙乱舞";break;  
                                case "perform_daoda":  rkmsg="倒打一耙";break;  
                                case "perform_daoluan":rkmsg="倒乱七星";break;  
                                case "perform_huadie": rkmsg="化    蝶";break;
                                case "perform_mantian":rkmsg="青霞漫天";break;
                                case "perform_wang":   rkmsg="天罗地网";break;
                                case "perform_kai":    rkmsg="开天辟地";break;
                                case "perform_meihua": rkmsg="梅花六出";break;
                                case "perform_lei":    rkmsg="雷殛怒火";break;
                                case "perform_zhua":   rkmsg="无常爪";break;
                                case "perform_ldlh":   rkmsg="六道轮回";break;
                                case "perform_lunhui": rkmsg="炼狱";break;
                                case "perform_pudu":   rkmsg="慈光普渡";break;
                                case "perform_xlfh":   rkmsg="降龙伏虎";break;
                                case "perform_storm":  rkmsg="暴风骤雨";break;
                                case "perform_diyu":   rkmsg="我入地狱";break;
                                case "perform_pili":   rkmsg="霹雳三打";break;
                                case "perform_qiankun":rkmsg="乾坤一棒";break;
                                case "perform_pozhan": rkmsg="破绽百出";break;
                                case "perform_zhangxinlei":rkmsg="掌心雷";break;
                                case "perform_flower": rkmsg="天女散花";break;
                                case "perform_diezhang":rkmsg="叠掌";break;
                                case "perform_huifeng": rkmsg="回风";break;
                                case "perform_wuxue":  rkmsg="舞雪";break;
                                case "perform_sheshen":rkmsg="舍身技";break;
                                case "perform_three":  rkmsg="神·人·鬼";break;
                                case "perform_chaofeng":rkmsg="百鸟朝凤";break;
                                case "perform_feijian": rkmsg="飞鸟投林";break;
                                case "perform_yaowu":  rkmsg="妖雾冲天";break;
                                case "perform_fumo":   rkmsg="御剑伏魔";break;
                                case "perform_jinsheng":rkmsg="御剑今生";break;
                                case "perform_wanjian":rkmsg="万剑决";break;
                                case "perform_duanshui":rkmsg="断水无痕";break;
                                case "perform_feilong": rkmsg="飞龙探云手";break;
                                case "perform_buhui": rkmsg="不悔";break;
                                case "perform_fengchan": rkmsg="五岳封禅";break;
                                case "perform_ji": rkmsg="祭枪";break;
                                case "perform_huohun": rkmsg="火魂";break;
                                case "perform_lihuo": rkmsg="离火三重";break;
                                case "perform_shenli": rkmsg="神力";break;
                                case "perform_leidong":rkmsg="雷动九天";break;
                                case "perform_break":  rkmsg="混元一破";break;
                                case "perform_fengbo": rkmsg="无尽风波";break;
                                case "perform_juejian":rkmsg="三清绝剑";break;
                                case "perform_jianzhang":rkmsg="剑掌";break;
                                case "perform_jianmang":rkmsg="灵幻剑芒";break;
                                case "perform_jianqi":rkmsg="灵幻剑气";break;
                                case "perform_luanwu":rkmsg="群魔乱舞";break;
                                case "perform_tiandi":rkmsg="天地同寿";break;
                                case "perform_zouxiao":rkmsg="碧箫传情";break;
                                case "perform_damoyange":rkmsg="大漠雁歌";break;
                                /***************** EXert **********************/ 
                                case "exert_sheqi": rkmsg="摄气";break;
                                case "exert_roar" : rkmsg="龙吟";break;
                                case "special_msg"://特殊的攻击
                                {       
                                        rkmsg=killer->query_temp("special_msg");        
                                        killer->delete_temp("special_msg");
                                }
                                break;
                        }
                }//if(killmsg)
                if( userp(killer) && init_killer!=-1) // killer is user.
                {
                        killer->apply_condition("no_pk_time",240+no_pk);
                        lose = victim_lose(killer,victim,killerid);
                        gain=lose*8/10;
                        if(gain<0) gain=0;
                        victim->delete_temp("last_fainted_from");
                        if(lose>100)
                                killer->delete("kill/last_killer");
                        killer->add("kill/pkgain",gain);
                        killer->add("daoxing",gain);
                        victim->set("kill/last_killer",killerid);
                        victim->set("kill/last_lose",gain);
                        victim_penalty(victim);
                        str=chinese_daoxing(gain);
                        if(strlen(str)>1) 
                                str = killer->name(1)+"得到"+str+"道行！";
                        weapon=killer->query_temp("kill_weapon");
                        if(weapon && rkmsg)
                        {                       
                                str = victim->name(1)+"在"+MISC_D->find_place(environment(killer))+"被"+killer->name(1)+"用"HIY+weapon->name()+HIM+rkmsg+"死了。"+str;
                                CHANNEL_D->do_channel(this_object(), "rumor",str);
                        } 
                        else 
                        {
                                if(rkmsg && !weapon)
                                {
                                        str=victim->name(1)+"在"+MISC_D->find_place(environment(killer))+"被"+killer->name(1)+"用一招"+"“"HIW+rkmsg+"”"NOR+HIM"送去见了阎王。"+str;
                                        CHANNEL_D->do_channel(this_object(), "rumor",str);
                                }
                                else if(weapon && !rkmsg)
                                {
                                        str=victim->name(1)+"在"+MISC_D->find_place(environment(killer))+"被"+killer->name(1)+"用"HIY+weapon->name()+HIM"送去了见了阎王。"+str;
                                        CHANNEL_D->do_channel(this_object(), "rumor",str);
                                }
                                else 
                                {
                                        str=victim->name(1)+"在"+MISC_D->find_place(environment(killer))+"被"+killer->name(1)+"杀死了。"+str;
                                        CHANNEL_D->do_channel(this_object(), "rumor",str);
                                }
                        }
                        bls=10;
                        killer->delete_temp("kill_weapon");
                        killer->delete_temp("kill_msg");
                } 
                else     // killer is not user or killer didn't init the kill.
                {                    
                        string last_faint;
                        object fainter; 
               // mon 8/1/98
               // check who fainted the victim.
               // if it was a player faint the victim,
               // give the player credit for pk :)
                        last_faint=victim->query_temp("last_fainted_from");
                        if(last_faint) 
                        {
                                fainter=find_player(last_faint);
                                if(fainter && userp(fainter)) 
                                {
                                        if(!my_killer_list) init_killer=-1;
                                        else init_killer=member_array(last_faint, my_killer_list);
                                        if(init_killer!=-1) 
                                        {
                                                fainter->apply_condition("no_pk_time",240+fainter->query_condition("no_pk_time"));
                                                log_file("death","["+ctime(time())+"] "+victim->query("id")+" was fainted by "+fainter->query("id")+" and killed by "+killer->query("id")+".\n");
                                        }
                                }
                        }
                        victim_penalty(victim);
                        bls = 10;
//             CHANNEL_D->do_channel(this_object(), "rumor",
//                sprintf("%s被%s杀死了。", victim->name(1), killer->name(1)));
/////////////////for NK rumor
//by tianlin 2001.8.15          
                        weapon=killer->query_temp("kill_weapon");
                        if(weapon && rkmsg)
                        {                       
                                str=victim->name(1)+"在"+MISC_D->find_place(environment(killer))+"被"+killer->name(1)+"用"HIY+weapon->name()+HIM+rkmsg+"死了。";
                                CHANNEL_D->do_channel(this_object(), "rumor",str);
                        } 
                        else 
                        {
                                if(rkmsg && !weapon)
                                {
                                        str=victim->name(1)+"在"+MISC_D->find_place(environment(killer))+"被"+killer->name(1)+"用一招"+HIW"“"+rkmsg+"”"+HIM"送去了阎罗地府。";
                                        CHANNEL_D->do_channel(this_object(), "rumor",str);
                                }
                                else if(weapon && !rkmsg)
                                {
                                        str=victim->name(1)+"在"+MISC_D->find_place(environment(killer))+"被"+killer->name(1)+"用"HIY+weapon->name()+HIM"送去了阎罗地府。";
                                        CHANNEL_D->do_channel(this_object(), "rumor",str);
                                }
                                else 
                                {
                                        str=victim->name(1)+"在"+MISC_D->find_place(environment(killer))+"被"+killer->name(1)+"杀死了。";
                                        CHANNEL_D->do_channel(this_object(), "rumor",str);
                                }
                                if( userp(killer) && !killer->query_temp("kill_killer")) 
                                        CHANNEL_D->do_channel(this_object(), "rumor",sprintf("%s被官府通缉了。", killer->name(0)));
                                if(victim->query("PKD")>9)
                                {                       
                                        str=HIR+"杀人犯"+HIM+victim->name(1)+"在"+MISC_D->find_place(environment(killer))+HIM+"被"+killer->name(1)+HIM+"就地正法"+HIM+"，"+killer->name(1)+"得到了应有的奖励。";
                                        CHANNEL_D->do_channel(this_object(), "rumor",str);
                                        killer->add("daoxing",5000);
                                        victim->set("PKD",0);
                                }
                                if(killer->query("PKD")>9)
                                {                       
                                        str=victim->name(1)+"在"+MISC_D->find_place(environment(killer))+HIM+"被"HIR"杀人犯"HIM+killer->name(1)+HIM+"杀死了"+HIM+"，"+killer->name(1)+"被玉皇大帝减少道行十五年作为处罚。";
                                        CHANNEL_D->do_channel(this_object(), "rumor",str);
                                        killer->add("daoxing",-15000);
                                        victim->set("PKD",0);
                                }       
                        }
                }
        } 

        else   //NPC is the victim.
        {
                if(userp(killer)) 
                {
                        int reward;

                        reward=nk_gain(killer, victim);
                        // nk_reward is defined as needed for each NPC
                        // this allows individual NPC to customize NK reward.
                        // mon 12/24/99
                        if((int)victim->nk_reward(killer, reward)>0) 
                        { // this NPC has its own reward.
                        } 
                        else if(reward>0) 
                        {
                                string msg;
                                killer->add("kill/nkgain",reward);
                                killer->add("daoxing",reward);
                                str=chinese_daoxing(reward);
                                tell_object(killer,"\n你得到了"+str+"道行。\n");
                                msg=sprintf("%s(%d)杀死了%s(%d)，得到%d点道行。", 
                                                killer->query("id"),(killer->query("daoxing")+
                                                killer->query("combat_exp"))/2, 
                                                victim->query("id"),(victim->query("daoxing")+
                                                victim->query("combat_exp"))/2,reward);
                                log_file("npc_kill","["+ctime(time())+"] "+msg+"\n");
                                CHANNEL_D->do_channel(this_object(), "sys",msg);
                        }
                }
                killer->add("MKS", 1);
                bls = 1;
        }

        if( !userp(killer) 
         &&((killer->query("daoxing")+killer->query("combat_exp"))/10>(victim->query("daoxing")+victim->query("combat_exp"))) ) 
                bls=0;
        //mon 2/15/98
        //can't use newbie to kill NPC to increase NPC's bls.
        // NPC got 10 times of bellicosity than user.
        killer->add("bellicosity", bls * (userp(killer)? 1: 10));
        if( stringp(vmark = victim->query("vendetta_mark")) )
                killer->add("vendetta/" + vmark, 1);
        if(userp(killer)) killer->save();
        if(userp(victim)) victim->save();
}
//被杀害的玩家参数设定
void victim_penalty(object victim)
{
        int i;
        // by snowcat 2/21/1998 for death/*
        int combat_exp_loss = (int)victim->query("combat_exp") / 40;
        int dx_loss = (int)victim->query("daoxing") / 40;

        victim->clear_condition();
        // Give the death penalty to the dying user.
        victim->set("bellicosity", 0);

        i=victim->query_condition("no_pk_time");
        if(i>240) victim->apply_condition("no_pk_time",i-80);

        victim->set("death/mud_age",victim->query("mud_age"));
        victim->set("death/combat_exp_loss",combat_exp_loss);
        victim->set("death/dx_loss",dx_loss);
        log_file("death",victim->query("id")+" lost "+combat_exp_loss+" exp points and "+ dx_loss+ " dx points.\n");

        victim->add("combat_exp", -combat_exp_loss);
        victim->add("daoxing", -dx_loss);
        victim->add("death/die",1);
        victim->delete("vendetta");
        if( victim->query("thief") )
                victim->set("thief", (int)victim->query("thief") / 2);
        if( (int)victim->query("potential") > (int)victim->query("learned_points"))
                victim->add("potential",((int)victim->query("learned_points") - (int)victim->query("potential"))/2 );//死亡掉的qn现在设定为2分之1
        if(random(100)>(int)victim->query("kar")) 
        {
                victim->set("death/skill_loss",1);
                victim->skill_death_penalty();
        }
//        else
//        victim->set("death/skill_loss",0);
        victim->save();
}

int nk_gain(object killer, object victim)
{
        string fam, fam1;
        int cla, eff_dx, eff1, eff2, dx, reward, nkgain;

        // some NPC has no rewards.mon 3/9/99
        if(victim->query("no_nk_reward")) 
                return 0;
        //can't kill NPCs which were fainted by other players to get daoxing.
        if( victim->query_temp("last_fainted_from")
         && victim->query_temp("last_fainted_from")!=killer->query("id")) 
                return 0;
        fam=killer->query("family/family_name");
        if(fam && !undefinedp(family[fam])) //player must have a family.
        {
                cla=family[fam];
                eff_dx=victim->query("eff_dx");
                nkgain=victim->query("nkgain");

              //can't kill NPCs of the same menpai as the player
              //to get daoxing.
                fam1=victim->query("family/family_name");
                if(fam1 && fam==fam1)
                        return 0;
                if(eff_dx!=0 && cla*eff_dx>0)
                        return 0;
                //for NPC being set eff_dx, only 
                //if cla*eff_dx<=0 (not all in xian or all in yao)
                //can gain daoxing.
              //For NPC which has not been set eff_dx,
              //the default is everyone can kill them to get
              //dx reward, however, the default value is low.
                if(!eff_dx) { 
                //default value for eff_dx and nkgain.
                //the default nkgain is low.
                //If want to increase the value for certain NPC,
                //then need to set its eff_dx and nkgain.
                        int dxn=0;
                        eff_dx=(victim->query("daoxing")+victim->query("combat_exp"))/2;
                        if(eff_dx>20000)
                                dxn=eff_dx/3;
                        else if(eff_dx>5000)
                                dxn=eff_dx/2;
                        else    dxn=eff_dx;
                  //make it easier for newbie.
                        eff_dx=dxn;
                }
                if(!nkgain) 
                {
                        int effdx=eff_dx;
                        if(effdx<0) effdx=-effdx;
                        if(effdx>667000) 
                                nkgain=600;
                        else if(effdx>333000)
                                nkgain=500;
                        else if(effdx>100000)
                                nkgain=400;
                        else if(effdx>33000)
                                nkgain=300;
                        else if(effdx>17000)
                                nkgain=200;
                        else if(effdx>5000)
                                nkgain=150;
                        else if(effdx>2000)
                                nkgain=100;
                        else if(effdx>500)
                                nkgain=50;
                        else nkgain=25;
                        nkgain=nkgain+20;
                }

                if(eff_dx<0) eff_dx=-eff_dx;
                eff1=eff_dx/8;
                eff2=eff_dx/4;
                dx=(killer->query("daoxing")+killer->query("combat_exp"))/2;
                if(dx>eff_dx) reward=0;
                else if(dx>eff2) reward=nkgain;
                else if(dx>eff1) reward=10*(dx-eff1)/(eff2-eff1)*(nkgain/10);
                else reward=0;

                if(cla==0 || (cla!=0 && !fam1)) reward=reward*2/3;
                //cla==0: people not xian and not yao. e.g. longgong, moon.
                //cla!=0: people either xian or yao. if they kill
                //        no family NPC, dx reward reduse.
                return reward;
                }
        return 0;
}

int victim_lose(object killer,object victim,string killerid) 
{            
        int lose,exp_k,exp_v;
        int lose1;

        if((wizardp(victim)&&!wizardp(killer))
         ||(!wizardp(victim)&&wizardp(killer)))
                return 0;
        if(victim->query_temp("last_fainted_from")
        && victim->query_temp("last_fainted_from")!=killerid) 
                lose=0;
        else 
        {
                exp_k=killer->query("daoxing");
                exp_v=victim->query("daoxing");
                if(exp_k>exp_v) 
                {
                        lose=10*exp_v/(exp_k+1)*(4000+exp_v)/500;
                        // a exp_v/exp_k pre-factor.
                        if(exp_k>exp_v*4) lose=0;
                        // if less then 1/4 dx, then no damage.
                } 
                else    lose=(4000+exp_v)/50;  // about 2% lose for victim.
                if(lose<0) lose=0;
                if(lose>exp_v) lose=exp_v;
        }
            // this is the maximum lose.
        lose1=(int)victim->query("daoxing") / 40;
        if(lose>lose1) lose=lose1;
        return lose;
}

string chinese_daoxing(int gain)
{            
        int year,day,hour;
        string str;

        year=gain/1000;
        day=(gain-year*1000)/4;
        hour=(gain-year*1000-day*4)*3;
        str="";
        if(year) str=str+chinese_number(year)+"年";
        if(day) str=str+chinese_number(day)+"天";
        if(hour) str=str+chinese_number(hour)+"时辰";
        return str;
}

int check_family(string fam)
{
        if(fam && !undefinedp(family[fam]))
                return family[fam];
        else    return 0;
}

//the following functions are for performs...weiqi
//copy and modified from spelld.c
int attacking_perform_success(object attacker, object target, int skill_level, int success_adj)
{
        int ap, dp, success;
         ap = ( skill_level * skill_level * skill_level / 10 ); //this is from skill.
        //at high exp, the skill level can not follow, so need adjustment here.
        ap = ap*(1+attacker->query("combat_exp")/500000);
        ap = ap+attacker->query("combat_exp");
        dp = target->query("combat_exp");
        success = 0;

        if( success_adj < 20 ) success_adj = 20;
        else if( success_adj > 500 ) success_adj = 500;

        ap = ap*success_adj/100;

        if( random(100)>dp*100/(ap+dp) ) success = 1;

        return success;
}

int attacking_perform_damage(object attacker, object target, int damage_adj)
{
        int a_neili, d_neili, damage;

        if( damage_adj < 50 ) damage_adj = 50;
        else if( damage_adj > 200 ) damage_adj = 200;

        //will use current neili...but do not allow it exceeds 2 time of the max.
        a_neili = attacker->query("force");
        if( a_neili > 2*attacker->query("max_force") ) a_neili = 2*attacker->query("max_force");
        d_neili = target->query("force");
        if( d_neili > 2*target->query("max_force") ) d_neili = 2*target->query("max_force");


        //neili and qi. weaker than cast here...
        damage = (a_neili - d_neili)/30 + 
                random(attacker->query("eff_kee") / 30)-random(target->query("eff_kee") / 30);

        //mana_factor, here the attacker has some advantage.
        //the damage_adj higher, the better for attacker.
        damage += (3*damage_adj/200) //weaker than cast here...
                *( attacker->query("force_factor") - random(target->query("force_factor")) );

        //for backfire, we need let it be serious...
        if( damage < 0 ) damage = damage - target->query("force_factor"); 
        //here increase the damage, since previously it's included in random()

        damage = damage*damage_adj/100; //last damage scaled again.

        //finally, we need let the force level useful...
        //the setting is, at enabled level 200, the damage will double.
        if( damage > 0 )
        {
                damage += (damage*(int)attacker->query_skill("force"))/200;
        }
        else if( damage < 0 )
        {
                damage += (damage*(int)target->query_skill("force"))/200;
        }
        
        
        return damage;
}

/*
weiqi 981206
attacking-cast...called from spells function.
modified for perform...
a typical call would be:

        COMBAT_D->attacking_perform(
                me, 
                        //attacker 
                target, 
                        //target
                skill_level, 
                        //level of skill used
                success_adj, 
                        //success adjustment
                damage_adj, 
                        //damage adjustment
                "both", 
                        //damage type: could be "qi"/"kee", "shen"/"sen", ...default "both"
                HIC "$N几个指头迅速捻动，突然张嘴一喷！红橙黄三道火焰呼！地一声向$n卷去！\n" NOR,
                        //initial message
                HIC "结果$n被烧得焦头烂额！\n" NOR, 
                        //success message
                HIC "但是$n轻轻一跳就躲了开来。\n" NOR, 
                        //fail message
                HIC "但是火焰被$n以法力一逼，反向$N回卷而去！\n" NOR, 
                        //backfire initial message
                HIC "结果太乙真火反噬，$n被烧得焦头烂额！\n" NOR
                        //backfire hit message. note here $N and $n!!!
        );
*/
void attacking_perform(
        object attacker, 
        object target, 
        int skill_level,//the level of skill used to attack.
        int success_adj, 
        int damage_adj, //default value is 100 for this 2 parameters.
        string damage_type, //must be "shen"/"sen", "qi"/"kee" or "both"(default)
        string msg_init, 
        string msg_success, 
        string msg_fail, 
        string msg_backfire_init,
        string msg_backfire_success)
{
        int damage;

        //first, show the initial message...
        if( attacker->query("env/brief_message") || target->query("env/brief_message") )
                message_vision("",attacker,target);             
        else    message_vision( msg_init, attacker, target );

        //calculate if the casting can happen...
        if( attacking_perform_success(attacker, target, skill_level, success_adj) == 0 )
        {
                message_vision( msg_fail, attacker, target );
                //let the target kill attacker.
                target->kill_ob(attacker);
                return;
        }

        damage = attacking_perform_damage(attacker, target, damage_adj);

        if( damage > 0 ) //attacker hit target
                SPELL_D->apply_damage(attacker, target, damage, damage_type, msg_success);

        else if( damage < 0 ) //backfire
        {
                message_vision(msg_backfire_init, attacker, target);
                SPELL_D->apply_damage(target, attacker, -damage, damage_type, msg_backfire_success);
        }

        else //damge=0
                message_vision(HIB "结果正好被$N以内力逼住，谁也没有吃亏。\n" NOR, target);

        //let the target kill attacker.
        target->kill_ob(attacker);

        return;
}

int CheckExp2(object killer,object victim,int multi)
{
        if(killer->query("combat_exp")/multi>victim->query("combat_exp"))
                return 1;
        return 0;
}

//luoye所用，自DT移植过来
int calc_damage(object attacker, object target, int damage)
{
        int defense_factor = target->query("combat_exp");
        damage-= target->query_temp("apply/armor_vs_force");
        if(damage < 0 ) 
                damage=100;
        while( random(defense_factor) > attacker->query("combat_exp") ) 
                damage -= damage / 3;
        return damage;
}

int do_attack_damage(object me, object victim, object weapon)//调动此函数，相当于直接打中敌人，敌人一样会受到伤害
{
        mapping my, your, action;
        string  result;
        string attack_skill, force_skill, martial_skill;
        mixed foo;
        int damage, damage_bonus, defense_factor;
        
        my = me->query_entire_dbase();
        your = victim->query_entire_dbase();    
        action = me->query("actions");
        damage = me->query_temp("apply/damage");
        damage = (damage + random(damage)) / 2;
        if( action["damage"] )
                damage += action["damage"] * damage / 100;
        damage_bonus = me->query_str();

        if( my["force_factor"] && (my["force"] > my["force_factor"]) ) 
        {
                if( force_skill = me->query_skill_mapped("force") ) 
                {
                        foo = SKILL_D(force_skill)->hit_ob(me, victim, damage_bonus, my["force_factor"]);
                        if( stringp(foo) ) 
                                result += foo;
                        else if( intp(foo) ) 
                                damage_bonus += foo;
                }
        }
        if( action["force"] )
                damage_bonus += action["force"] * damage_bonus / 100;
        if( martial_skill = me->query_skill_mapped(attack_skill) ) 
        {
                foo = SKILL_D(martial_skill)->hit_ob(me, victim, damage_bonus);
                if( stringp(foo) ) result += foo;
                else if(intp(foo) ) damage_bonus += foo;
        }
        if( weapon ) 
        {
                foo = weapon->hit_ob(me, victim, damage_bonus);
                if( stringp(foo) ) result += foo;
                else if(intp(foo) ) damage_bonus += foo;
        } 
        else 
        {
                foo = me->hit_ob(me, victim, damage_bonus);
                if( stringp(foo) ) result += foo;
                else if(intp(foo) ) damage_bonus += foo * 3 / 4;
        }
        if( damage_bonus > 0 )
                damage += (damage_bonus + random(damage_bonus))/2;
        if( damage < 0 ) damage = 0;
        
        defense_factor = your["combat_exp"];
        while( random(defense_factor) > my["combat_exp"] ) 
                damage -= damage / 3;
        damage = victim->receive_damage("kee", damage, me );
        if( (me->is_killing(victim) || weapon)
         && random(damage) > (int)victim->query_temp("apply/armor") ) 
                victim->receive_wound("kee",damage - (int)victim->query_temp("apply/armor"), me);
        return damage;  
}

int querypgwin(object killer,object victim)
{
	if(killer->query("combat_exp")<20000000)
		return 2;
	if(killer->query("combat_exp")>(victim->query("combat_exp")*10))
		return 1;
	if(killer->query("combat_exp")>victim->query("combat_exp"))
		return 2;
	else
		if(killer->query("combat_exp")<victim->query("combat_exp")/2)
			return 4;
		else
			return 2;
	return 2;

}
