save.lua 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284
  1. --- Generates a control key for savegames.
  2. --
  3. -- It's a random character string, used to differenciate savegames.
  4. generate_control_key = function()
  5. ControlKey = ""
  6. for i = 1, 8 do
  7. ControlKey = ControlKey .. string.char(math.random(97, 97 + 25))
  8. end
  9. end
  10. --- Saves the game.
  11. --
  12. -- @param slot The slot to save at (0-15).
  13. -- @param force If false, exisiting game data will not be overwritten if control keys are different.
  14. save_game = function(slot, force)
  15. savemap_manager:set_control_key(ControlKey)
  16. savemap_manager:set_window_colours(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12) -- TODO Actual data
  17. savemap_manager:set_money(Inventory.money)
  18. savemap_manager:set_game_time(123456) -- TODO Actual data
  19. savemap_manager:set_countdown_time(0) -- TODO Actual data
  20. for i = 1, 50 do
  21. if Inventory.key[i] == true then
  22. savemap_manager:set_key_item(i - 1, true)
  23. end
  24. end
  25. savemap_manager:set_party(Party[1] or -1, Party[2] or -1, Party[3] or -1)
  26. for i = 1, MAX_INVENTORY_SLOTS do
  27. if Inventory[i] ~= nil then
  28. savemap_manager:set_item(i - 1, Inventory[i].item, Inventory[i].quantity)
  29. end
  30. end
  31. for i = 1, MAX_MATERIA_SLOTS do
  32. if Materia[i] ~= nil then
  33. savemap_manager:set_materia(i - 1, Materia[i].id, Materia[i].ap)
  34. if Materia[i].id == Materia.ENEMY_SKILL_ID then
  35. for s = 1, 24 do
  36. if Materia[i].skills[s] == true then
  37. savemap_manager:set_e_skill_materia(i - 1, s, true)
  38. end
  39. end
  40. end
  41. end
  42. end
  43. -- TODO: Materia stash, when implemented.
  44. local player = entity_manager:get_player_entity()
  45. local x, y, z = player:get_position()
  46. savemap_manager:set_location(x, y, z, player:get_move_triangle_id(), player:get_rotation(), System["MapChanger"].current_map_name, System["MapChanger"].location_name) -- TODO Actual data
  47. -- TODO Settings, when implemented
  48. for i = 0, 11 do
  49. if Characters[i] ~= nil and Characters[i].char_id ~= nil then
  50. local c = Characters[i]
  51. savemap_manager:set_character_info(i, c.char_id, c.name, c.enabled, c.locked, c.level, c.kills, c.back_row, c.exp, c.exp_to_next, c.limit.current, c.limit.bar, c.weapon.id, c.armor.id, c.accessory or -1)
  52. savemap_manager:set_character_stat(i, 0, c.stats.str.base, c.stats.str.bonus)
  53. savemap_manager:set_character_stat(i, 1, c.stats.vit.base, c.stats.vit.bonus)
  54. savemap_manager:set_character_stat(i, 2, c.stats.mag.base, c.stats.mag.bonus)
  55. savemap_manager:set_character_stat(i, 3, c.stats.spr.base, c.stats.spr.bonus)
  56. savemap_manager:set_character_stat(i, 4, c.stats.dex.base, c.stats.dex.bonus)
  57. savemap_manager:set_character_stat(i, 5, c.stats.lck.base, c.stats.lck.bonus)
  58. savemap_manager:set_character_stat(i, 6, c.stats.hp.base, c.stats.hp.current)
  59. savemap_manager:set_character_stat(i, 7, c.stats.mp.base, c.stats.mp.current)
  60. for l = 1, 4 do
  61. savemap_manager:set_character_limit_learned(i, l - 1, 0, c.limit.learned[l][1], c.limit.uses[l])
  62. savemap_manager:set_character_limit_learned(i, l - 1, 1, c.limit.learned[l][2], c.limit.uses[l])
  63. end
  64. for m = 0, 8 do
  65. if c.weapon.materia[m] ~= nil then
  66. savemap_manager:set_character_materia(i, true, m, c.weapon.materia[m].id, c.weapon.materia[m].ap)
  67. if c.weapon.materia[m].id == Materia.ENEMY_SKILL_ID then
  68. for s = 1, 24 do
  69. if c.weapon.materia[m].skills[s] == true then
  70. savemap_manager:set_character_e_skill_materie(i, true, m, s, true)
  71. end
  72. end
  73. end
  74. end
  75. if c.armor[m] ~= nil then
  76. savemap_manager:set_character_materia(i, false, m, c.armor.materia[m].id, c.weapon.materia[m].ap)
  77. if c.weapon.materia[m].id == Materia.ENEMY_SKILL_ID then
  78. for s = 1, 24 do
  79. if c.armor.materia[m].skills[s] == true then
  80. savemap_manager:set_character_e_skill_materie(i, true, m, s, true)
  81. end
  82. end
  83. end
  84. end
  85. end
  86. -- TODO: Character statuses
  87. end
  88. end
  89. for b = 0, 14 do
  90. for a = 0, 254 do
  91. if (Banks[b] ~= nil and Banks[b][a] ~= nil and Banks[b][a] ~= 0) then
  92. savemap_manager:set_data(b, a, tonumber(Banks[b][a]))
  93. end
  94. end
  95. end
  96. savemap_manager:save(slot, force or true)
  97. end
  98. --- Laods a game.
  99. --
  100. -- @param slot The slot to load (0-15).
  101. load_game = function(slot)
  102. -- Populate banks
  103. for b = 0, 14 do
  104. for a = 0, 254 do
  105. Banks[b][a] = savemap_manager:get_slot_data(slot, b, a)
  106. end
  107. end
  108. -- TODO: Window colours
  109. Inventory.money = savemap_manager:get_slot_money(slot)
  110. -- TODO: Game time
  111. -- TODO: Countdown
  112. for p = 1, 3 do
  113. Party[p] = savemap_manager:get_slot_party_member(slot, p - 1)
  114. end
  115. for i = 0, MAX_INVENTORY_SLOTS do
  116. Inventory[i] = {item = 0, quantity = 0}
  117. Inventory[i].quantity = savemap_manager:get_slot_item_at_pos_qty(slot, i)
  118. if Inventory[i].quantity > 0 then
  119. Inventory[i].id = savemap_manager:get_slot_item_at_pos_id(slot, i)
  120. else
  121. Inventory[i] = nil
  122. end
  123. end
  124. for i = 0, MAX_MATERIA_SLOTS do
  125. Materia[i] = {id = -1, ap = 0}
  126. Materia[i].id = savemap_manager:get_slot_materia_at_pos_id(slot, i)
  127. if Materia[i].id >= 0 then
  128. Materia[i].ap = savemap_manager:get_slot_materia_at_pos_ap(slot, i)
  129. if Materia[i].id == Materia.ENEMY_SKILL_ID then
  130. Materia[i].ap = 0
  131. Materia[i].skills = {}
  132. for s = 1, 24 do
  133. Materia[i].skills[s] = savemap_manager:is_slot_materia_at_pos_e_skill_learned(slot, i, s - 1)
  134. end
  135. end
  136. else
  137. Materia[i] = nil
  138. end
  139. end
  140. -- TODO: Stash (same as materia)
  141. for i = 0, MAX_KEY_SLOTS do
  142. Inventory.key[i] = savemap_manager:get_slot_key_item(slot, i)
  143. end
  144. -- Characters
  145. for c = 0, 11 do
  146. Characters[c].char_id = savemap_manager:get_slot_character_char_id(slot, c)
  147. if Characters[c].char_id == -1 then
  148. Characters[c] = nil
  149. else
  150. Characters[c] = {}
  151. Characters[c].name = savemap_manager:get_slot_character_name(slot, c)
  152. Characters[c].level = savemap_manager:get_slot_character_level(slot, c)
  153. Characters[c].enabled = savemap_manager:is_slot_character_enabled(slot, c)
  154. Characters[c].locked = savemap_manager:is_slot_character_locked(slot, c)
  155. Characters[c].kills = savemap_manager:get_slot_character_kills(slot, c)
  156. Characters[c].back_row = savemap_manager:is_slot_character_back_row(slot, c)
  157. Characters[c].exp = savemap_manager:get_slot_character_exp(slot, c)
  158. Characters[c].exp_to_next = savemap_manager:get_slot_character_exp_to_next(slot, c)
  159. Characters[c].stats = {}
  160. Characters[c].stats.str = {
  161. base = savemap_manager:get_slot_character_stat_base(slot, c, 0),
  162. bonus = savemap_manager:get_slot_character_stat_extra(slot, c, 0),
  163. total = 0
  164. }
  165. Characters[c].stats.vit = {
  166. base = savemap_manager:get_slot_character_stat_base(slot, c, 1),
  167. bonus = savemap_manager:get_slot_character_stat_extra(slot, c, 1),
  168. total = 0
  169. }
  170. Characters[c].stats.mag = {
  171. base = savemap_manager:get_slot_character_stat_base(slot, c, 2),
  172. bonus = savemap_manager:get_slot_character_stat_extra(slot, c, 2),
  173. total = 0
  174. }
  175. Characters[c].stats.spr = {
  176. base = savemap_manager:get_slot_character_stat_base(slot, c, 3),
  177. bonus = savemap_manager:get_slot_character_stat_extra(slot, c, 3),
  178. total = 0
  179. }
  180. Characters[c].stats.dex = {
  181. base = savemap_manager:get_slot_character_stat_base(slot, c, 4),
  182. bonus = savemap_manager:get_slot_character_stat_extra(slot, c, 4),
  183. total = 0
  184. }
  185. Characters[c].stats.lck = {
  186. base = savemap_manager:get_slot_character_stat_base(slot, c, 5),
  187. bonus = savemap_manager:get_slot_character_stat_extra(slot, c, 5),
  188. total = 0
  189. }
  190. Characters[c].stats.hp = {
  191. current = savemap_manager:get_slot_character_stat_extra(slot, c, 6),
  192. base = savemap_manager:get_slot_character_stat_base(slot, c, 6),
  193. max = 65535
  194. }
  195. Characters[c].stats.mp = {
  196. current = savemap_manager:get_slot_character_stat_extra(slot, c, 7),
  197. base = savemap_manager:get_slot_character_stat_base(slot, c, 7),
  198. max = 65535
  199. }
  200. Characters[c].limit = {}
  201. Characters[c].limit.current = savemap_manager:get_slot_character_limit_level(slot, c)
  202. Characters[c].limit.bar = savemap_manager:get_slot_character_limit_bar(slot, c)
  203. Characters[c].limit.learned = {}
  204. Characters[c].limit.uses = {}
  205. for l = 1, 4 do
  206. Characters[c].limit.learned[l] = {
  207. [1] = savemap_manager:is_slot_character_limit_learned(slot, c, l, 0),
  208. [2] = savemap_manager:is_slot_character_limit_learned(slot, c, l, 1)
  209. }
  210. Characters[c].limit.uses[l] = savemap_manager:get_slot_character_limit_uses(slot, c, l)
  211. end
  212. Characters[c].accessory = savemap_manager:get_slot_character_accessory_id(slot, c)
  213. Characters[c].weapon = {}
  214. Characters[c].armor = {}
  215. Characters[c].weapon.id = savemap_manager:get_slot_character_weapon_id(slot, c)
  216. Characters[c].armor.id = savemap_manager:get_slot_character_armor_id(slot, c)
  217. Characters[c].weapon.materia = {}
  218. Characters[c].armor.materia = {}
  219. for i = 0, 8 do
  220. Characters[c].weapon.materia[i] = {id = -1, ap = 0}
  221. Characters[c].armor.materia[i] = {id = -1, ap = 0}
  222. Characters[c].weapon.materia[i].id = savemap_manager:get_slot_character_materia_id(slot, c, true, i)
  223. Characters[c].armor.materia[i].id = savemap_manager:get_slot_character_materia_id(slot, c, false, i)
  224. if Characters[c].weapon.materia[i].id >= 0 then
  225. Characters[c].weapon.materia[i].ap = savemap_manager:get_slot_character_materia_ap(slot, i, true, i)
  226. if Characters[c].weapon.materia[i].id == Materia.ENEMY_SKILL_ID then
  227. Characters[c].weapon.materia[i].ap = 0
  228. Characters[c].weapon.materia[i].skills = {}
  229. for s = 1, 24 do
  230. Characters[c].weapon.materia[i].skills[s] = savemap_manager:is_slot_character_materia_e_skill_learned(slot, i, c, true, s - 1)
  231. end
  232. end
  233. else
  234. Characters[c].weapon.materia[i] = nil
  235. end
  236. if Characters[c].armor.materia[i].id >= 0 then
  237. Characters[c].armor.materia[i].ap = savemap_manager:get_slot_character_materia_ap(slot, i, false, i)
  238. if Characters[c].armor.materia[i].id == Materia.ENEMY_SKILL_ID then
  239. Characters[c].armor.materia[i].ap = 0
  240. Characters[c].armor.materia[i].skills = {}
  241. for s = 1, 24 do
  242. Characters[c].armor.materia[i].skills[s] = savemap_manager:is_slot_character_materia_e_skill_learned(slot, i, c, false, s - 1)
  243. end
  244. end
  245. else
  246. Characters[c].armor.materia[i] = nil
  247. end
  248. end
  249. -- TODO: Status
  250. Characters[c].status = {}
  251. Characters.recalculate_stats(c)
  252. end
  253. end
  254. -- TODO: Settings
  255. -- TODO: Location
  256. -- TODO: Update character stats
  257. -- TODO: Handle world map when implemented
  258. console("camera_free false")
  259. load_field_map_request(savemap_manager:get_slot_location_field(slot), "")
  260. System["MapChanger"].location_name = savemap_manager:get_slot_location_name(slot)
  261. System["MapChanger"].current_map_name = savemap_manager:get_slot_location_field(slot)
  262. -- TODO: For now, assume the PC is Cloub, but it must be saved.
  263. local player = nil
  264. while player == nil do
  265. entity_manager:set_player_entity("Cloud")
  266. player = entity_manager:get_player_entity()
  267. script:wait(0)
  268. end
  269. --local player = entity_manager:get_entity("Cloud")
  270. if player ~= nil then
  271. player:set_position(savemap_manager:get_slot_location_x(slot), savemap_manager:get_slot_location_y(slot), savemap_manager:get_slot_location_z(slot))
  272. player:set_move_triangle_id(savemap_manager:get_slot_location_triangle(slot))
  273. player:set_rotation(savemap_manager:get_slot_location_angle(slot))
  274. background2d:autoscroll_to_entity(player)
  275. local x, y, z = player:get_position()
  276. end
  277. MenuSettings.pause_available = true
  278. end