far语言写的回合制战斗逻辑
static map skillsConf = ({});
///*实际伤害 = [(攻击方.str + 攻击方.combatExp / 100) * (1 + 攻击方.int / 100)] - (防御方.con / 2)
//
//若 攻击方.dex / 防御方.dex > 随机数(0, 1),则攻击方躲避防御方反击
//若 防御方.dex / 攻击方.dex > 随机数(0, 1),则防御方躲避攻击,实际伤害 = 0*/
static number fight(object me, object victim){
map kEntire = me.entityData();
map vEntire = victim.entityData();
//伤害
number kdmg = ( kEntire["str"] + kEntire["combatExp"] / 100 ) * (1 + kEntire["int"] / 100) ;
println(me.query("name")+" 开始伤害是"+kdmg);
number vDef = vEntire["con"] / 2;
kdmg = kdmg - vDef;
if (randomRange(0,5) < vEntire["dex"] / kEntire["dex"]){
println("没打中");
}else{
vEntire["qi"] -= kdmg;
}
println(fmt("%s 气是 %s",victim.query("name"),vEntire["qi"]));
if( vEntire["qi"] < 1 ){
string msg = fmt("%s 口吐鲜血,一口气上不来死了。",victim.query("name"));
tellObject(me,msg);
println(msg);
me.removeKiller(victim);
victim.die();
//
me.set("pot",me.query("pot")+20);
tellObject(me,fmt("战斗胜利 修为 + %s",20));
return 1;
}
println(fmt("%s(%s) -> %s(%s)",me.query("name"),kEntire["qi"],victim.query("name"),vEntire["qi"]));
}
//获取物理站位的名称
static string posDesc(number posId){
string desc;
if( posId==1 ){
desc="左(后上)";
}else if(posId==2){
desc="左(后中)";
}else if(posId==3){
desc="左(后下)";
}else if(posId==4){
desc="左(前上)";
}else if(posId==5){
desc="左(前中)";
}else if(posId==6){
desc="左(前下)";
}else if(posId==7){
desc="右(前上)";
}else if(posId==8){
desc="右(前中)";
}else if(posId==9){
desc="右(前下)";
}else if(posId==10){
desc="右(后上)";
}else if(posId==11){
desc="右(后中)";
}else if(posId==12){
desc="右(后下)";
}else{
desc="位置数据错误!";
}
return desc;
}
static number getPosOf(number vPosId,map target){
foreach(e in target){
println(e);
}
}
//计算伤害
static number calcDamage(map killer,map buf,number baseDamage){
if( buf["resultType"] > 1){//调整比例
if( buf["refChangeType"]==1 && buf["refTarget"]==1){//增加模式
baseDamage += baseDamage * buf["refChangeVal"];
}
}
if( sizeof(killer["effs"]) > 0 ){
foreach( e in killer["effs"]){
if( e["type"] == "减伤" && e["duration"] > 0){
println(fmt("减伤 %s",baseDamage * e["refChangeVal"]));
baseDamage-= baseDamage * e["refChangeVal"];
}
}
}
return baseDamage;
}
static number rdKill(map killer,map kSkillData,map kBuf, map victim,number currRound,string* combatMessage){
//伤害
number kdmg = ( killer["str"] + killer["combatExp"] / 100 ) * (1 + killer["int"] / 100) ;
// println(killer["name"]+" 开始伤害是"+kdmg);
number vDef = victim["con"] / 2;
kdmg = kdmg - vDef;
number rand = randomRange(0,5);
number dexRate = victim["dex"] / killer["dex"];
var attackSk = killer["skills"]["attack"];
if( !this::skillsConf ){
println("skillConf没有数据啊!");
return 1;
}
map skillData = kSkillData;
//大当家(200/200, 能量:50/50)<左(前下)> 使出 十八摸(抓手)(消耗20能量) 攻击 李阿婆(200/200, 能量:50/50)<右(前上)>
//→ 攻击命中!造成20.52点伤害(25攻-4.48防),附加迟缓(Buf 0,闪避-20%,持续2回合)
// → 大当家能量剩余:30/50
map buf = kBuf;//skillData["bufs"][random(sizeof(skillData["bufs"]))];
map carryEffect = ({});
//恢复类效果的值
number recoverVal;
object kOb = killer["teamLeader"];
object vOb = victim["teamLeader"];
string skName = skillData["name"];
string skBufName = buf["name"];
string kPosDesc = this::posDesc(killer["pPos"]);
string vPosDesc = this::posDesc(victim["pPos"]);
string* kmsg;
// string batMsg1 = fmt("%s(%s)<%s> 使出 %s(%s) 攻击 %s(%s)<%s> ",killer["name"],killer["qi"],kPosDesc, skillData["name"],buf["name"],victim["name"],victim["qi"],vPosDesc);
//[回合N] 大当家(气血:200/200 | 能量:50/50)<左(前下)> 释放技能「十八摸·抓手」(消耗能量20)
string kStr = fmt("[回合%s] %s(气:%s/%s | 能:%s/%s)<%s>",currRound,killer["name"],killer["qi"],killer["maxQi"],killer["neili"],killer["maxNeili"],kPosDesc);
string vStr = fmt(" -> 目标: %s(气:%s/%s | 能:%s/%s)<%s>\n",victim["name"],victim["qi"],victim["maxQi"],victim["neili"],victim["maxNeili"],vPosDesc);
string btMsg="";
string kTitle = fmt("%s(气 %s/%s 能 %s/%s)<%s>",killer["name"],killer["qi"],killer["maxQi"],killer["neili"],killer["maxNeili"],kPosDesc);
string vTitle = fmt("%s(气 %s/%s 能 %s/%s)<%s>",victim["name"],victim["qi"],victim["maxQi"],victim["neili"],victim["maxNeili"],vPosDesc);
string actType;
string skillMsg;
string batMsg;
string effMsg="";
// [回合1] 大当家(气血:200/200 | 能量:50/50)<左(前下)> 释放技能「十八摸·抓手」(消耗能量20)
// → 目标:李阿婆(气血:200/200 | 能量:50/50)<右(前上)>
// → 计算:攻击强度25 - 目标防御4.48 = 基础伤害20.52
// → 结果:命中!造成**20.52点伤害**(气血剩余:**179.48/200**)
// → 附加效果:迟缓(Buf ID:0 | 闪避-20% | 持续2回合)
// → 执行者状态:能量剩余**30/50**
//
//// [回合2] 李阿婆(气血:179.48/200 | 能量:50/50)<右(前上)> 普通攻击 大当家(气血:200/200 | 能量:30/50)<左(前下)>
// → 计算:攻击强度15 - 目标防御8 = 基础伤害7
// → 结果:未命中!(受迟缓影响,闪避+20%)
// → 执行者状态:能量无消耗 **50/50**
//
//// [回合3] 大当家(气血:200/200 | 能量:30/50)<左(前下)> 释放技能「十八摸·锁喉」(消耗能量30)
// → 目标:李阿婆(气血:179.48/200 | 能量:50/50)<右(前上)>
// → 计算:攻击强度30(暴击!×1.2)- 目标防御4.48 = 基础伤害31.52
// → 结果:暴击命中!造成**31.52点伤害**(气血剩余:179.48 - 31.52 = **147.96/200**)
// → 附加效果:流血(每回合损失5%气血,持续3回合)
// → 执行者状态:能量剩余30 - 30 = **0/50**(下一回合无法释放技能)
number hitTrue = 0;
//执行前的能量
number befNeili = killer["neili"];
skillMsg = fmt("使出 %s(%s)",skName,skBufName);
if( buf["type"]=="物理攻击" ){
kdmg = calcDamage(killer,buf,kdmg);
actType = "攻击";
if (rand < dexRate){
batMsg = fmt("但没打中%s",victim["name"]);
btMsg+=fmt(" -> 结果:未命中 原因 %s < %s\n",rand,dexRate);
}else{
hitTrue = 1;
btMsg+=fmt(" -> 结果:命中 造成 %s 点伤害,目标气血剩余 %s - %s =",kdmg,victim["qi"],kdmg);
victim["qi"] -= kdmg;
btMsg+=fmt(" %s\n",victim["qi"]);
//会不会给对方贴上buf?
if( has( buf,"afterEffect") && has(buf["afterEffect"],"effs") && sizeof(buf["afterEffect"]["effs"]) > 0 ){
foreach( e in buf["afterEffect"]["effs"] ){
if( !canSetBuf(victim,e) ) continue;
e["duration"] = e["cycle"];
effMsg+=fmt(" %s 持续%s回合、",e["name"],e["cycle"]);
if( !victim["effs"] ){
victim["effs"] = ([]);
victim["effs"]+=e;
}else{
victim["effs"]+=e;
}
}
}
batMsg = fmt("造成 %s 点伤害。",kdmg);
if( effMsg ){
btMsg+=fmt(" -> 附加效果:%s\n",effMsg);
batMsg+= "还附加了Buf "+effMsg;
}
}
}
else if( buf["type"] == "治疗"){
// var aef = buf["afterEffect"]["bufs"][0];
carryEffect["triggerOdds"] = buf["triggerOdds"];
carryEffect["refChangeVal"] = buf["refChangeVal"];
carryEffect["resultType"] = buf["resultType"];
carryEffect["refTarget"] = buf["refTarget"];
carryEffect["refChangeType"] = buf["refChangeType"];
carryEffect["costNeili"] = buf["costNeili"];
if( buf["resultType"] > 1 && buf["refChangeType"]==1 ){//增加模式
if( carryEffect["refTarget"]==4 ){
recoverVal = victim["maxQi"] * buf["refChangeVal"];
}
}
number costNeili = killer["maxNeili"] * buf["costNeili"] ;
actType = "治疗";
// println( fmt(" 当前内里 %s ,消耗内力 %s ->内里减去 结果 %s",killer["neili"],costNeili,killer["neili"] - costNeili) );
if( killer["neili"] - costNeili > 1 ){
killer["neili"] -= costNeili;
victim["qi"]+=recoverVal;
btMsg+=fmt(" -> 结果:命中 恢复 %s 点气,目标气剩余 %s\n",recoverVal,victim["qi"]);
batMsg = fmt("%s 恢复了 %s 点气血",victim["name"],recoverVal);
}else{
btMsg+=" -> 结果:未命中\n"
batMsg = "结果能量不足!";
}
// println( fmt("能量消耗 %s ,当前能量 %s",costNeili,killer["neili"]) );
//预防超量恢复
if( victim["qi"] > victim["maxQi"] ){
victim["qi"] = victim["maxQi"];
}
}else{
}
btMsg+=fmt(" -> 执行者状态 : 能量 %s - %s = %s",befNeili, befNeili - killer["neili"] ,befNeili - (befNeili - killer["neili"]));
batMsg = fmt( "%s %s %s %s %s", kTitle, skillMsg, actType,vTitle,batMsg );
kStr+=fmt("使出 %s(%s) -> %s\n",skName,skBufName,actType);
println(kStr+vStr+btMsg);
combatMessage+=batMsg;
// if( kOb.query("isUser") ){
//
// kmsg = kOb.query("combatMessage");
// kmsg+= batMsg;
// }
//
// if(vOb.query("isUser") ){
// kmsg = vOb.query("combatMessage");
// kmsg+= batMsg;
// }
if( victim["qi"] < 1 ){
combatMessage+=fmt("%s(%s) 口吐鲜血,一口气上不来死了。",victim["name"],victim["qi"]);
// if( kOb.query("isUser") ){
// kOb.add("combat/reward/pot",20);
// combatMessage+=fmt("%s(%s) 口吐鲜血,一口气上不来死了。",victim["name"],victim["qi"]);
// }
return 1;
}
// println(fmt("%s(%s) -> %s(%s)",killer["name"],killer["qi"],victim["name"],victim["qi"]));
}
//是否能给目标设置Buf
static number canSetBuf(map victim,map buf){
if( victim["effs"] && sizeof( victim["effs"] ) > 0 ){
foreach(e in victim["effs"]){
if( buf["type"]==e["type"] ) return 0;
}
}
return 1;
}
static map* crRound(object k, object v){
//回合唯一ID
k.set("combatMessage",([]));
v.set("combatMessage",([]));
k.set("rGame/skills/attack","100001");
k.set("rGame/skills/defense","100002");
v.set("rGame/skills/attack","100003");
v.set("rGame/skills/defense","100004");
map sk1 = ({
"rGame":({
"skills":({
"attack":"100003"
})
})
});
map sk2 = ({
"rGame":({
"skills":({
"attack":"100002"
})
})
});
// println("技能显示");
// println(sk1["rGame"]["skills"]);
map* que = ([
({
"teamId":k.id(),
"teamLeader":k,
"name":k.query("name"),
"qi":k.query("qi"),
"maxQi":k.query("maxQi"),
"neili":k.query("neili"),
"maxNeili":k.query("maxNeili"),
"str":k.query("str"),
"int":k.query("int"),
"dex":k.query("dex"),
"combatExp":k.query("combatExp"),
"skills":k.query("rGame/skills"),
"con":k.query("con"),
//虚拟站位 玩家vs玩家时 玩家始终在右边 6格
"vPos":1,
//物理站位
"pPos":6
}),
({
"teamId":k.id(),
"teamLeader":k,
"name":"老色鬼",
"qi":100,
"maxQi":100,
"neili":100,
"maxNeili":100,
"str":15,
"int":15,
"dex":15,
"combatExp":0,
"skills":sk1["rGame"]["skills"],
"con":15,
"vPos":4,
//物理站位
"pPos":5
}),
({
"teamId":v.id(),
"teamLeader":v,
"name":v.query("name"),
"qi":v.query("qi"),
"maxQi":v.query("maxQi"),
"neili":v.query("neili"),
"maxNeili":v.query("maxNeili"),
"str":v.query("str"),
"int":v.query("int"),
"dex":v.query("dex"),
"combatExp":v.query("combatExp"),
"skills":v.query("rGame/skills"),
"con":v.query("con"),
"vPos":1,
//物理站位
"pPos":7
}),
({
"teamId":v.id(),
"teamLeader":v,
"name":"赵灵儿",
"qi":100,
"maxQi":100,
"neili":100,
"maxNeili":100,
"str":15,
"int":15,
"dex":15,
"combatExp":0,
"skills":sk2["rGame"]["skills"],
"con":15,
"vPos":5,
//物理站位
"pPos":11
})
]);
return que;
}
//prev 上一回合数据
static map* nextRound(map *prev){
//回合唯一ID
map* nQue = ([]);
foreach(k in prev){
k["haveBeenAttack"]=0;
if( k["qi"] > 0){
nQue+=k;
}
}
return nQue;
}
//获取对手阵营数据
static map* getEnemyLists(map killer,map* que){
map* enemys = ([]);
foreach(e in que){
if( e["teamId"]!=killer["teamId"] && e["qi"] > 0 ){
enemys+=e;
}
}
return enemys;
}
//获取我方成员数据
static map* getAllieLists(map killer,map* que){
map* enemys = ([]);
foreach(e in que){
if( e["teamId"]==killer["teamId"] && e["qi"] > 0 ){
enemys+=e;
}
}
return enemys;
}
//我方或者地方的前排
static map* getFront(map* enemys){
map* enemyLists = ([]);
foreach( e in enemys ){
if( e["vPos"] > 0 && e["vPos"] < 4 ){
enemyLists+=e;
}
}
return enemyLists;
}
//我方或者地方的后排
static map* getBack(map* enemys){
map* enemyLists = ([]);
foreach( e in enemys ){
if( e["vPos"] > 3 && e["vPos"] < 7 ){
enemyLists+=e;
}
}
return enemyLists;
}
static map getSkiData(map killer){
//提取出技能
var attackSk = killer["skills"]["attack"];
if( !this::skillsConf ){
println("skillConf没有数据啊!");
return 1;
}
map skillData = this::skillsConf[attackSk];
if( !skillData ){
println(attackSk+" 没有找到技能文件");
}
return skillData;
}
//从对手集合中随机获取一个对手
static number getEnemyOfRandom(map* enemyQue){
map enemy = enemyQue[ random(sizeof(enemyQue)-1) ];
return enemy;
}
static number selectEnemy(map killer,map* que,number currRound,string* combatMessage){
map sk = getSkiData(killer);
map buf = sk["bufs"][random(sizeof(sk["bufs"]))];
var enemyLists = ([]);
//1我方前排 2我方后排 3我方所有 4我自己(使用技能的人) 5敌方前排 6敌方后排 7敌方所有 8上一次攻击 9相同占位
var emys ;
// if( sizeof(emys) < 1 ) return 3;
if( buf["findDomain"] == 5 ){//技能要求选择敌方前排
emys = getEnemyLists(killer,que);
enemyLists = getFront( emys );
}else if(buf["findDomain"] == 1){//我方前排
emys = getAllieLists(killer,que);
enemyLists = getFront( emys );
}else{
emys = getEnemyLists(killer,que);
}
// if( killer["name"]=="大当家" ){
// println(emys);
// println(enemyLists);
// }
// //对面都没人了...
if( sizeof(emys) < 1 ) return 3;
if( !enemyLists || sizeof(enemyLists) < 1 ) enemyLists+= emys[random(sizeof(emys)-1)];
foreach(kv in enemyLists){
this::rdKill(killer,sk,buf,kv,currRound,combatMessage);
return 1;
}
}
static number getReming(string id,map* que){
number n=0;
foreach( k in que ){
if( k["teamId"]==id ) n++;
}
return n;
}
//每个回合 执行buf
static number evalBufs(map k){
number n = sizeof(k["effs"]);
if( n > 0 ){
// for(number i=0;i < sizeof(k["effs"]);i++ ){
// map e = k["effs"][i];
// if( k["effs"][i]["duration"] > 0 ){
// string s = fmt("%s 有 %s buf 剩余%s",k["name"],k["effs"][i]["type"],k["effs"][i]["duration"]);
// println(s);
// k["effs"][i]["duration"]--;
// }
// }
foreach( e in k["effs"] ){
e["duration"]--;
}
//过滤掉不需要的
k["effs"] = filterArray( k["effs"],(e)->{
return e["duration"] > 0 ;
} );
// println(k["effs"]);
}
return 1;
}
//能量恢复
static number recoverNeli(map *que){
foreach(k in que){
if( k["qi"] < 1 ) continue;
if( k["neili"] < k["maxNeili"] ){
number recoverVal = k["maxNeili"] * 0.02;
k["neili"]+=recoverVal;
}
if( k["neili"] > k["maxNeili"] ){
println(fmt("当前能量 %s 最大能量 %s",k["neili"],k["maxNeili"]));
k["neili"] = k["maxNeili"];
}
}
}
static number roundFight(object me, object victim){
map kEntire = me.entityData();
map vEntire = victim.entityData();
//构建回合制调度器 交替回合制 所有人出手完成 算一回合
//获取第n回合 战斗序列
map* que = this::crRound(me,victim);
//如果是PVP 则是两个玩家
object player = findPlayerObj(que);
//提取队列分组ID
string a1Id = me.id();
string a2Id = victim.id();
string* combatMessage = ([]);
number rounCount = 1;
// for(; sizeof(que) > 1 ;){
for( ;; ){
foreach(k in que){
if( k["qi"] < 1 ) continue;
//是否有buf
evalBufs(k);
selectEnemy(k,que,rounCount,combatMessage);
}
//恢复能量
recoverNeli(que);
rounCount++;
que = nextRound( que );
if( getReming(a1Id,que) < 1 || getReming(a2Id,que) < 1 ) break;
}
println(combatMessage);
//把战斗记录挂载玩家身上
player.set("combatMessage",combatMessage);
println( fmt("%s 回合后 剩下的队伍%s",rounCount,toJsonStr(que)) );
}
static object findPlayerObj(map* que){
foreach( e in que ){
if( e["teamLeader"].query("isUser") ){
return e["teamLeader"];
}
}
return 0;
}
static number testCron(string param){
println("被计划调用咯"+param);
}
Rust编程语言群 1036955113
java新手自学群 626070845
java/springboot/hadoop/JVM 群 4915800
Hadoop/mongodb(搭建/开发/运维)Q群481975850
GOLang Q1群:6848027
GOLang Q2群:450509103
GOLang Q3群:436173132
GOLang Q4群:141984758
GOLang Q5群:215535604
C/C++/QT群 1414577
单片机嵌入式/电子电路入门群群 306312845
MUD/LIB/交流群 391486684
Electron/koa/Nodejs/express 214737701
大前端群vue/js/ts 165150391
操作系统研发群:15375777
汇编/辅助/破解新手群:755783453
大数据 elasticsearch 群 481975850
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
java新手自学群 626070845
java/springboot/hadoop/JVM 群 4915800
Hadoop/mongodb(搭建/开发/运维)Q群481975850
GOLang Q1群:6848027
GOLang Q2群:450509103
GOLang Q3群:436173132
GOLang Q4群:141984758
GOLang Q5群:215535604
C/C++/QT群 1414577
单片机嵌入式/电子电路入门群群 306312845
MUD/LIB/交流群 391486684
Electron/koa/Nodejs/express 214737701
大前端群vue/js/ts 165150391
操作系统研发群:15375777
汇编/辅助/破解新手群:755783453
大数据 elasticsearch 群 481975850
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。