Monster.php 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789
  1. <?php
  2. /**
  3. * Base monster entity file.
  4. *
  5. * Creates the entity and makes it available.
  6. *
  7. * @author Iñigo Valentin <i@inigovalentin.com>
  8. * @license https://www.gnu.org/licenses/gpl-3.0.en.html GNU General Public License V3
  9. * @package SWDB
  10. */
  11. require_once(PATH::ENTITY . "Entity.php");
  12. require_once(PATH::ENTITY . "Skill.php");
  13. require_once(PATH::ENTITY . "Leader_Skill.php");
  14. require_once(PATH::ENTITY . "Source.php");
  15. require_once(PATH::ENTITY . "Inventory.php");
  16. require_once(PATH::ENTITY . "Monster_Transformation.php");
  17. /**
  18. * A monster.
  19. *
  20. * Represents an object from the table 'monster'.
  21. *
  22. * @category Entity
  23. */
  24. class Monster extends Entity{
  25. /**
  26. * @var int Monster ID
  27. */
  28. private $id;
  29. /**
  30. * @var int Monster family ID.
  31. */
  32. private $family;
  33. /**
  34. * @var string Monster name.
  35. */
  36. private $name;
  37. /**
  38. * @var int Monster element ID ({@see ELEMENT_ID}).
  39. */
  40. private $element;
  41. /**
  42. * @var string Monster element name.
  43. */
  44. private $element_name;
  45. /**
  46. * @var int Monster archetype ID ({@see ARCHETYPE_ID}).
  47. */
  48. private $archetype;
  49. /**
  50. * @var string Monster archetype name.
  51. */
  52. private $archetype_name;
  53. /**
  54. * @var int Stars of the monster in it's current form (1-6)
  55. */
  56. private $base_stars;
  57. /**
  58. * @var int Stars of the monster in it's base form (1-5).
  59. */
  60. private $natural_stars;
  61. /**
  62. * @var bool Indicates if the monster is obtainable.
  63. */
  64. private $obtainable;
  65. /**
  66. * @var bool Indicates if the monster can awaken.
  67. */
  68. private $can_awaken;
  69. /**
  70. * @var string The bonus the monster obtains when awakening.
  71. */
  72. private $awaken_bonus;
  73. /**
  74. * @var int Total skill ups to ma all skills.
  75. */
  76. private $skill_ups_to_max;
  77. /**
  78. * @var int[] Stats of the monster in it's base grade at max level.
  79. */
  80. private $stats = array(
  81. "hp" => 0,
  82. "atk" => 0,
  83. "def" => 0,
  84. "spd" => 0,
  85. "crr" => 0,
  86. "crd" => 0,
  87. "acc" => 0,
  88. "res" => 0,
  89. );
  90. /**
  91. * @var int[] Stats of the monster in it's base grade at level 1.
  92. */
  93. private $min_stats = array(
  94. "hp" => 0,
  95. "atk" => 0,
  96. "def" => 0,
  97. "spd" => 0,
  98. "crr" => 0,
  99. "crd" => 0,
  100. "acc" => 0,
  101. "res" => 0,
  102. );
  103. /**
  104. * @var int[] Stats of the monster at 6 stars and max level.
  105. */
  106. private $max_stats = array(
  107. "hp" => 0,
  108. "atk" => 0,
  109. "def" => 0,
  110. "spd" => 0,
  111. "crr" => 0,
  112. "crd" => 0,
  113. "acc" => 0,
  114. "res" => 0,
  115. );
  116. /**
  117. * @var int ID of the monster this awakens from.
  118. */
  119. private $awakens_from;
  120. /**
  121. * @var int ID of the monster this awakens to.
  122. */
  123. private $awakens_to;
  124. /**
  125. * @var bool Indicates if the monster can be skilled up with fusion monsters.
  126. */
  127. private $fusion_food;
  128. /**
  129. * @var bool Indicates if the monster is an Homunculus.
  130. */
  131. private $homunculus;
  132. /**
  133. * @var mixed[] Crafting cost
  134. * @todo Unimplemented, do not use.
  135. */
  136. private $craft_cost;
  137. /**
  138. * @var bool internal flag to check if the monster skills, including the leader skill, have
  139. * been loaded into the entity.
  140. */
  141. private $flag_skills = false;
  142. /**
  143. * @var Leader_Skill Monster's leader skill.
  144. */
  145. private $leader_skill;
  146. /**
  147. * @var int Leader skill ID.
  148. */
  149. private $leader_skill_id;
  150. /**
  151. * @var Skill[] Monster skills.
  152. */
  153. private $skill = [];
  154. /**
  155. * @var bool Internal flag to check if the essences have been loaded into the entity.
  156. */
  157. private $flag_essences = false;
  158. /**
  159. * @var mixed[] Essences required to awaken the monster.
  160. */
  161. private $essences = [];
  162. /**
  163. * @var bool Internal flag to check if the monster sources have been loaded.
  164. */
  165. private $flag_sources = false;
  166. /**
  167. * @var Source[] List of sources the monster can be obtained from.
  168. */
  169. private $sources = [];
  170. /**
  171. * @var string Monster title.
  172. */
  173. private $title;
  174. /**
  175. * @var bool Internal flag to check if the monsters transformation have been checked.
  176. */
  177. private $flag_transformation = false;
  178. /**
  179. * @var Monster_Transformation The monster this one can transform into in battle.
  180. */
  181. private $transformation;
  182. /**
  183. * Constructor.
  184. *
  185. * Searches the database and retrieves the information about the
  186. * monster, populating it and it's items.
  187. *
  188. * @param int $id Monster identifier.
  189. */
  190. public function __construct($id){
  191. $this->id = $id;
  192. $statement = get_context()->get_db()->prepare("
  193. SELECT
  194. id,
  195. family,
  196. name,
  197. element,
  198. archetype,
  199. base_stars,
  200. natural_stars,
  201. obtainable,
  202. can_awaken,
  203. awaken_bonus,
  204. skill_ups_to_max,
  205. leader_skill,
  206. hp,
  207. attack,
  208. defense,
  209. speed,
  210. crit_rate,
  211. crit_damage,
  212. resistance,
  213. accuracy,
  214. raw_hp,
  215. raw_attack,
  216. raw_defense,
  217. max_lvl_hp,
  218. max_lvl_attack,
  219. max_lvl_defense,
  220. awakens_from,
  221. awakens_to,
  222. fusion_food,
  223. homunculus,
  224. craft_cost
  225. FROM monster
  226. WHERE id = :id;
  227. ");
  228. $statement->bindValue(':id', $id, SQLITE3_TEXT);
  229. $r = $statement->execute()->fetchArray(SQLITE3_ASSOC);
  230. if ($r){
  231. $this->family = $r["family"];
  232. $this->name = HTML::e($r["name"]);
  233. $this->element = $r["element"];
  234. switch($this->element){
  235. case ELEMENT_ID::WATER:
  236. $this->element_name = "Water";
  237. break;
  238. case ELEMENT_ID::FIRE:
  239. $this->element_name = "Fire";
  240. break;
  241. case ELEMENT_ID::WIND:
  242. $this->element_name = "Wind";
  243. break;
  244. case ELEMENT_ID::LIGHT:
  245. $this->element_name = "Light";
  246. break;
  247. case ELEMENT_ID::DARK:
  248. $this->element_name = "Dark";
  249. break;
  250. }
  251. $this->archetype = $r["archetype"];
  252. switch($this->archetype){
  253. case ARCHETYPE_ID::ATTACK:
  254. $this->archetype_name = "Attack";
  255. break;
  256. case ARCHETYPE_ID::DEFENSE:
  257. $this->archetype_name = "Defense";
  258. break;
  259. case ARCHETYPE_ID::HP:
  260. $this->archetype_name = "HP";
  261. break;
  262. case ARCHETYPE_ID::SUPPORT:
  263. $this->archetype_name = "Support";
  264. break;
  265. case ARCHETYPE_ID::MATERIAL:
  266. $this->archetype_name = "Material";
  267. break;
  268. }
  269. $this->base_stars = $r["base_stars"];
  270. $this->natural_stars = $r["natural_stars"];
  271. $this->obtainable = $r["obtainable"];
  272. if ($r["can_awaken"] == 1){
  273. $this->can_awaken = true;
  274. }
  275. else{
  276. $this->can_awaken = false;
  277. }
  278. $this->awaken_bonus = HTML::e($r["awaken_bonus"]);
  279. $this->skill_ups_to_max = $r["skill_ups_to_max"];
  280. if (strlen($r["leader_skill"]) > 0){
  281. $this->leader_skill_id = $r["leader_skill"];
  282. }
  283. $this->stats["hp"] = $r["hp"];
  284. $this->stats["atk"] = $r["attack"];
  285. $this->stats["def"] = $r["defense"];
  286. $this->stats["spd"] = $r["speed"];
  287. $this->stats["crr"] = $r["crit_rate"];
  288. $this->stats["crd"] = $r["crit_damage"];
  289. $this->stats["res"] = $r["resistance"];
  290. $this->stats["acc"] = $r["accuracy"];
  291. $this->min_stats["hp"] = $r["raw_hp"];
  292. $this->min_stats["atk"] = $r["raw_attack"];
  293. $this->min_stats["def"] = $r["raw_defense"];
  294. $this->min_stats["spd"] = $r["speed"];
  295. $this->min_stats["crr"] = $r["crit_rate"];
  296. $this->min_stats["crd"] = $r["crit_damage"];
  297. $this->min_stats["res"] = $r["resistance"];
  298. $this->min_stats["acc"] = $r["accuracy"];
  299. $this->max_stats["hp"] = $r["max_lvl_hp"];
  300. $this->max_stats["atk"] = $r["max_lvl_attack"];
  301. $this->max_stats["def"] = $r["max_lvl_defense"];
  302. $this->max_stats["spd"] = $r["speed"];
  303. $this->max_stats["crr"] = $r["crit_rate"];
  304. $this->max_stats["crd"] = $r["crit_damage"];
  305. $this->max_stats["res"] = $r["resistance"];
  306. $this->max_stats["acc"] = $r["accuracy"];
  307. $this->awakens_from = $r["awakens_from"];
  308. $this->awakens_to = $r["awakens_to"];
  309. if ($r["fusion_food"] == 1){
  310. $this->fusion_food = true;
  311. }
  312. else{
  313. $this->fusion_food = false;
  314. }
  315. if ($r["homunculus"] == 1){
  316. $this->homunculus = true;
  317. }
  318. else{
  319. $this->homunculus = false;
  320. }
  321. $this->craft_cost = $r["craft_cost"];
  322. }
  323. // Guess monster name
  324. if ($this->awakens_from == "" && $this->awakens_to == ""){
  325. // No to, no from. Silver monster.
  326. if ($this->base_stars >= 4){
  327. // SFV Collab event monsters, always awakened.
  328. $this->title = $this->name;
  329. }
  330. elseif($this->archetype == ARCHETYPE_ID::MATERIAL && $this->element == ELEMENT_ID::LIGHT){
  331. // Rainbowmon, always awakened
  332. $this->title = $this->name;
  333. }
  334. elseif($this->archetype == ARCHETYPE_ID::MATERIAL && $this->element == ELEMENT_ID::DARK){
  335. // Devilmon, always unawakened, but dont include element
  336. $this->title = $this->name;
  337. }
  338. else{
  339. // Unawakeable monster
  340. $this->title = $this->element_name . " " . $this->name;
  341. }
  342. }
  343. // Awakened
  344. elseif ($this->awakens_from != ""){
  345. $this->title = $this->name;
  346. }
  347. // Gold
  348. elseif (strlen($this->awakens_to) > 0){
  349. $this->title = $this->element_name . " " . $this->name;
  350. }
  351. }
  352. /**
  353. * Loads the monster skills into the entity.
  354. *
  355. * Must be called only once before trying to get the skills (including the leader one). Sets
  356. * the flag {@link Monster:$flag_skills} to true.
  357. */
  358. private function load_skills(){
  359. $statement = get_context()->get_db()->prepare("
  360. SELECT skill.id AS skill
  361. FROM
  362. skill,
  363. monster_skill
  364. WHERE
  365. skill.id = monster_skill.skill AND
  366. monster_skill.monster = :monster
  367. ORDER BY slot;
  368. ");
  369. $statement->bindValue(':monster', $this->id, SQLITE3_TEXT);
  370. $q = $statement->execute();
  371. while ($r = $q->fetchArray(SQLITE3_ASSOC)){
  372. array_push($this->skill, new Skill($r["skill"]));
  373. }
  374. if ($this->leader_skill_id != null){
  375. $this->leader_skill = new Leader_Skill($this->leader_skill_id);
  376. }
  377. $this->flag_skills = true;
  378. }
  379. /**
  380. * Loads the monster sources into the entity.
  381. *
  382. * Must be called only once before trying to get the sources. Sets the flag
  383. * {@link Monster:$flag_sources} to true.
  384. */
  385. private function load_sources(){
  386. $statement = get_context()->get_db()->prepare("
  387. SELECT source
  388. FROM monster_source
  389. WHERE monster = :monster;
  390. ");
  391. $statement->bindValue(':monster', $this->id, SQLITE3_TEXT);
  392. $q = $statement->execute();
  393. while ($r = $q->fetchArray(SQLITE3_ASSOC)){
  394. array_push($this->sources, new Source($r["source"]));
  395. }
  396. $this->flag_sources = true;
  397. }
  398. /**
  399. * Loads the essences to awaken the monster into the entity.
  400. *
  401. * Must be called only once before trying to get the essences. Sets the flag
  402. * {@link Monster:$flag_essences} to true.
  403. */
  404. private function load_essences(){
  405. $statement = get_context()->get_db()->prepare("
  406. SELECT
  407. item,
  408. amount
  409. FROM monster_essence
  410. WHERE
  411. monster = :monster
  412. ORDER BY item;
  413. ");
  414. $statement->bindValue(':monster', $this->id, SQLITE3_TEXT);
  415. $q = $statement->execute();
  416. while ($r = $q->fetchArray(SQLITE3_ASSOC)){
  417. $e = [
  418. "item" => new Inventory($r["item"], INVENTORY_TYPE_ID::ESSENCES),
  419. "amount" => $r["amount"]
  420. ];
  421. array_push($this->essences, $e);
  422. }
  423. $this->flag_essences = true;
  424. }
  425. /**
  426. * Loads the monster transformation into the entity.
  427. *
  428. * Must be called only once before trying to get the transformation. Sets the flag
  429. * {@link Monster:$flag_transformation} to true.
  430. */
  431. private function load_transformation(){
  432. $statement = get_context()->get_db()->prepare("
  433. SELECT id
  434. FROM monster_transformation
  435. WHERE monster = :monster;
  436. ");
  437. $statement->bindValue(':monster', $this->id, SQLITE3_TEXT);
  438. $r = $statement->execute()->fetchArray(SQLITE3_ASSOC);
  439. if ($r){
  440. $this->transformation = new Monster_Transformation($r["id"]);
  441. }
  442. $this->flag_transformation = true;
  443. }
  444. /**
  445. * Retrieves the monster identifier.
  446. *
  447. * @return string Monster ID
  448. */
  449. public function get_id(){
  450. return $this->id;
  451. }
  452. /**
  453. * Retrieves the monsters family identifier.
  454. *
  455. * @return string Family ID.
  456. */
  457. public function get_family(){
  458. return $this->family;
  459. }
  460. /**
  461. * Retrieves the monster name.
  462. *
  463. * @return string Monster name.
  464. */
  465. public function get_name(){
  466. return $this->name;
  467. }
  468. /**
  469. * Retrieves the monster's element.
  470. *
  471. * @see ELEMENT_ID
  472. *
  473. * @return int Element ID.
  474. */
  475. public function get_element(){
  476. return $this->element;
  477. }
  478. /**
  479. * Retrieves the monster's element name.
  480. *
  481. * @return string Element name.
  482. */
  483. public function get_element_name(){
  484. return $this->element_name;
  485. }
  486. /**
  487. * Retrieves the monster's archetype.
  488. *
  489. * @see ARCHETYPE_ID
  490. *
  491. * @return int Monster's archetype ID.
  492. */
  493. public function get_archetype(){
  494. return $this->archetype;
  495. }
  496. /**
  497. * Retrieves the monster's archetype name.
  498. *
  499. * @return string Archetype name.
  500. */
  501. public function get_archetype_name(){
  502. return $this->archetype_name;
  503. }
  504. /**
  505. * Retrieves the monster's base stars.
  506. * Base stars are the default stars of the monsters in it's current form. I.E awakened
  507. * monsters have always one more base stars than their unawakened forms, and second awaken
  508. * monster always have 6 stars.
  509. *
  510. * @return int Monster base stars (1-6).
  511. */
  512. public function get_base_stars(){
  513. return $this->base_stars;
  514. }
  515. /**
  516. * Retrieves the monster's natural stars.
  517. * Natural stars are the default stars of the monsters in it's unawakened form.
  518. *
  519. * @return int Monster natural stars (1-5).
  520. */
  521. public function get_natural_stars(){
  522. return $this->natural_stars;
  523. }
  524. /**
  525. * Checks if the monster is obtainable.
  526. * Non obtainable monster are usually enemies (boses, towers, pure units...)
  527. *
  528. * @return bool True for obtainable monsters, false for unobtainable.
  529. */
  530. public function is_obtainable(){
  531. return $this->obtainable;
  532. }
  533. /**
  534. * Checks if the monster can be awakened.
  535. * It also includes monsters that can second awaken.
  536. *
  537. * @return bool True if the monster can awaken, false otherwise.
  538. */
  539. public function can_awaken(){
  540. return $this->can_awaken;
  541. }
  542. /**
  543. * Retrieves the awakening bonus description.
  544. * Note that for second awakenings, the bonus always is described as "Secondary Awakening".
  545. * For units that can't awaken, it will return an empty string.
  546. *
  547. * @return string Awaken bonus.
  548. */
  549. public function get_awaken_bonus(){
  550. return $this->awaken_bonus;
  551. }
  552. /**
  553. * Retrieves the number of skill-ups needed to fully skill-up the monster.
  554. *
  555. * @return int Required skill-ups
  556. */
  557. public function get_skill_ups_to_max(){
  558. return $this->skill_ups_to_max;
  559. }
  560. /**
  561. * Retrieves the monster's leader skill.
  562. *
  563. * @return Leader_Skill The leader skill.
  564. */
  565. public function get_leader_skill(){
  566. if (! $this->flag_skills){
  567. $this->load_skills();
  568. }
  569. return $this->leader_skill;
  570. }
  571. /**
  572. * Retrieves the monster stats.
  573. * These stats are the ones for the monster in it's base grade, at max level.
  574. *
  575. * It's an associative array with the following keys:
  576. * atk, def, hp, spd, crr, crd, acc, res
  577. *
  578. * @see get_min_stats()
  579. * @see get_max_stats()
  580. *
  581. * @return int[] Monster stats.
  582. */
  583. public function get_stats(){
  584. return $this->stats;
  585. }
  586. /**
  587. * Retrieves the monster stats.
  588. * These stats are the ones for the monster in it's base grade, at level 1.
  589. *
  590. * It's an associative array with the following keys:
  591. * atk, def, hp, spd, crr, crd, acc, res
  592. *
  593. * @see get_stats()
  594. * @see get_max_stats()
  595. *
  596. * @return int[] Monster stats.
  597. */
  598. public function get_min_stats(){
  599. return $this->min_stats;
  600. }
  601. /**
  602. * Retrieves the monster stats.
  603. * These stats are the ones for the monster with 6 stars at level 40.
  604. *
  605. * It's an associative array with the following keys:
  606. * atk, def, hp, spd, crr, crd, acc, res
  607. *
  608. * @return int[] Monster stats.
  609. *
  610. * @see get_stats()
  611. * @see get_min_stats()
  612. */
  613. public function get_max_stats(){
  614. return $this->max_stats;
  615. }
  616. /**
  617. * Retrieves the identifier of the monster who awakens to this one.
  618. *
  619. * @return string Unawakened monster identifier, null for unawakened monsters.
  620. */
  621. public function get_awakens_from(){
  622. return $this->awakens_from;
  623. }
  624. /**
  625. * Retrieves the identifier of the monster this one awakens to.
  626. *
  627. * @return string Next awaken monster identifier, null for fully awakened monsters.
  628. */
  629. public function get_awakens_to(){
  630. return $this->awakens_to;
  631. }
  632. /**
  633. * Checks if skill-ups can be created by fussion.
  634. *
  635. * @return bool True if skill-us can be fused, false otherwise.
  636. */
  637. public function has_fusion_food(){
  638. return $this->fusion_food;
  639. }
  640. /**
  641. * Checks if the monster is an Homunculus.
  642. *
  643. * @return bool True if Homunculus, false otherwise.
  644. */
  645. public function is_homunculus(){
  646. return $this->homunculus;
  647. }
  648. /**
  649. * // TODO: Unimplemented.
  650. * Retrieves $craft_cost
  651. *
  652. * @return int
  653. */
  654. public function get_craft_cost(){
  655. return $this->craft_cost;
  656. }
  657. /**
  658. * Retrieves the monster skills
  659. *
  660. * @return Skill[] Monster skills.
  661. */
  662. public function get_skills(){
  663. if (! $this->flag_skills){
  664. $this->load_skills();
  665. }
  666. return $this->skill;
  667. }
  668. /**
  669. * Retrieves the essences required to awaken the monster.
  670. *
  671. * @return [[Inventory][int]] Essences required to awaken the monster.s
  672. */
  673. public function get_essences(){
  674. if (! $this->flag_essences){
  675. $this->load_essences();
  676. }
  677. return $this->essences;
  678. }
  679. /**
  680. * Retrieves the sources the monster can be obtained from.
  681. *
  682. * @return Source[] Array of sources.s
  683. */
  684. public function get_sources(){
  685. if (! $this->flag_sources){
  686. $this->load_sources();
  687. }
  688. return $this->sources;
  689. }
  690. /**
  691. * Retrieves the unit's $title
  692. * If awakened, it will be the awakened from name.
  693. * If unawakened, it will be <element> <name>.
  694. *
  695. * @return string Units title.
  696. */
  697. public function get_title(){
  698. return $this->title;
  699. }
  700. /**
  701. * Retrieves the unit this ne can transform to.
  702. *
  703. * @return Monster_Transformation The transformation, null if none.
  704. */
  705. public function get_transformation(){
  706. if (! $this->flag_transformation){
  707. $this->load_transformation();
  708. }
  709. return $this->transformation;
  710. }
  711. /**
  712. * Gets the path to the monster image.
  713. *
  714. * @return string Image URL, or a fixed unknown image.
  715. */
  716. public function get_image(){
  717. return APPLICATION::img("UNIT", $this->id);
  718. }
  719. }