Welcome 微信登录
编程资源 图片资源库 蚂蚁家优选

首页 / 网页编程 / PHP / PHP网页游戏学习之Xnova(ogame)源码解读(十六)

十九、攻击任务(MissionCaseAttack.php)
按照舰队任务的编号,排在第一个的就是攻击任务。这个代码很长,看的时候要有耐心。
好在引用的内容并不是很多,并且给出了详细的注释,读者不会晕头转向。
function MissionCaseAttack ($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("<span style="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; $SetItem 0) {$TargetSet[$SetItem]["count"] = $TargetPlanet[$resource[$SetItem]];}}// 生成攻击方的舰队,也是用数组存放。"fleet_array"是不能直接拿来用的 // 这个字段的结构是编号,数量;编号,数量; …… // 所以使用时需要用两次explode把它打散然后存进数组 $TheFleet = explode(";", $FleetRow["fleet_array"]);foreach($TheFleet as $a => $b) {if ($b != "") {$a = explode(",", $b);$CurrentSet[$a[0]]["count"] = $a[1];}}// 包含进战斗引擎,ready to fightinclude_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 ($CurrentSet as $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($TargetSet as $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 .= "LIMIT 1;";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 .= "LIMIT 1;";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_rw as $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 = "INSERT INTO {{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 .= "WHERE fleet_id = "" . $FleetRow["fleet_id"] . "" ";$QryUpdateFleet .= "LIMIT 1 ;";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 .= "WHERE id = "" . $CurrentUserID . "" ";$QryUpdateOfficier .= "LIMIT 1 ;";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 .= "WHERE id = "" . $CurrentUserID . "" ";$QryUpdateRaidsCompteur .= "LIMIT 1 ;";doquery($QryUpdateRaidsCompteur, "users");} elseif ($FleetResult == "r" || $FleetResult == "w") {$RaidsLoose = $CurrentUser["raidsloose"] + 1;$QryUpdateRaidsCompteur = "UPDATE {{table}} SET ";$QryUpdateRaidsCompteur .= "`raidswin` ="" . $RaidsLoose . "", ";$QryUpdateRaidsCompteur .= "`raids` ="" . $RaidsTotal . "" ";$QryUpdateRaidsCompteur .= "WHERE id = "" . $CurrentUserID . "" ";$QryUpdateRaidsCompteur .= "LIMIT 1 ;";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($fleet as $a => $b) {if ($b != "") {$a = explode(",", $b);$fquery .= "{$resource[$a[0]]}={$resource[$a[0]]} + {$a[1]}, 
";}}}// → 到最后别忘了删除这一条舰队记录,不然会一直占用航道。对其他舰队任务也是一样 doquery ("DELETE FROM {{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"] . " LIMIT 1 ;";doquery($QryUpdatePlanet, "planets");}}}}