PHP网页游戏学习之Xnova(ogame)源码解读(十六)
十九、攻击任务(MissionCaseAttack.php)
按照舰队任务的编号,排在第一个的就是攻击任务。这个代码很长,看的时候要有耐心。
好在引用的内容并不是很多,并且给出了详细的注释,读者不会晕头转向。
functionMissionCaseAttack($FleetRow)
{
global$user,$phpEx,$xnova_root_path,$pricelist,$lang,$resource,$CombatCaps;
//在舰队的记录中,fleet_start_time代表的不是出发时间,而是到达目的地时间
//代表出发时间的是start_time
//此外还有fleet_end_time这个是回到家的时间
//fleet_end_stay这个是结束逗留的时间(联合防御和远征任务会用到)
//所以下面这个判断的意思是“舰队到达了目的地”,而不是“舰队起飞了”
if($FleetRow['fleet_start_time']<=time()){
//fleet_mess是用来记录舰队的状态的,基本可以理解为是在前进途中还是返航途中
//但感觉利用得并不好,如果只有两个状态,可以用true和false来记录
//所以我把它设为了0,1,2三个状态,对于需要停留的任务,停留时就处于第三个状态
if($FleetRow['fleet_mess']==0){
//↓↓这个判断是试探存放战斗数据的文件是否存在
//如果文件不存在,就中断操作,提示联系管理员
if(!isset($CombatCaps[202]['sd'])){
message("<spanstyle="FONT-FAMILY:">".$lang['sys_no_vars']."</span>",$lang['sys_error'],"fleet.".$phpEx,2);
}
//↓↓开始是一系列的数据库查询,取得攻防双方的舰队数量和科技等级
//根据舰队信息取得防守方星球数据
$QryTargetPlanet="SELECT*FROM{{table}}";
$QryTargetPlanet.="WHERE";
$QryTargetPlanet.="`galaxy`='".$FleetRow['fleet_end_galaxy']."'AND";
$QryTargetPlanet.="`system`='".$FleetRow['fleet_end_system']."'AND";
$QryTargetPlanet.="`planet`='".$FleetRow['fleet_end_planet']."'AND";
$QryTargetPlanet.="`planet_type`='".$FleetRow['fleet_end_type']."';";
$TargetPlanet=doquery($QryTargetPlanet,'planets',true);
$TargetUserID=$TargetPlanet['id_owner'];
//根据舰队信息取得攻击方信息
$QryCurrentUser="SELECT*FROM{{table}}";
$QryCurrentUser.="WHERE";
$QryCurrentUser.="`id`='".$FleetRow['fleet_owner']."';";
$CurrentUser=doquery($QryCurrentUser,'users',true);
$CurrentUserID=$CurrentUser['id'];
//由星球数据取得目标星球的所有者的信息
$QryTargetUser="SELECT*FROM{{table}}";
$QryTargetUser.="WHERE";
$QryTargetUser.="`id`='".$TargetUserID."';";
$TargetUser=doquery($QryTargetUser,'users',true);
//然后取得双方的科技信息
//其实下面这两个完全可以与上面两个查询整到一起
$QryTargetTech="SELECT";
$QryTargetTech.="`military_tech`,`defence_tech`,`shield_tech`";
$QryTargetTech.="FROM{{table}}";
$QryTargetTech.="WHERE";
$QryTargetTech.="`id`='".$TargetUserID."';";
$TargetTechno=doquery($QryTargetTech,'users',true);
$QryCurrentTech="SELECT";
$QryCurrentTech.="`military_tech`,`defence_tech`,`shield_tech`";
$QryCurrentTech.="FROM{{table}}";
$QryCurrentTech.="WHERE";
$QryCurrentTech.="`id`='".$CurrentUserID."';";
$CurrentTechno=doquery($QryCurrentTech,'users',true);
//↑↑如果有其他的能影响舰队三围的项目(比如指挥官等),也应该在这里一并取出来
//生成防守方的舰队(防御)
//如果考虑联合防御,在上面还应该把这个星球上联合防御的舰队提取出来
//然后一起计算数量和科技水平
for($SetItem=200;$SetItem0){
$TargetSet[$SetItem]['count']=$TargetPlanet[$resource[$SetItem]];
}
}
//生成攻击方的舰队,也是用数组存放。'fleet_array'是不能直接拿来用的
//这个字段的结构是编号,数量;编号,数量;……
//所以使用时需要用两次explode把它打散然后存进数组
$TheFleet=explode(";",$FleetRow['fleet_array']);
foreach($TheFleetas$a=>$b){
if($b!=''){
$a=explode(",",$b);
$CurrentSet[$a[0]]['count']=$a[1];
}
}
//包含进战斗引擎,readytofight
include_once($xnova_root_path.'includes/ataki.'.$phpEx);
//在输入信息之前采集时间
$mtime=microtime();
$mtime=explode("",$mtime);
$mtime=$mtime[1]+$mtime[0];
$starttime=$mtime;
//将双方舰队和科技输入战斗引擎,并用$walka来记录输出结果
$walka=walka($CurrentSet,$TargetSet,$CurrentTechno,$TargetTechno);
//再采集时间,得到战斗过程所用的时间
//也就是“战斗报告产生于x.xxxxxxxxxx秒”的由来
$mtime=microtime();
$mtime=explode("",$mtime);
$mtime=$mtime[1]+$mtime[0];
$endtime=$mtime;
$totaltime=($endtime-$starttime);
//分别用一个单独的数组来记录攻击方的剩余舰队信息、
$CurrentSet=$walka["atakujacy"];
//……防守方的舰队信息、
$TargetSet=$walka["wrog"];
//……战斗的胜负结果、
$FleetResult=$walka["wygrana"];
//……每一轮的详细情况、
$dane_do_rw=$walka["dane_do_rw"];
//以及双方的损失和废墟情况
$zlom=$walka["zlom"];
//计算攻击方剩下的单位,顺便把装载量也一并计算进去了
$FleetArray="";
$FleetAmount=0;
$FleetStorage=0;
foreach($CurrentSetas$Ship=>$Count){
$FleetStorage+=$pricelist[$Ship]["capacity"]*$Count['count'];
//用$FleetArray记载舰队情况,转换成数据库里字段的格式,准备“入库”
$FleetArray.=$Ship.",".$Count['count'].";";
$FleetAmount+=$Count['count'];
}
$FleetStorage-=$FleetRow["fleet_resource_metal"];
$FleetStorage-=$FleetRow["fleet_resource_crystal"];
$FleetStorage-=$FleetRow["fleet_resource_deuterium"];
//计算防守星球战后的情况
$TargetPlanetUpd="";
if(!is_null($TargetSet)){
foreach($TargetSetas$Ship=>$Count){
$TargetPlanetUpd.="`".$resource[$Ship]."`='".$Count['count']."',";
}
}
//如果战斗结果为攻击方获胜,则开始计算掠夺资源的情况↓↓
//这里可以include进PlanetResourceUpdate.php,在掠夺之前先更新目标星球的资源
$Mining['metal']=0;
$Mining['crystal']=0;
$Mining['deuter']=0;
if($FleetResult=="a"){
if($FleetStorage>0){
$metal=$TargetPlanet['metal']/2;
$crystal=$TargetPlanet['crystal']/2;
$deuter=$TargetPlanet["deuterium"]/2;
if(($metal)>$FleetStorage/3){
$Mining['metal']=$FleetStorage/3;
$FleetStorage=$FleetStorage-$Mining['metal'];
}else{
$Mining['metal']=$metal;
$FleetStorage=$FleetStorage-$Mining['metal'];
}
if(($crystal)>$FleetStorage/2){
$Mining['crystal']=$FleetStorage/2;
$FleetStorage=$FleetStorage-$Mining['crystal'];
}else{
$Mining['crystal']=$crystal;
$FleetStorage=$FleetStorage-$Mining['crystal'];
}
if(($deuter)>$FleetStorage){
$Mining['deuter']=$FleetStorage;
$FleetStorage=$FleetStorage-$Mining['deuter'];
}else{
$Mining['deuter']=$deuter;
$FleetStorage=$FleetStorage-$Mining['deuter'];
}
}
}
//↑↑到这里为止就计算结束了,但如果星球上金属巨多,但晶体和重氢几乎没有
//那就会出现装了1/3仓的金属,剩下2/3仓全都空着
//所以可以考虑自己把掠夺方法完善一下,也不是很难
$Mining['metal']=round($Mining['metal']);
$Mining['crystal']=round($Mining['crystal']);
$Mining['deuter']=round($Mining['deuter']);
//↓↓更新数据库
$QryUpdateTarget="UPDATE{{table}}SET";
$QryUpdateTarget.=$TargetPlanetUpd;
$QryUpdateTarget.="`metal`=`metal`-'".$Mining['metal']."',";
$QryUpdateTarget.="`crystal`=`crystal`-'".$Mining['crystal']."',";
$QryUpdateTarget.="`deuterium`=`deuterium`-'".$Mining['deuter']."'";
$QryUpdateTarget.="WHERE";
$QryUpdateTarget.="`galaxy`='".$FleetRow['fleet_end_galaxy']."'AND";
$QryUpdateTarget.="`system`='".$FleetRow['fleet_end_system']."'AND";
$QryUpdateTarget.="`planet`='".$FleetRow['fleet_end_planet']."'AND";
$QryUpdateTarget.="`planet_type`='".$FleetRow['fleet_end_type']."'";
$QryUpdateTarget.="LIMIT1;";
doquery($QryUpdateTarget,'planets');
$QryUpdateGalaxy="UPDATE{{table}}SET";
$QryUpdateGalaxy.="`metal`=`metal`+'".$zlom['metal']."',";
$QryUpdateGalaxy.="`crystal`=`crystal`+'".$zlom['crystal']."'";
$QryUpdateGalaxy.="WHERE";
$QryUpdateGalaxy.="`galaxy`='".$FleetRow['fleet_end_galaxy']."'AND";
$QryUpdateGalaxy.="`system`='".$FleetRow['fleet_end_system']."'AND";
$QryUpdateGalaxy.="`planet`='".$FleetRow['fleet_end_planet']."'";
$QryUpdateGalaxy.="LIMIT1;";
doquery($QryUpdateGalaxy,'galaxy');
//↓↓计算废墟和损失的情况
$FleetDebris=$zlom['metal']+$zlom['crystal'];
$StrAttackerUnits=sprintf($lang['sys_attacker_lostunits'],pretty_number($zlom["atakujacy"]));
$StrDefenderUnits=sprintf($lang['sys_defender_lostunits'],pretty_number($zlom["wrog"]));
$StrRuins=sprintf($lang['sys_gcdrunits'],pretty_number($zlom["metal"]),$lang['Metal'],pretty_number($zlom['crystal']),$lang['Crystal']);
$DebrisField=$StrAttackerUnits."".$StrDefenderUnits."".$StrRuins;
//↓↓计算产月概率
$MoonChance=$FleetDebris/100000;
if($FleetDebris>2000000){
$MoonChance=20;
}
if($FleetDebris=100000){
$UserChance=mt_rand(1,100);
$ChanceMoon=sprintf($lang['sys_moonproba'],$MoonChance);
}
//如果RP够好,就能产生月亮了。当然前提是这个坐标上没有月亮
if(($UserChance>0)and($UserChance$MoonChance){
……
}
//↓↓从这里开始生成战斗报告,很长,但并不复杂
$AttackDate=date("r",$FleetRow["fleet_start_time"]);
$title=sprintf($lang['sys_attack_title'],$AttackDate);
$raport="".$title."";
$zniszczony=false;
$a_zestrzelona=0;
//↓↓双方攻防信息。如果有其他能影响舰队三围的,也要在这里加进去
//当然这里的数据只是显示在战报中而已,是不会影响岛实际战斗的
$AttackTechon['A']=$CurrentTechno["military_tech"]*10;
$AttackTechon['B']=$CurrentTechno["defence_tech"]*10;
$AttackTechon['C']=$CurrentTechno["shield_tech"]*10;
$AttackerData=sprintf($lang['sys_attack_attacker_pos'],$CurrentUser["username"],$FleetRow['fleet_start_galaxy'],$FleetRow['fleet_start_system'],$FleetRow['fleet_start_planet']);
$AttackerTech=sprintf($lang['sys_attack_techologies'],$AttackTechon['A'],$AttackTechon['B'],$AttackTechon['C']);
$DefendTechon['A']=$TargetTechno["military_tech"]*10;
$DefendTechon['B']=$TargetTechno["defence_tech"]*10;
$DefendTechon['C']=$TargetTechno["shield_tech"]*10;
$DefenderData=sprintf($lang['sys_attack_defender_pos'],$TargetUser["username"],$FleetRow['fleet_end_galaxy'],$FleetRow['fleet_end_system'],$FleetRow['fleet_end_planet']);
$DefenderTech=sprintf($lang['sys_attack_techologies'],$DefendTechon['A'],$DefendTechon['B'],$DefendTechon['C']);
//根据战斗中每一轮的详细情况生成交火的细节,包括每一轮的数量,攻防值,造成和吸收了多少伤害等
//有一些键值可能需要看了战斗引擎才会明白它代表的什么,所以看不懂也没关系↓↓
foreach($dane_do_rwas$a=>$b){
……
}
//↓↓根据胜负结果显示相应的结尾
switch($FleetResult){
……
}
//战斗报告生成于x.xxxxxxxxxxxx秒
$SimMessage=sprintf($lang['sys_rapport_build_time'],$totaltime);
$raport.=$SimMessage."";
//↓↓将战斗报告编码,存入数据库
$dpath=(!$user["dpath"])?DEFAULT_SKINPATH:$user["dpath"];
$rid=md5($raport);
$QryInsertRapport="INSERTINTO{{table}}SET";
$QryInsertRapport.="`time`=UNIX_TIMESTAMP(),";
$QryInsertRapport.="`id_owner1`='".$FleetRow['fleet_owner']."',";
$QryInsertRapport.="`id_owner2`='".$TargetUserID."',";
$QryInsertRapport.="`rid`='".$rid."',";
$QryInsertRapport.="`a_zestrzelona`='".$a_zestrzelona."',";
$QryInsertRapport.="`raport`='".addslashes($raport)."';";
doquery($QryInsertRapport,'rw');
//↓↓这里才是发给玩家的消息,其中有一个onclick的链接到上面的战报
//下面这个是发给攻击方的,根据战斗结果不同,标题也有不同的颜色
$raport="";
$raport.="";
if($FleetResult=="a"){
$raport.="";
}elseif($FleetResult=="r"){
$raport.="";
}elseif($FleetResult=="w"){
$raport.="";
}
$raport.=……
//↓这里突然回到计算攻击舰队的资源装载量,其实完全可以挪到上面去
$Mining['metal']=$Mining['metal']+$FleetRow["fleet_resource_metal"];
$Mining['crystal']=$Mining['crystal']+$FleetRow["fleet_resource_crystal"];
$Mining['deuter']=$Mining['deuter']+$FleetRow["fleet_resource_deuterium"];
//更新舰队信息
$QryUpdateFleet="UPDATE{{table}}SET";
$QryUpdateFleet.="`fleet_amount`='".$FleetAmount."',";
$QryUpdateFleet.="`fleet_array`='".$FleetArray."',";
$QryUpdateFleet.="`fleet_mess`='1',";
$QryUpdateFleet.="`fleet_resource_metal`='".$Mining['metal']."',";
$QryUpdateFleet.="`fleet_resource_crystal`='".$Mining['crystal']."',";
$QryUpdateFleet.="`fleet_resource_deuterium`='".$Mining['deuter']."'";
$QryUpdateFleet.="WHEREfleet_id='".$FleetRow['fleet_id']."'";
$QryUpdateFleet.="LIMIT1;";
doquery($QryUpdateFleet,'fleets');
//发送战斗消息给攻击方
SendSimpleMessage($CurrentUserID,'',$FleetRow['fleet_start_time'],3,$lang['sys_mess_tower'],$lang['sys_mess_attack_report'],$raport);
//↓又突然插进来开始计算战斗经验和战斗次数
//严重怀疑coder写这个文件时是不是喝高了
$AddPoint=$CurrentUser['xpraid']+1;
$QryUpdateOfficier="UPDATE{{table}}SET";
$QryUpdateOfficier.="`xpraid`='".$AddPoint."'";
$QryUpdateOfficier.="WHEREid='".$CurrentUserID."'";
$QryUpdateOfficier.="LIMIT1;";
doquery($QryUpdateOfficier,'users');
$RaidsTotal=$CurrentUser['raids']+1;
if($FleetResult=="a"){
$RaidsWin=$CurrentUser['raidswin']+1;
$QryUpdateRaidsCompteur="UPDATE{{table}}SET";
$QryUpdateRaidsCompteur.="`raidswin`='".$RaidsWin."',";
$QryUpdateRaidsCompteur.="`raids`='".$RaidsTotal."'";
$QryUpdateRaidsCompteur.="WHEREid='".$CurrentUserID."'";
$QryUpdateRaidsCompteur.="LIMIT1;";
doquery($QryUpdateRaidsCompteur,'users');
}elseif($FleetResult=="r"||$FleetResult=="w"){
$RaidsLoose=$CurrentUser['raidsloose']+1;
$QryUpdateRaidsCompteur="UPDATE{{table}}SET";
$QryUpdateRaidsCompteur.="`raidswin`='".$RaidsLoose."',";
$QryUpdateRaidsCompteur.="`raids`='".$RaidsTotal."'";
$QryUpdateRaidsCompteur.="WHEREid='".$CurrentUserID."'";
$QryUpdateRaidsCompteur.="LIMIT1;";
doquery($QryUpdateRaidsCompteur,'users');
}
//↓↓终于又回来了,开始写发给防御方的消息
$raport2="";
$raport2.="";
if($FleetResult=="a"){
$raport2.="";
}elseif($FleetResult=="r"){
$raport2.="";
}elseif($FleetResult=="w"){
$raport2.="";
}
$raport2.=$lang['sys_mess_attack_report']."[".$FleetRow['fleet_end_galaxy'].":".$FleetRow['fleet_end_system'].":".$FleetRow['fleet_end_planet']."]";
SendSimpleMessage($TargetUserID,'',$FleetRow['fleet_start_time'],3,$lang['sys_mess_tower'],$lang['sys_mess_attack_report'],$raport2);
}
//↓↓如果舰队回到出发地了,就开始卸货,然后飞机入库
$fquery="";
if($FleetRow['fleet_end_time']$Count){
$fquery.="`".$resource[$Ship]."`=`".$resource[$Ship]."`+'".$Count['count']."',";
}
}else{
$fleet=explode(";",$FleetRow['fleet_array']);
foreach($fleetas$a=>$b){
if($b!=''){
$a=explode(",",$b);
$fquery.="{$resource[$a[0]]}={$resource[$a[0]]}+{$a[1]},\n";
}
}
}
//→到最后别忘了删除这一条舰队记录,不然会一直占用航道。对其他舰队任务也是一样
doquery("DELETEFROM{{table}}WHERE`fleet_id`=".$FleetRow["fleet_id"],'fleets');
if(!($FleetResult=="w")){
$QryUpdatePlanet="UPDATE{{table}}SET";
$QryUpdatePlanet.=$fquery;
$QryUpdatePlanet.="`metal`=`metal`+".$FleetRow['fleet_resource_metal'].",";
$QryUpdatePlanet.="`crystal`=`crystal`+".$FleetRow['fleet_resource_crystal'].",";
$QryUpdatePlanet.="`deuterium`=`deuterium`+".$FleetRow['fleet_resource_deuterium']."";
$QryUpdatePlanet.="WHERE";
$QryUpdatePlanet.="`galaxy`=".$FleetRow['fleet_start_galaxy']."AND";
$QryUpdatePlanet.="`system`=".$FleetRow['fleet_start_system']."AND";
$QryUpdatePlanet.="`planet`=".$FleetRow['fleet_start_planet']."AND";
$QryUpdatePlanet.="`planet_type`=".$FleetRow['fleet_start_type']."LIMIT1;";
doquery($QryUpdatePlanet,'planets');
}
}
}
}