PageRenderTime 74ms CodeModel.GetById 30ms RepoModel.GetById 1ms app.codeStats 0ms

/php/base/village.inc.php

https://bitbucket.org/obsidian/selador
PHP | 853 lines | 721 code | 69 blank | 63 comment | 42 complexity | 93a4b3661570353997229503801a3914 MD5 | raw file
Possible License(s): AGPL-3.0, LGPL-2.1
  1. <?php
  2. /* village.inc.php - Class representing a village
  3. *
  4. * Copyright (C) 2006-2010 Kevin Read, Simone Schaefer
  5. * Copyright (C) 2010 Markus Bender
  6. *
  7. * This file is part of Selador, a browser-based fantasy strategy game
  8. *
  9. * This program is distributed under the terms of the GNU Affero General Public License.
  10. *
  11. *
  12. * Selador is free software: you can redistribute it and/or modify
  13. * it under the terms of the GNU Affero General Public License as published by
  14. * the Free Software Foundation, either version 3 of the License, or
  15. * any later version.
  16. *
  17. * Selador is distributed in the hope that it will be useful,
  18. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  19. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  20. * GNU Affero General Public License for more details.
  21. *
  22. * You should have received a copy of the GNU Affero General Public License
  23. * along with Selador. If not, see <http://www.gnu.org/licenses/>.
  24. **/
  25. class Village
  26. {
  27. public $name;
  28. public $villageid;
  29. public $uid;
  30. public $x;
  31. public $y;
  32. public $ress_prod = array();
  33. public $ress_max;
  34. public $ress = array();
  35. public $ress_spent = array (0, 0, 0, 0, 0, 0);
  36. public $goldcost;
  37. public $population;
  38. public $secs_yielded = 0;
  39. public $secs_passed;
  40. public $secs_recruited;
  41. public $score_to_add=0;
  42. public $outposts = array();
  43. public $outpost_of = 0;
  44. public $speed_build;
  45. public $speed_research;
  46. public $speed_recruit = array ();
  47. public $recruit_rest;
  48. public $recruiting = array ();
  49. public $owner; // the user object of the village owner - used for logging (shudder)
  50. // These show that the village is under siege:
  51. public $besieged_by;
  52. public $besieged_from;
  53. public $exhaustion_in = 0;
  54. // These show that the village will be under siege soon:
  55. /*
  56. public $soon_siege_in; // The timestamp, when siege will start
  57. public $soon_siege_by; // The UID of the besieger
  58. public $soon_siege_from; // The village id from where the siege comes
  59. */
  60. public $merchants; // Number of merchants that live here
  61. public $expansion_slots; // Number of times we can add ress fields before upgrading bergfried
  62. public $outpost_expansion; // How many new outposts can be founded or overtaken
  63. public $updated; // If the stamp updater has to save this information at the end of computation
  64. public $dirty = true; // If update_to_latest has to re-read village info
  65. public function __construct ($villageInfo, $user)
  66. {
  67. $this->set_info ($villageInfo, $user);
  68. }
  69. function set_info ($villageInfo, $user)
  70. {
  71. $this->villageid = $villageInfo['villageid'];
  72. $this->owner = $user;
  73. $this->uid = $villageInfo['uid'];
  74. $this->name = stripslashes ($villageInfo['name']);
  75. $this->x = $villageInfo['x'];
  76. $this->y = $villageInfo['y'];
  77. $this->outpost_of = $villageInfo['outpost_of'];
  78. $this->ress_max = $villageInfo['resmax'];
  79. $this->ress_prod[1] = $villageInfo['resprod1'];
  80. $this->ress_prod[2] = $villageInfo['resprod2'];
  81. $this->ress_prod[3] = $villageInfo['resprod3'];
  82. $this->ress_prod[4] = $villageInfo['resprod4'];
  83. $this->ress_prod[5] = $villageInfo['resprod5'];
  84. if (isset ($villageInfo['goldcost']))
  85. $this->goldcost = $villageInfo['goldcost'];
  86. $this->speed_build = $villageInfo['buildspeed'];
  87. $this->speed_research = $villageInfo['resspeed'];
  88. $this->speed_recruit[1] = $villageInfo['recrspeed1']; // foot
  89. $this->speed_recruit[2] = $villageInfo['recrspeed2']; // horse
  90. $this->speed_recruit[3] = $villageInfo['recrspeed3']; // bow
  91. $this->speed_recruit[4] = $villageInfo['recrspeed4']; // siege
  92. $this->speed_recruit[5] = $villageInfo['recrspeed5']; // castle
  93. $this->ress[1] = $villageInfo['ress1'];
  94. $this->ress[2] = $villageInfo['ress2'];
  95. $this->ress[3] = $villageInfo['ress3'];
  96. $this->ress[4] = $villageInfo['ress4'];
  97. // $this->population = $villageInfo['population'];
  98. $this->expansion_slots = $villageInfo['expansion'];
  99. $this->outpost_expansion = $villageInfo['out_expansion'];
  100. $this->recruit_rest = $villageInfo['recruit_rest'];
  101. $this->secs_yielded = $this->secs_recruited = $this->secs_passed = $villageInfo['secs_passed'];
  102. $this->merchants = $villageInfo['merchants'];
  103. $this->score = $villageInfo['score'];
  104. if (FINITE_RESSOURCES)
  105. $this->exhaustion_in = -$villageInfo['exhaustion_in'];
  106. /*
  107. if (!$villageInfo['besieged_in'])
  108. {
  109. $this->besieged_by = $villageInfo['besieged_by'];
  110. $this->besieged_from = $villageInfo['besieged_from'];
  111. }
  112. else
  113. {
  114. $this->soon_siege_in = $villageInfo['besieged_in'];
  115. $this->soon_siege_by = $villageInfo['besieged_by'];
  116. $this->soon_siege_from = $villageInfo['besieged_from'];
  117. } */
  118. $this->updated = false;
  119. $this->dirty = false;
  120. $this->ress_spent = array (0, 0, 0, 0, 0, 0);
  121. }
  122. public function update_to_latest ($debug=false, $time=false)
  123. {
  124. global $user_row;
  125. if (!$time)
  126. $time = $user_row['time'];
  127. // Fetch village ressources
  128. if (FINITE_RESSOURCES)
  129. $query = "select *, abs(time_to_sec(timediff(stamp,\"" . $time . "\"))) as secs_passed, time_to_sec(timediff(next_exhaust,now())) as exhaustion_in from village where villageid=".$this->villageid;
  130. else
  131. $query = "select *, abs(time_to_sec(timediff(stamp,\"" . $time . "\"))) as secs_passed from village where villageid=".$this->villageid;
  132. $res = mysql_query ($query);
  133. $stamprow = mysql_fetch_array($res);
  134. $this->secs_yielded = $this->secs_recruited = $this->secs_passed = $stamprow['secs_passed'];
  135. $this->recruit_rest = $stamprow['recruit_rest'];
  136. $this->population = $stamprow['population'];
  137. $this->ress[1] = $stamprow['ress1'];
  138. $this->ress[2] = $stamprow['ress2'];
  139. $this->ress[3] = $stamprow['ress3'];
  140. $this->ress[4] = $stamprow['ress4'];
  141. $this->ress_spent = array (0, 0, 0, 0, 0, 0);
  142. if (isset ($stamprow['goldcost']))
  143. $this->goldcost = $stamprow['goldcost'];
  144. $this->expansion_slots = $stamprow['expansion'];
  145. $this->outpost_expansion = $stamprow['out_expansion'];
  146. $this->besieged_by = $stamprow['besieged_by'];
  147. $this->besieged_from = $stamprow['besieged_from'];
  148. if (FINITE_RESSOURCES)
  149. $this->exhaustion_in = -$stamprow['exhaustion_in'];
  150. $this->updated = false;
  151. $this->dirty = false;
  152. mysql_free_result ($res);
  153. if ($debug)
  154. $this->owner->log_debug ("Own village ".$this->villageid." (".$this->name.") updated to latest. Slept ".$this->secs_passed." seconds, old ress ".$this->ress[1].", ".$this->ress[2].", ".$this->ress[3].", ".$this->ress[4]." - exhaustion in ".$this->exhaustion_in);
  155. }
  156. function update_production ()
  157. {
  158. // Fetch village ressources
  159. $query = "select villageid,resprod1,resprod2,resprod3,resprod4,resprod5,besieged_by,besieged_from, time_to_sec(timediff(next_exhaust,now())) as exhaustion_in from village where villageid in (".$this->villageid;
  160. if (count ($this->outposts))
  161. {
  162. foreach ($this->outposts as $id=>$this_outpost)
  163. $query .= ",".$id;
  164. }
  165. $query .= ")";
  166. $this->ress_prod[1] = $this->ress_prod[2] = $this->ress_prod[3] = $this->ress_prod[4] = $this->ress_prod[5] = 0;
  167. $res = mysql_query ($query);
  168. while ($villageInfo = mysql_fetch_array($res))
  169. {
  170. $factor = 1;
  171. if ($villageInfo['besieged_by'] == 0)
  172. {
  173. $this->ress_prod[1] += (int)($villageInfo['resprod1'] * $factor);
  174. $this->ress_prod[2] += (int)($villageInfo['resprod2'] * $factor);
  175. $this->ress_prod[3] += (int)($villageInfo['resprod3'] * $factor);
  176. $this->ress_prod[4] += (int)($villageInfo['resprod4'] * $factor);
  177. $this->ress_prod[5] += (int)($villageInfo['resprod5'] * $factor);
  178. $this->exhaustion_in = -$villageInfo['exhaustion_in'];
  179. }
  180. }
  181. mysql_free_result ($res);
  182. }
  183. function give_z ()
  184. {
  185. return (($this->y * WORLD_SIZEX) + $this->x);
  186. }
  187. /* Calculate the amount of ressource income and update local copy of ressource vars */
  188. function do_income ($debug=false)
  189. {
  190. $this->do_income_partial (0, $debug);
  191. }
  192. /* Calculate the amount of ressource income and update local copy of ressource vars */
  193. function do_income_partial ($newtime, $debug=false)
  194. {
  195. $newtime = abs ($newtime);
  196. if (FINITE_RESSOURCES)
  197. {
  198. if ($newtime < $this->exhaustion_in)
  199. {
  200. $this->do_income_partial ($this->exhaustion_in);
  201. $this->secs_yielded = abs ($this->exhaustion_in);
  202. $this->owner->CalculateVillageProd ($this->villageid);
  203. // $owner->CalculateVillageProd ($this->villageid);
  204. }
  205. }
  206. $time_passed = $this->secs_yielded - $newtime;
  207. if ($time_passed > 0)
  208. {
  209. $gone = (float)($time_passed)/(float)3600;
  210. // Calculate ressource income. Note that secspassed might have been changed by event handler
  211. $this->ress_spent[1] -= ($this->ress_prod[1] * $gone);
  212. $this->ress_spent[2] -= ($this->ress_prod[2] * $gone);
  213. $this->ress_spent[3] -= ($this->ress_prod[3] * $gone);
  214. $this->ress_spent[4] -= ($this->ress_prod[4] * $gone);
  215. // Cap the ressources at the limit
  216. foreach ($this->ress as $currency=>$amount)
  217. {
  218. if ($amount - $this->ress_spent[$currency] > $this->ress_max)
  219. {
  220. $this->ress_spent[$currency] += $amount - $this->ress_spent[$currency] - $this->ress_max;
  221. $this->owner->log_debug ("C".$currency.": RS ".$this->ress_spent[$currency]." ".$amount." - ".$this->ress_spent[$currency]." - ".$this->ress_max);
  222. }
  223. }
  224. if ($debug)
  225. $this->owner->log_debug ("Own village ".$this->villageid." (".$this->name.") partial income after ".($this->secs_yielded-$newtime)." seconds, yield seconds left ".abs($newtime)." to ".$this->ress[1].", ".$this->ress[2].", ".$this->ress[3].", ".$this->ress[4]);
  226. $this->secs_yielded = abs ($newtime);
  227. $this->updated = true;
  228. }
  229. }
  230. public function spend ($ress1, $ress2, $ress3, $ress4=0)
  231. {
  232. $this->ress_spent[1] += $ress1;
  233. $this->ress_spent[2] += $ress2;
  234. $this->ress_spent[3] += $ress3;
  235. $this->ress_spent[4] += $ress4;
  236. $this->updated = true;
  237. }
  238. public function spend_array ($ress)
  239. {
  240. $this->ress_spent[1] += $ress[1];
  241. $this->ress_spent[2] += $ress[2];
  242. $this->ress_spent[3] += $ress[3];
  243. $this->ress_spent[4] += $ress[4];
  244. $this->updated = true;
  245. }
  246. public function spend_type ($type, $amount)
  247. {
  248. $this->ress_spent[$type] += $amount;
  249. $this->updated = true;
  250. }
  251. public function can_spend ($ress1, $ress2, $ress3, $ress4=0)
  252. {
  253. if (($this->ress[1] - $this->ress_spent[1] >= $ress1) && ($this->ress[2] - $this->ress_spent[2] >= $ress2) && ($this->ress[3] - $this->ress_spent[3] >= $ress3) && ($this->ress[4] - $this->ress_spent[4] >= $ress4))
  254. return (true);
  255. else
  256. return (false);
  257. }
  258. public function can_spend_array ($ress)
  259. {
  260. if (($this->ress[1] - $this->ress_spent[1] >= $ress[1]) && ($this->ress[2] - $this->ress_spent[2] >= $ress[2]) && ($this->ress[3] - $this->ress_spent[3] >= $ress[3]) && ($this->ress[4] - $this->ress_spent[4] >= $ress[4]))
  261. return (true);
  262. else
  263. return (false);
  264. }
  265. public function can_spend_single ($ress1, $ress2, $ress3, $ress4=0)
  266. {
  267. $result = array (1=>false, 2=>false, 3=>false, 4=>false);
  268. if ($this->ress[1] - $this->ress_spent[1] >= $ress1)
  269. $result[1] = true;
  270. if ($this->ress[2] - $this->ress_spent[2] >= $ress2)
  271. $result[2] = true;
  272. if ($this->ress[3] - $this->ress_spent[3] >= $ress3)
  273. $result[3] = true;
  274. if ($this->ress[4] - $this->ress_spent[4] >= $ress4)
  275. $result[4] = true;
  276. return ($result);
  277. }
  278. public function ress_val ($type)
  279. {
  280. return ($this->ress[$type] - $this->ress_spent[$type]);
  281. }
  282. public function can_spend_type ($type, $amount)
  283. {
  284. if ($this->ress[$type] - $this->ress_spent[$type] >= $amount)
  285. return true;
  286. else
  287. return false;
  288. }
  289. /**************************************************************************
  290. Update the timestamp, but note that this was a user action
  291. *************************************************************************/
  292. // Need to think about how to save timestamps. But maybe we don't need to think about that,
  293. // as long as multi-row village updates don't touch indexed columns.
  294. public function update_stamp ($debug=false, $time=false)
  295. {
  296. global $db_locked;
  297. if ($this->updated)
  298. {
  299. $this->update_stamp_nounlock ($debug, "lock", $time);
  300. }
  301. mysql_query ("commit");
  302. $db_locked = false;
  303. }
  304. public function update_stamp_nounlock ($debug=false, $logname="nounlock", $time=false)
  305. {
  306. global $user_row;
  307. global $gamedb;
  308. if (!$time) {
  309. $time = $user_row['time'];
  310. }
  311. if ($this->updated)
  312. {
  313. // Cap the ressources at the limit
  314. foreach ($this->ress as $currency=>$amount)
  315. {
  316. if ($amount - $this->ress_spent[$currency] > $this->ress_max)
  317. {
  318. $this->ress_spent[$currency] += $amount - $this->ress_spent[$currency] - $this->ress_max;
  319. $this->owner->log_debug ("C".$currency.": RS ".$this->ress_spent[$currency]." ".$amount." - ".$this->ress_spent[$currency]." - ".$this->ress_max);
  320. }
  321. }
  322. if ($this->score_to_add > 0)
  323. {
  324. $query = "update village set ress1=ress1-".$this->ress_spent[1].", ress2=ress2-".$this->ress_spent[2].", ress3=ress3-".$this->ress_spent[3].", ress4=ress4-".$this->ress_spent[4].", stamp=\"" . $time . "\", score=score+".$this->score_to_add." where villageid=".$this->villageid;
  325. $this->score_to_add = 0;
  326. }
  327. else
  328. $query = "update village set ress1=ress1-".$this->ress_spent[1].", ress2=ress2-".$this->ress_spent[2].", ress3=ress3-".$this->ress_spent[3].", ress4=ress4-".$this->ress_spent[4].", stamp=\"" . $time . "\" where villageid=".$this->villageid;
  329. if (!$gamedb->query ($query))
  330. $this->owner->log_err ("Couldn't update stamp in ".$logname."!! Query: ".$query.": ".mysql_error());
  331. // if ($debug)
  332. $this->owner->log_debug ("Own village ".$this->villageid." (".$this->name.") ".$logname." update query ".$query);
  333. $this->updated = false;
  334. $this->dirty = true;
  335. }
  336. }
  337. function building_enoughcash ($type, $tolevel, $costfac=1)
  338. {
  339. if (($spend = building_costs ($type, $tolevel)))
  340. {
  341. if ($this->can_spend ($spend[1], $spend[2], $spend[3], $spend[4]))
  342. return (true);
  343. }
  344. return false;
  345. }
  346. function building_build ($type, $tolevel, $costfac=1)
  347. {
  348. global $me; // hmm not very bright var name eh :)
  349. $no_go = false;
  350. if ($spend = building_costs ($type, $tolevel, $costfac))
  351. {
  352. if ($this->building_enoughcash ($type, $tolevel, $costfac))
  353. {
  354. foreach ($this->ress as $ressidx => $thisress)
  355. {
  356. $this->ress[$ressidx] -= $spend[$ressidx];
  357. // $me->score += $spend[$ressidx];
  358. }
  359. return true;
  360. }
  361. else
  362. return false;
  363. }
  364. }
  365. function now_ress ($type)
  366. {
  367. return (min ((int)$this->ress_max, (int)($this->ress[$type] - $this->ress_spent[$type])));
  368. }
  369. /***********************************************************************
  370. Display monetary amounts in a nice way
  371. **********************************************************************/
  372. function display_money ($costs, $dont_display_timer = false)
  373. {
  374. global $tmp_notenough;
  375. $width = 100;
  376. $time_to_wait = 0;
  377. $prod_is_zero = false;
  378. if (isset ($costs[1]))
  379. {
  380. if ($this->now_ress(1) < $costs[1])
  381. {
  382. $retstr = "<span class=\"notenough\"><img src=\"styles/".$_SESSION['theme']."/holz.gif\" width=\"14\">&nbsp;".prettynumber ($costs[1])."</span> ";
  383. $tmp_notenough = true;
  384. if ($this->ress_prod[1] < 1)
  385. {
  386. $prod_is_zero = true;
  387. }
  388. else
  389. {
  390. //calculate how long it will last until we have enough ressources
  391. $time_to_wait = ($costs[1] - ($this->now_ress(1))) / ($this->ress_prod[1] );
  392. //$retstr .= $time_to_wait;
  393. }
  394. }
  395. else
  396. $retstr = "<img src=\"styles/".$_SESSION['theme']."/holz.gif\" width=\"14\">&nbsp;".prettynumber ($costs[1])." ";
  397. }
  398. if (isset ($costs[2]))
  399. {
  400. if ($this->now_ress(2) < $costs[2])
  401. {
  402. $retstr .= "<img src=\"styles/".$_SESSION['theme']."/stein.gif\" width=\"14\"><span class=\"notenough\">&nbsp;".prettynumber ($costs[2])."</span> ";
  403. $tmp_notenough = true;
  404. if ($this->ress_prod[2] < 1)
  405. {
  406. $prod_is_zero = true;
  407. }
  408. else
  409. {
  410. if (($costs[2] - $this->now_ress(2)) / $this->ress_prod[2] > $time_to_wait)
  411. $time_to_wait = ($costs[2] - ($this->now_ress(2))) / ($this->ress_prod[2] );
  412. }
  413. }
  414. else
  415. $retstr .= "<img src=\"styles/".$_SESSION['theme']."/stein.gif\" width=\"14\">&nbsp;".prettynumber ($costs[2])." ";
  416. }
  417. if (isset ($costs[3]))
  418. {
  419. if ($this->now_ress(3) < $costs[3])
  420. {
  421. if ($this->ress_prod[3] < 1)
  422. {
  423. $prod_is_zero = true;
  424. }
  425. else
  426. {
  427. if (($costs[3] - $this->now_ress(3)) / $this->ress_prod[3] > $time_to_wait)
  428. $time_to_wait = ($costs[3] - ($this->now_ress(3))) / ($this->ress_prod[3] );
  429. }
  430. $retstr .= "<img src=\"styles/".$_SESSION['theme']."/eisen.gif\" width=\"14\">&nbsp;<span class=\"notenough\">".prettynumber ($costs[3])."</span> ";
  431. $tmp_notenough = true;
  432. }
  433. else
  434. $retstr .= "<img src=\"styles/".$_SESSION['theme']."/eisen.gif\" width=\"14\">&nbsp;".prettynumber ($costs[3])." ";
  435. }
  436. if (isset ($costs[4]))
  437. {
  438. if ($this->now_ress(4) < $costs[4])
  439. {
  440. if ($this->ress_prod[4] < 1)
  441. {
  442. $prod_is_zero = true;
  443. }
  444. else
  445. {
  446. if (($costs[4] - ($this->now_ress(4))) / $this->ress_prod[4] > $time_to_wait)
  447. $time_to_wait = ($costs[4] - ($this->now_ress(4))) / ($this->ress_prod[4] );
  448. }
  449. $retstr .= "<img src=\"styles/".$_SESSION['theme']."/gold.gif\" width=\"14\">&nbsp;<span class=\"notenough\">".prettynumber ($costs[4])."</span> ";
  450. $tmp_notenough = true;
  451. }
  452. else
  453. $retstr .= "<img src=\"styles/".$_SESSION['theme']."/gold.gif\" width=\"14\">&nbsp;".prettynumber ($costs[4])." ";
  454. }
  455. if ($tmp_notenough && !$dont_display_timer)
  456. {
  457. $hours = floor ($time_to_wait);
  458. $rest = $time_to_wait - $hours;
  459. $minutes = floor ($rest * 60);
  460. $rest2 = ($rest*60) - $minutes;
  461. $seconds = floor ($rest2 * 60);
  462. $minutes += floor ($seconds/60);
  463. $seconds = ($seconds % 60);
  464. if ($hours == 1)
  465. $hour_string = "Stunde";
  466. else
  467. $hour_string = "Stunden";
  468. if ($hours < 10)
  469. $hours = "0".$hours;
  470. if ($minutes < 10)
  471. $minutes = "0".$minutes;
  472. if ($prod_is_zero)
  473. $retstr .= "<span style=\"color:grey\"> (Genug Rohstoffe: <i>nie</i>)</span>";
  474. else
  475. $retstr .= "<span style=\"color:grey\"> (Genug Rohstoffe in ".$hours.":".$minutes." Stunden)</span>";
  476. }
  477. return $retstr;
  478. }
  479. /***********************************************************************
  480. Display monetary amounts in a nice way, each ressource in its own
  481. table cell
  482. **********************************************************************/
  483. function display_money_table ($costs)
  484. {
  485. global $tmp_notenough;
  486. $width = 100;
  487. if ($this->ress[1] - $this->ress_spent[1] < $costs[1])
  488. {
  489. $retstr = "<td><span class=\"notenough\"><img src=\"styles/".$_SESSION['theme']."/holz.gif\" width=\"18\">".prettynumber ($costs[1])."</span></td>";
  490. $tmp_notenough = true;
  491. }
  492. else
  493. $retstr = "<td class=\"none\"><img src=\"styles/".$_SESSION['theme']."/holz.gif\" width=\"18\">".prettynumber ($costs[1])."</td>";
  494. if ($this->ress[2] - $this->ress_spent[2] < $costs[2])
  495. {
  496. $retstr .= "<td class=\"none\"><img src=\"styles/".$_SESSION['theme']."/stein.gif\" width=\"18\"><span class=\"notenough\">".prettynumber ($costs[2])."</span></td>";
  497. $tmp_notenough = true;
  498. }
  499. else
  500. $retstr .= "<td class=\"none\"><img src=\"styles/".$_SESSION['theme']."/stein.gif\" width=\"18\">".prettynumber ($costs[2])."</td>";
  501. if ($this->ress[3] - $this->ress_spent[3] < $costs[3])
  502. {
  503. $retstr .= "<td class=\"none\"><img src=\"styles/".$_SESSION['theme']."/eisen.gif\" width=\"18\"><span class=\"notenough\">".prettynumber ($costs[3])."</span></td>";
  504. $tmp_notenough = true;
  505. }
  506. else
  507. $retstr .= "<td class=\"none\"><img src=\"styles/".$_SESSION['theme']."/eisen.gif\" width=\"18\">".prettynumber ($costs[3])."</td>";
  508. if ($this->ress[4] - $this->ress_spent[4] < $costs[4])
  509. {
  510. $retstr .= "<td><img src=\"styles/".$_SESSION['theme']."/gold.gif\" width=\"18\"><span class=\"notenough\">".prettynumber ($costs[4])."</span></td>";
  511. $tmp_notenough = true;
  512. }
  513. else
  514. $retstr .= "<td ><img src=\"styles/".$_SESSION['theme']."/gold.gif\" width=\"18\">".prettynumber ($costs[4])."</td>";
  515. return $retstr;
  516. }
  517. // Retrieve all armies und troops in a village
  518. function fetch_troops ()
  519. {
  520. $troops = array ();
  521. $query = "select A.troopid, A.uid, A.flag, A.location, B.unitid, B.amount from armies A join troops B on (A.troopid=B.troopid) where location=".$this->villageid." and flag=0";
  522. if (!($res = mysql_query ($query)))
  523. {
  524. $this->owner->log_err ("Cannot read armies and troops for this village. Query: ".$query.", ".mysql_error());
  525. }
  526. else
  527. {
  528. while ($row = mysql_fetch_array ($res))
  529. {
  530. $troops[$row['uid']][$row['unitid']] = $row['amount'];
  531. }
  532. }
  533. return ($troops);
  534. }
  535. // TODO: Zero gui unit arrays, if timelimit != 0
  536. public function recruit_handler (&$gui, &$deleids, $time_remains=0)
  537. {
  538. global $me; // ouch
  539. // global $troops_done;
  540. $score_to_add = 0;
  541. $troops_done = false;
  542. // Iterate over all remaining recruit jobs, because we'll stop after we have hit the time limit
  543. foreach ($this->recruiting as $recrindex=>$evrow)
  544. {
  545. // Stop here if we have already "recruited away" all available time
  546. if (!$troops_done)
  547. {
  548. // timelimit specifies if we should only recruit to a certain point in time
  549. if ($time_remains > 0)
  550. $real_time = -$evrow['dif'] - $time_remains; // FIXME: Can this be true?
  551. else
  552. $real_time = -$evrow['dif'];
  553. // So maybe there is no time left for this recruit job
  554. if ($real_time > 0)
  555. {
  556. // Yes, there is. The upped bound is still the amount of time available for this recruit job
  557. $timediff = min ($evrow['village2'], $real_time);
  558. $this->recruit_rest = (-$evrow['dif'] - $this->secs_recruited) - ((-$evrow['dif'] - $this->secs_recruited) % $evrow['param2']) ;
  559. $this->owner->log_debug ("D".(-$evrow['dif'])." - SR ".$this->secs_recruited."=".(-$evrow['dif'] - $this->secs_recruited)." - MOD (".((-$evrow['dif'] - $this->secs_recruited) % $evrow['param2'])." = ".$this->recruit_rest);
  560. // Subtract the recruit rest from the time that we have now for recruiting
  561. $newtrooptime = $timediff - $this->recruit_rest;
  562. // This directly translates into the amount of units we can recruit
  563. $newtroops = max (0, floor ($newtrooptime / $evrow['param2']));
  564. $this->owner->log_debug ("Recruiting done: ".$newtrooptime." Limit ".$time_remains." (".$timediff." - ".$this->recruit_rest.") final ".$evrow['village2']);
  565. $this->owner->log_debug ("Newtroops: ".$newtroops." (".$newtrooptime." / ".$evrow['param2']." )");
  566. $this->secs_recruited -= $newtrooptime;
  567. if ($real_time > $evrow['village2'])
  568. {
  569. $deleids[] = $evrow['eid'];
  570. $this->owner->log_debug ("Killing event ".$evrow['eid']);
  571. unset ($this->recruiting[$recrindex]);
  572. $this->recruit_rest = 0;
  573. }
  574. else
  575. {
  576. $troops_done = true;
  577. $this->recruit_rest = $timediff - ($timediff % $evrow['param2']);
  578. $timeremaining = $evrow['village2'] + $evrow['dif'];
  579. // Only update unit time if units later in the queue didn't already set a higher wait time
  580. if ($gui)
  581. {
  582. if (isset ($gui->unit_time))
  583. {
  584. if ($gui->unit_time < $timeremaining)
  585. $gui->unit_time = $timeremaining;
  586. }
  587. $gui->unit_first = ceil ($timeremaining / $evrow['param2'])." <img src=\"gfx/u/".$evrow['param'].".gif\" width=\"16\" height=\"16\" border=\"0\" alt=\"".$evrow['param']."\"> in <span title=\"Fertig am ".date ("d.m. H:i:s", time () + $timeremaining)."\" id=\"timer";
  588. $gui->unit_queue_suffix = external_calcdur ($timeremaining)."</span>";
  589. $gui->unit_number += ceil ($timeremaining / $evrow['param2']);
  590. }
  591. }
  592. if ($newtroops > 0)
  593. {
  594. $query = "update troops A, armies B set amount=amount+".$newtroops." where A.troopid=B.troopid and B.villageid=".$evrow['village1']." and B.location=".$evrow['village1']." and B.flag=0 and A.unitid=".$evrow['param'];
  595. $this->owner->log_debug ("Newtroopquery: ".$query);
  596. if (!mysql_query ($query))
  597. {
  598. $this->owner->log_err ("Error while finishing recruitment: ".$query.", ".mysql_error ());
  599. }
  600. $num_aff = mysql_affected_rows ();
  601. if ($num_aff != 1)
  602. {
  603. $this->owner->log_err ("Strange effect while updating troops. Affected rows ".$num_aff.", query: ".$query);
  604. if ($num_aff == 0)
  605. {
  606. $query = "select troopid from armies where villageid=".$evrow['village1']." and location=".$evrow['village1']." and flag=0";
  607. if (!($res = mysql_query ($query)))
  608. $this->owner->log_err ("Cannot fetch army to recruit into when trying recruiting fault recovery. Query: ".$query.", ".mysql_error ());
  609. else
  610. {
  611. if (($row = mysql_fetch_array ($res)))
  612. $troopid = $row['troopid'];
  613. else
  614. {
  615. $query = "insert into armies values (NULL, ".$evrow['village1'].", ".$evrow['uid1'].", 0, ".$evrow['village1'].")";
  616. if (!mysql_query ($query))
  617. $this->owner->log_err ("Cannot insert army to recruit into when trying recruiting fault recovery. Query: ".$query.", ".mysql_error ());
  618. else
  619. {
  620. $troopid = mysql_insert_id ();
  621. $this->owner->log_err ("No army here, dude. We create one: ".$query.", new id is ".$troopid);
  622. }
  623. }
  624. if (isset ($troopid))
  625. {
  626. $query = "insert into troops values (".$troopid.", ".$evrow['param'].", ".$newtroops.")";
  627. $this->owner->log_err ("Also adding this troop entry: ".$query);
  628. if (!mysql_query ($query))
  629. $this->owner->log_err ("Cannot insert troops to recruit into when trying recruiting fault recovery. Query: ".$query.", ".mysql_error ());
  630. }
  631. }
  632. }
  633. }
  634. $this->updated = true;
  635. $query = "insert into eventlog values (".$evrow['eid'].", ".$evrow['uid1'].", ".$evrow['village1'].", ".$evrow['uid2'].", ".$newtroops.", now(), '".$evrow['timestamp']."', ".$evrow['type'].", ".$evrow['param'].", ".$evrow['param2'].", ".$evrow['score'].", 1)";
  636. if (!mysql_query ($query))
  637. $this->owner->log_err ("Cannot update eventlog. Query: ".$query.", ".mysql_error());
  638. $score_to_add += ($evrow['score']*$newtroops);
  639. }
  640. }
  641. }
  642. }
  643. return ($score_to_add);
  644. }
  645. function sum_population ($Gui)
  646. {
  647. $query = "select sum(B.amount) from armies A, troops B where A.villageid=".$this->villageid." and A.troopid=B.troopid and B.unitid<1000";
  648. if (!($res = mysql_query ($query)))
  649. $this->owner->log_err ("Cannot sum population in villages.inc.php. Query: ".$query.", ".mysql_error ());
  650. else
  651. {
  652. if (($row = mysql_fetch_row ($res)))
  653. return ($row[0] + $Gui->unit_number);
  654. else
  655. $this->owner->log_err ("No rows returned in population sum. Query: ".$query.", ".mysql_error ());
  656. }
  657. return ($Gui->unit_number);
  658. }
  659. function update_recrspeed ($which, $evrow)
  660. {
  661. $factor = ConstructionTime ($evrow['param']) * 6;
  662. $this->speed_recruit[$which] = $factor;
  663. $query = "update village set recrspeed".$which."=\"".$factor."\" where villageid=".$evrow['village1'];
  664. // echo $query;
  665. if (!mysql_query ($query))
  666. $this->log_err ("Event recrspeed".$which." update failed: ".$query.": ".mysql_error());
  667. }
  668. function recalculate_upgrade ($outpostid, $num_vill)
  669. {
  670. global $world, $debug;
  671. if (isset ($this->outposts[$outpostid]))
  672. {
  673. // First check how many villages this player already has
  674. $query = "select level from tileres where villageid=".$outpostid;
  675. if (!($res = mysql_query ($query)))
  676. $this->owner->log_err ("WTF, cannot read out tile levels for upgrade outpost->city: ".$query.", ".mysql_error ());
  677. else
  678. {
  679. //$this->owner->log_err ("tileres query ".$query);
  680. // We iterate through all ressource fields and check if they are equal to
  681. // or greater than the necessary level to upgrade this outpost to a village
  682. $enough = true;
  683. $fieldcount = 0;
  684. while (($row = mysql_fetch_row ($res)) && $enough)
  685. {
  686. // echo '<br><br>LEvel: '.$row[0].', num villages: '.$num_vill;
  687. if ($row[0])
  688. {
  689. if ($row[0] < $num_vill * OP_LEVEL_FAC)
  690. {
  691. $enough = false;
  692. break;
  693. }
  694. $fieldcount++;
  695. }
  696. }
  697. $this->owner->log_debug ("O->C: Fieldcount ".$fieldcount.", enough is ".$enough.", num_vill is ".$num_vill);
  698. // If this outpost can be upgraded, we note this change and also flush the outposts info cache
  699. if ($enough && ($fieldcount >= 4))
  700. {
  701. $this->owner->log_debug ("Outpost ".$outpostid." can be upgraded to village!!");
  702. $query = "update village set expansion=1 where villageid=".$outpostid;
  703. if (!mysql_query ($query))
  704. $this->owner->log_err ("Cannot set outpost to upgradeable. Query: ".$query.", ".mysql_error ());
  705. // To flush this info cache, we need the coordinates
  706. $query = "select x, y from village where villageid=".$outpostid;
  707. if (!($res = mysql_query ($query)))
  708. {
  709. $this->owner->log_err ("Cannot fetch coordinates for info flushing when outpost can be upgraded. Query: ".$query.", ".mysql_error ());
  710. }
  711. else
  712. {
  713. if (($row = mysql_fetch_array ($res)))
  714. {
  715. $delz = $row['y'] * $world->sizex + $row['x'];
  716. $path = TILEINFO_PATH.$delz.".php";
  717. @safe_delete ($path);
  718. // $this->log_err ("Cannot delete outpost info cache file after upgrade is possible: ".$path);
  719. }
  720. }
  721. }
  722. }
  723. }
  724. }
  725. }
  726. ?>