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