十九、攻击任务(MissionCaseAttack.PHP)
按照舰队任务的编号,排在第一个的就是攻击任务。这个代码很长,看的时候要有耐心。 好在引用的内容并不是很多,并且给出了详细的注释,读者不会晕头转向。
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("",$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,true);
// 然后取得双方的科技信息
// 其实下面这两个完全可以与上面两个查询整到一起
$QryTargetTech = "SELECT ";
$QryTargetTech .= "`military_tech`,`defence_tech`,`shield_tech` ";
$QryTargetTech .= "FROM {{table}} ";
$QryTargetTech .= "WHERE ";
$QryTargetTech .= "`id` = '" . $TargetUserID . "';";
$TargetTechno = doquery($QryTargetTech,true);
$QryCurrentTech = "SELECT ";
$QryCurrentTech .= "`military_tech`,`shield_tech` ";
$QryCurrentTech .= "FROM {{table}} ";
$QryCurrentTech .= "WHERE ";
$QryCurrentTech .= "`id` = '" . $CurrentUserID . "';";
$CurrentTechno = doquery($QryCurrentTech,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 fight
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 ($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 . "','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,$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]},\n";
}
}
}
// → 到最后别忘了删除这一条舰队记录,不然会一直占用航道。对其他舰队任务也是一样
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');
}
}
}
}