./store_character.lua

  1. STORE_CHARACTER_MALE_GENDER_NAME 				=	"male" 
  2. STORE_CHARACTER_FEMALE_GENDER_NAME				=	"female" 
  3.  
  4. STORE_CHARACTER_DEFAULT_MALE_FIGURE				=	"athletic" 
  5. STORE_CHARACTER_DEFAULT_FEMALE_FIGURE			=	"athletic" 
  6.  
  7. STORE_CHARACTER_CHEEK_MAKEUP_INDEX		 		= 1 
  8. STORE_CHARACTER__ENTIRE_FACE_MAKEUP_INDEX	 	= 3 
  9.  
  10. local INVALID_STATE						= 0 
  11. local LINEUP_STATE						= 1 
  12. local GALLERY_DOWNLOAD_STATE			= 2 
  13. local CUSTOMIZATION_STATE				= 3 
  14. local GALLERY_FULL_STATE				= 4 
  15. local FINISHED_STATE						= 5 
  16.  
  17. Store_character_current_state = INVALID_STATE 
  18. Store_character_new_state_on_validation = INVALID_STATE 
  19.  
  20. local SCALE_FONT_STORE_CHARACTER_LIST = 0.8 
  21.  
  22. local Online_check_thread = -1 
  23.  
  24. -- Menu Tiers 
  25. local MENU_TIER 			= 1 
  26. local BUILD_TIER 			= 2 
  27. local SKIN_COLOR_TIER	= 3 
  28. local EYE_COLOR_TIER		= 4 
  29. local HAIR_COLOR_TIER	= 5 
  30. local MAKEUP_COLOR_TIER	= 6 
  31. local LINEUP_TIER			= 7 
  32. local Current_tier 		= MENU_TIER 
  33.  
  34. Store_character_doc_handle = -1 
  35.  
  36. -- Used to determine which of three colors player is currently picking, and the index in the color grid is currently chosen. 
  37. local Color_grid_idx			= 1 
  38. local Color_slot_chosen		= 0 
  39.  
  40. Color_grid_data		= {} 
  41.  
  42. local Prev_index = -1 
  43.  
  44. local Input_tracker_body_morph_select = nil 
  45. Hint_bar_mouse_input_tracker = -1 
  46. local Triangle_select_button_handle = -1 
  47. local Triangle_select_text_handle = -1 
  48.  
  49. local Susan_mouse_area_img_h 
  50.  
  51. Store_character_in_anim = -1 
  52. Store_character_out_anim = -1 
  53. Player_creation_bg_anim = -1 
  54. Iad_logo_anim = -1 
  55. Iad_bg_anim = -1 
  56.  
  57. -- Hint bar and store header vdo's. 
  58. local Not_popup_grp = -1 
  59. local Reward_image = -1 
  60. local Triangle_select = -1 
  61.  
  62. Lineup_input_tracker = {} 
  63. Lineup_mouse_input_tracker = {} 
  64.  
  65. Store_character_current_preset_gender = -1 
  66. Store_character_current_preset_race	  = -1 
  67. Store_character_current_preset_figure = -1 
  68.  
  69. --Store_character_rand_func 
  70. Store_character_randomizing_morph_set = -1 
  71.  
  72. Store_character_building_morph_set = -1 
  73.  
  74. -- Save current preset settings in case they are needed for a revert. 
  75. Store_character_preset_previous_settings = -1 
  76.  
  77. Store_character_confirm_randomize = true 
  78.  
  79. MAX_FACIAL_FEATURES = 10 
  80.  
  81. -- variable to help control when player customization is actually ready 
  82. Store_lineup_is_loaded = true 
  83.  
  84. -- Compositing data 
  85. -------------------------------------------- 
  86.  
  87. Store_character_composite_slots = { 
  88. 	["facial hair"] 			= {}, 
  89. 	["eyebrows"] 				= {}, 
  90. 	["body mask"]				= {}, 
  91. 	["makeup eyeliner"]		= {}, 
  92. 	["makeup eyeshadow"]		= {}, 
  93. 	["makeup cheeks"]			= {}, 
  94. 	["lips"]						= {}, 
  95. 	["makeup entire face"]	= {},	 
  96. 	["face items"]				= {},	 
  97. 	["face features"]			= {},		 
  98. 	["fingernails"]			= {},			 
  99. } 
  100.  
  101. -- Composite actions; enum must match C code 
  102.  
  103. COMPOSITE_REPLACE = 0 
  104. COMPOSITE_ADD		= 1 
  105. COMPOSITE_REMOVE	= 2 
  106.  
  107. Store_character_current_composite_area = -1 
  108. Store_character_current_composite_item = -1 
  109. Store_character_current_composite_color = -1 
  110. Store_character_current_composite_alpha = -1 
  111. Store_character_allow_multiple_composites = -1 
  112. Store_character_composites_allowed = -1 
  113. Store_character_composites_used = -1 
  114.  
  115. -------------------------------------------- 
  116.  
  117. CHARACTER_COLOR_POOL_TYPE = 0 
  118.  
  119. HAIR_ITEM_SLOT = 1 
  120.  
  121. Store_character_hair_acc_info = { 
  122. 	colors = { [0] = { }, [1] = { }, [2] = { } } 
  123. } 
  124.  
  125. -- Save off current clothing color index if player cancels change 
  126. local Color_prev_color		= 0 
  127.  
  128. Store_character_hair_values = {} 
  129.  
  130. -- Stores skin color selection when the player started, in case they preview new choices but revert. 
  131. Store_character_skin_color_current_setting = -1 
  132.  
  133. Store_character_skin_color_selected = 0 
  134. Store_character_eye_selected = 0 
  135.  
  136. Store_character_movement_anim_grp = -1 
  137.  
  138. -- Save eye color for reverting 
  139. Store_character_orig_eye_color = -1 
  140.  
  141. -- Save off morph values in case player reverts changes 
  142. Store_character_strength = -1 
  143. Store_character_skinny = -1 
  144. Store_character_fat = -1 
  145.  
  146. Store_character_build_cursor_x = -1 
  147. Store_character_build_cursor_y = -1 
  148.  
  149. Store_character_nav_thread = -1 
  150. local Store_character_nav_value = nil 
  151.  
  152. Store_character_preset_update_thread 	= -1 
  153. local Store_character_preset_update_data		= nil 
  154.  
  155. Store_character_preset_new_gender = -1 
  156.  
  157. Store_character_init_camera_moved = false 
  158.  
  159. Store_character_anim_done = true 
  160.  
  161. Store_character_original_anim_id = -1 
  162.  
  163. -- Do we need to display a popup to confirm if the player should cancel? 
  164. Store_character_cancel_confirm_needed = false 
  165.  
  166. -- Save off preset info while waiting for a confirmation of setting it. 
  167. Store_character_tentative_preset_data = -1 
  168.  
  169. local Game_platform = -1 
  170.  
  171. -- Global referencse to the "lazy susan" vdo for the character lineup.  Needed for VDO callbacks. 
  172. Susan_object = -1 
  173.  
  174. -- Number of images in the character lineup 
  175. STORE_CHARACTER_NUM_LINEUP_IMAGES        = 9 
  176. STORE_CHARACTER_NUM_LINEUP_IMAGES_LOADED = 5 
  177.  
  178. -- Table of character lineup preset settings 
  179. Store_character_lineup_presets = { 
  180. 	{ gender = "male",     race = "white",      figure = "athletic" }, 
  181. 	{ gender = "female",   race = "white",      figure = "athletic" }, 
  182. 	{ gender = "male",     race = "black",      figure = "athletic" }, 
  183. 	{ gender = "female",   race = "black",      figure = "athletic" }, 
  184. 	{ gender = "male",     race = "hispanic",   figure = "athletic" }, 
  185. 	{ gender = "female",   race = "hispanic",   figure = "athletic" }, 
  186. 	{ gender = "male",     race = "asian",      figure = "athletic" }, 
  187. 	{ gender = "female",   race = "asian",      figure = "athletic" }, 
  188. } 
  189.  
  190. -- Flag to indicate if we've finished loading/animating in the character lineup. 
  191. Store_character_lineup_init_complete = false 
  192.  
  193. local Store_character_clothing_load_thread = -1 
  194. local Store_character_clothes_on_current = true 
  195. local Store_character_clothes_on_pending = true 
  196.  
  197.  
  198. function store_character_fail_msg(event) 
  199. 	Store_common_popup:nav_enable(false, nil, nil) 
  200. 	game_UI_audio_play("UI_Main_Menu_Select") 
  201. 	Not_popup_grp:set_alpha(1) 
  202. 	Active_list:set_visible(true) 
  203. 	store_character_enable_mouse(true) 
  204. end 
  205.  
  206. -- Player creation utility functions 
  207. -------------------------------------------- 
  208.  
  209. function store_character_change_clothes() 
  210. 	while true do 
  211. 		delay(0.1) 
  212. 		if pcu_is_streaming_done() then 
  213. 			-- Must wait at least a frame for handshake after streaming is done 
  214. 			delay(0.2) 
  215. 			if Store_character_clothes_on_current ~= Store_character_clothes_on_pending then 
  216. 				if Store_character_clothes_on_pending then 
  217. 					pcr_restore_clothing() 
  218. 				else 
  219. 					pcr_strip_clothing() 
  220. 				end 
  221. 				 
  222. 				Store_character_clothes_on_current = Store_character_clothes_on_pending 
  223. 			end 
  224. 		end 
  225. 	end 
  226. end 
  227.  
  228. -- This function is used to strip the clothes off the player when they enter submenus from the character creation screen. 
  229. -- 
  230. function store_character_creation_strip_clothes() 
  231. 	if pcr_is_plastic_surgeon() == false then 
  232. 		if Store_character_clothing_load_thread == -1 then 
  233. 			Store_character_clothing_load_thread = thread_new("store_character_change_clothes") 
  234. 		end 
  235. 		Store_character_clothes_on_pending = false 
  236. 	end 
  237. end 
  238.  
  239. -- This function is used to return the clothes on the player when they enter the top menu of the character creation screen. 
  240. -- 
  241. function store_character_creation_add_clothes() 
  242. 	if pcr_is_plastic_surgeon() == false then 
  243. 		if Store_character_clothing_load_thread == -1 then 
  244. 			Store_character_clothing_load_thread = thread_new("store_character_change_clothes") 
  245. 		end 
  246. 		Store_character_clothes_on_pending = true 
  247. 	end 
  248. end 
  249.  
  250. -- Compositing functions --- Possibly move to store_common so tatoos can use them???? 
  251. -------------------------------------------- 
  252.  
  253. -- Save current info on one composite slot 
  254. -- 
  255. function store_character_composite_save_info(slot_name) 
  256.  
  257. 	slot_name = slot_name or Store_character_current_composite_area 
  258.  
  259. 	local index, color, alpha = pcr_get_composite_info(slot_name) 
  260. 	Store_character_composite_slots[slot_name].index = index 
  261. 	Store_character_composite_slots[slot_name].color = color 
  262. 	Store_character_composite_slots[slot_name].alpha = alpha 
  263. end 
  264.  
  265. -- Restore to saved info on one composite slot 
  266. -- 
  267. function store_character_composite_restore_info(slot_name) 
  268.  
  269. 	-- kill update thread if it's still around 
  270. 	if Store_character_nav_thread ~= -1 then 
  271. 		thread_kill(Store_character_nav_thread) 
  272. 		Store_character_nav_thread = -1 
  273. 	end 
  274.  
  275. 	slot_name = slot_name or Store_character_current_composite_area 
  276.  
  277. 	local values = Store_character_composite_slots[slot_name] 
  278. 	pcr_change_composite(slot_name, values.index, values.color, values.alpha) 
  279. end 
  280.  
  281. -- Build a menu based on compositing choices 
  282. -- 
  283. function store_character_composite_menu_build(menu_data) 
  284.  
  285. 	Store_character_current_composite_area = menu_data.composite_area 
  286. 	 
  287. 	-- save off current settings 
  288. 	store_character_composite_save_info() 
  289. 	 
  290. 	-- Get the colors for the palette. 
  291. 	-- We need to do this now, because we need to find and save off the current composite the player has in case they revert. 
  292. 	Color_grid_data = {} 
  293. 	Color_grid_idx = 1 
  294. 	pcr_report_composite_colors(Store_character_current_composite_area, true, "store_character_composite_add_color")		 
  295. 	 
  296. 	-- Initialize the current settings 
  297. 	local values = Store_character_composite_slots[Store_character_current_composite_area] 
  298. 	Store_character_current_composite_item = values.index 
  299. 	Store_character_current_composite_color = values.color 
  300. 	Store_character_current_composite_alpha = values.alpha 
  301. 	 
  302. 	if menu_data.max_selections ~= nil and menu_data.max_selections > 1 then 
  303. 		Store_character_allow_multiple_composites = true 
  304. 		Store_character_composites_used = 0 
  305. 		Store_character_composites_allowed = menu_data.max_selections 
  306. 	else 
  307. 		Store_character_allow_multiple_composites = false	 
  308. 	end 
  309. 		 
  310. 	-- Special case: body mask or menus with multiple selections don't have a "none" choice 
  311. 	if menu_data.composite_area ~= "body mask" and Store_character_allow_multiple_composites == false then 
  312. 		local item = { 
  313. 			label = "CUST_ITEM_NOTHING", type = TYPE_BUTTON, composite_item = -1, on_nav = store_character_composite_item_nav, 
  314. 			on_select = store_character_composite_item_set, on_cancel = store_character_composite_item_revert 
  315. 		}	 
  316. 	 
  317. 		local menu_idx = #Store_common_sub_menu + 1 
  318. 		Store_common_sub_menu[menu_idx] = item 
  319. 	end 
  320. 	 
  321. 	pcr_report_composite_items(Store_character_current_composite_area, "store_character_composite_item_add") 
  322. end 
  323.  
  324. function store_character_composite_color_grid_show(menu_data) 
  325. 	Active_list:set_visible(false) 
  326. 	 
  327. 	Current_tier = MAKEUP_COLOR_TIER 
  328. 	store_character_enable_mouse(false, false) 
  329. 	 
  330. 	-- display the grid 
  331. 	--input_data, current_option, max_width, max_height, button_w, button_h, hint_button_offset, current_category, outline_scale, background_enabled, show_current_button, grid_padding, set_size 
  332. 	Store_common_color_grid:draw_items(Color_grid_data, Color_grid_idx, 9, 7, 53.5, 53.5, 15, nil, 1.1, true, true, -7, true) 
  333. 	Store_common_color_grid:set_visible(true) 
  334. 	Store_common_color_grid:nav_enable(true, "store_character_composite_color_select", "store_character_composite_color_grid_nav")	 
  335. 	Color_grid_data.alpha_select = menu_data.alpha_select 
  336. end 
  337.  
  338. function store_character_composite_color_grid_nav(event, value) 
  339. 	store_character_grid_nav(event, value) 
  340. 	 
  341. 	-- set the color and preview the item 
  342. 	local idx = Store_common_color_grid:return_selected_index() 
  343. 	Store_character_current_composite_color = Color_grid_data[idx].index 
  344. 	 
  345. 	if Store_character_nav_thread ~= -1 then 
  346. 		thread_kill(Store_character_nav_thread) 
  347. 		Store_character_nav_thread = -1 
  348. 	end 
  349. 	 
  350. 	Store_character_nav_thread = thread_new("store_character_composite_item_delayed_set")	 
  351. end 
  352.  
  353. function store_character_composite_add_color(color_index, label_crc, label_str, red, green, blue, max_colors, is_current) 
  354. 	local grid_idx = #Color_grid_data + 1 
  355. 	 
  356. 	Color_grid_data[grid_idx] = { 
  357. 		icon = "ui_menu_veh_pnt_base", 
  358. 		label = label_str, 
  359. 		label_crc = label_crc, 
  360. 		color = {red = red, green = green, blue = blue}, 
  361. 		index = color_index, 
  362. 	} 
  363. 	 
  364. 	if is_current == true then 
  365. 		Color_grid_idx = grid_idx 
  366. 		Store_character_current_composite_color = Color_grid_data[grid_idx].index 
  367. 	end 
  368. end 
  369.  
  370. function store_character_composite_alpha_done() 
  371. 	game_UI_audio_play("UI_Main_Menu_Select") 
  372. 	store_character_composite_save_info() 
  373. 	store_common_back_menu() 
  374. 	store_common_back_menu()	 
  375. end 
  376.  
  377. function store_character_composite_alpha_revert() 
  378. 	game_UI_audio_play("UI_Main_Menu_Nav_Back") 
  379. end 
  380.  
  381. function store_character_composite_alpha_change(menu_data) 
  382. 	Store_character_current_composite_alpha = menu_data.current_value 
  383. 	store_character_composite_update() 
  384. end 
  385.  
  386. function store_character_composite_show_alpha_menu() 
  387. 	Active_list:set_visible(true) 
  388. 	 
  389. 	-- Get data to populate the megalist 
  390. 	local New_menu_data = { 
  391. 		{ label = "CUST_OPACITY_SLIDER", type = TYPE_SLIDER, on_select = store_character_composite_alpha_done, on_cancel =  store_character_composite_alpha_revert,  
  392. 		  on_value_update = store_character_composite_alpha_change, min = 0, max = 1, step = 0.05, current_value = Store_character_current_composite_alpha },	 
  393. 	} 
  394. 	 
  395. 	store_common_push_menu(New_menu_data) 
  396. end 
  397.  
  398. function store_character_composite_color_select(event) 
  399.  
  400. 	Store_common_color_grid:nav_enable(false, nil, nil) 
  401. 	Store_common_color_grid:cleanup() 
  402. 	Store_common_color_grid:set_visible(false) 
  403. 	Active_list:set_visible(true) 
  404. 	 
  405. 	Current_tier = MENU_TIER 
  406. 	store_character_enable_mouse(true, false) 
  407.  
  408. 	-- Did the player select a color? 
  409. 	if event == "select" or event == "mouse_click" then 
  410. 		game_UI_audio_play("UI_Main_Menu_Select") 
  411. 		if Color_grid_data.alpha_select then 
  412. 			store_character_composite_show_alpha_menu() 
  413. 		else 
  414. 			store_character_composite_save_info() 
  415. 			store_common_back_menu() 
  416. 			Color_grid_data = {} 
  417. 		end 
  418. 	else 
  419. 		game_UI_audio_play("UI_Main_Menu_Nav_Back") 
  420. 	end 
  421. end 
  422.  
  423. function store_character_composite_item_set(menu_data) 
  424.  
  425. 	-- Toggle selection if multiple selections allowed 
  426. 	if Store_character_allow_multiple_composites then 
  427. 		Store_character_current_composite_item = menu_data.composite_item		 
  428. 		if menu_data.equipped then 
  429. 			store_character_composite_update(COMPOSITE_REMOVE) 
  430. 		else	 
  431. 			-- Have we hit the maximum number? 
  432. 			if Store_character_composites_used >= Store_character_composites_allowed then 
  433. 				Store_common_popup:populate_list(Ok_choice, 1, STORE_COMMON_LIST_SIZE, 1) 
  434. 				Store_common_popup:set_title("MENU_TITLE_NOTICE") 
  435. 				Store_common_popup:set_text("CUST_MAX_COMPOSITE_WARNING")		 
  436. 				Store_common_popup:nav_enable(true, "store_character_fail_msg", "store_character_popup_nav") 
  437. 				Not_popup_grp:set_alpha(.5)	 
  438. 				Active_list:set_visible(false) 
  439. 				store_character_enable_mouse(false) 
  440. 				return			 
  441. 			else 
  442. 				store_character_composite_update(COMPOSITE_ADD) 
  443. 			end 
  444. 		end 
  445. 		 
  446. 		-- refresh the menu 
  447. 		local index = Active_list:get_selection() 
  448. 		Store_character_composites_used = 0 
  449. 		Store_common_sub_menu = {} 
  450. 		pcr_report_composite_items(Store_character_current_composite_area, "store_character_composite_item_add")		 
  451. 		Menu_data = Store_common_sub_menu 
  452. 		Store_common_sub_menu = {} 
  453. 		 
  454. 		--Rather than reupdate the list we will only reupdate a single item (JMH 9/20/2011) 
  455. 		--store_character_populate_list(Menu_data, index) 
  456. 		Active_list.data = Menu_data 
  457. 		Active_list:refresh_single_item(index) 
  458. 		if Mouse_input_tracker ~= 0 then 
  459. 			Mouse_input_tracker:remove_all() 
  460. 			Active_list:add_mouse_inputs("store_common", Mouse_input_tracker) 
  461. 			Mouse_input_tracker:subscribe(true) 
  462. 		end 
  463. 		 
  464. 		return 
  465. 	end 
  466.  
  467. 	Store_character_current_composite_item = menu_data.composite_item 
  468. 	 
  469. 	if menu_data.composite_item ~= -1 then 
  470. 		-- only some things do we choose color for 
  471. 		if menu_data.colorized then 
  472. 			store_character_composite_color_grid_show(menu_data) 
  473. 		else 
  474. 			if menu_data.alpha_select then 
  475. 				store_character_composite_show_alpha_menu() 
  476. 			else 
  477. 				store_character_composite_save_info() 
  478. 				store_common_back_menu() 
  479. 			end 
  480. 		end 
  481. 	else 
  482. 		store_common_back_menu() 
  483. 	end 
  484. end 
  485.  
  486. -- Player reverted and didn't make a composite change.  Revert previewed composite back to what it was. 
  487. -- 
  488. function store_character_composite_item_revert() 
  489.  
  490. 	-- Don't revert for multiple selections allowed 
  491. 	if Store_character_allow_multiple_composites then 
  492. 		return 
  493. 	end 
  494.  
  495. 	store_character_composite_restore_info() 
  496. end 
  497.  
  498. function store_character_composite_update(optional_action) 
  499.  
  500. 	optional_action = optional_action or COMPOSITE_REPLACE 
  501.  
  502. 	pcr_change_composite(Store_character_current_composite_area, Store_character_current_composite_item, Store_character_current_composite_color, Store_character_current_composite_alpha, optional_action) 
  503.  
  504. 	Store_character_confirm_randomize = true 
  505. end 
  506.  
  507. function store_character_composite_item_delayed_set() 
  508. 	delay(0.4) 
  509. 	store_character_composite_update() 
  510. 	Store_character_nav_thread = -1 
  511. end 
  512.  
  513. function store_character_composite_item_nav(menu_data) 
  514.  
  515. 	-- Don't preview for multiple selections allowed 
  516. 	if Store_character_allow_multiple_composites then 
  517. 		return 
  518. 	end 
  519.  
  520. 	if Store_character_nav_thread ~= -1 then 
  521. 		thread_kill(Store_character_nav_thread) 
  522. 		Store_character_nav_thread = -1 
  523. 	end 
  524. 	 
  525. 	Store_character_current_composite_item = menu_data.composite_item 
  526. 	 
  527. 	-- reset alpha to 1 
  528. 	Store_character_current_composite_alpha = 1 
  529. 	Store_character_nav_thread = thread_new("store_character_composite_item_delayed_set") 
  530. end 
  531.  
  532. function store_character_composite_item_add(composite_index, name_crc, name_str, current, colorized, alpha_select, unused_price, unused_respect) 
  533. 	local item = { 
  534. 		type = TYPE_BUTTON, composite_item = composite_index, label = name_str, label_crc = name_crc, on_nav = store_character_composite_item_nav,  
  535. 		on_select = store_character_composite_item_set, on_cancel = store_character_composite_item_revert, colorized = colorized, alpha_select = alpha_select, 
  536. 	} 
  537.  
  538. 	if Store_character_allow_multiple_composites then 
  539. 		item.equipped = current	 
  540. 		if current then 
  541. 			Store_character_composites_used = Store_character_composites_used + 1 
  542. 		end 
  543. 	end 
  544. 	 
  545. 	local menu_idx = #Store_common_sub_menu + 1 
  546. 	 
  547. 	if current == true then 
  548. 		Store_common_sub_menu.start_index = menu_idx 
  549. 	end 
  550.  
  551. 	Store_common_sub_menu[menu_idx] = item 
  552. end 
  553.  
  554.  
  555.  
  556. -- Preset menus 
  557. -------------------------------------------- 
  558.  
  559. function store_character_preset_enter_main(menu_data) 
  560.  
  561. 	-- Get initial preset values 
  562. 	Store_character_current_preset_gender, Store_character_current_preset_race, Store_character_current_preset_figure = pcr_get_player_preset() 
  563.  
  564. 	if Store_character_preset_update_thread == -1 then 
  565. 		Store_character_preset_update_thread = thread_new("store_character_preset_update_thread") 
  566. 	end 
  567. end 
  568.  
  569. function store_character_preset_cleanup(menu_data) 
  570.  
  571. 	Store_character_preset_update_data = nil 
  572. 	 
  573. 	if Store_character_preset_update_thread ~= -1 then 
  574. 		thread_kill(Store_character_preset_update_thread) 
  575. 		Store_character_preset_update_thread = -1 
  576. 	end 
  577.  
  578. end 
  579.  
  580. function store_character_preset_update_thread() 
  581. 	while true do 
  582.  
  583. 		delay(0.5) 
  584. 		 
  585. 		local update_data = Store_character_preset_update_data 
  586. 		 
  587. 		Store_character_preset_update_data = nil 
  588. 		 
  589. 		if update_data ~= nil then 
  590. 			store_character_apply_preset(update_data) 
  591. 		end 
  592. 		 
  593. 		if Store_character_preset_update_thread == -1 then 
  594. 			break 
  595. 		end 
  596. 	end 
  597. end 
  598.  
  599. -- Player chose a preset - update the character 
  600. -- 
  601. function store_character_preset_nav(menu_data) 
  602. 	Store_character_preset_update_data = menu_data 
  603. end 
  604.  
  605. function store_character_apply_preset(menu_data) 
  606. 	local update_preset = false 
  607. 	local update_regional_preset = false 
  608. 	 
  609. 	-- Age preset updating is handled differently.  So check if this is an age update, and 
  610. 	-- if so, just do that and return. 
  611. 	-- 
  612. 	if menu_data.preset_age ~= nil then 
  613. 		pcr_apply_morph_value("global body", "old", menu_data.preset_age) 
  614. 		pcr_mark_changed() 
  615. 		return 
  616. 	end 
  617. 	 
  618. 	if menu_data.preset_gender ~= nil and menu_data.preset_gender ~= Store_character_current_preset_gender then 
  619. 	 
  620. 		Store_character_preset_new_gender = menu_data.preset_gender 
  621. 	 
  622. 		Store_character_current_preset_gender = menu_data.preset_gender 
  623. 		update_preset = true 
  624. 		if Store_character_current_preset_gender == STORE_CHARACTER_FEMALE_GENDER_NAME then 
  625. 			Store_character_current_preset_figure = STORE_CHARACTER_DEFAULT_FEMALE_FIGURE 
  626. 		else 
  627. 			Store_character_current_preset_figure = STORE_CHARACTER_DEFAULT_MALE_FIGURE 
  628. 		end 
  629. 	end 
  630. 	 
  631. 	if menu_data.preset_race ~= nil and menu_data.preset_race ~= Store_character_current_preset_race then 
  632. 		Store_character_current_preset_race = menu_data.preset_race 
  633. 		update_preset = true 
  634. 	end 
  635. 	 
  636. 	if menu_data.preset_figure ~= nil and menu_data.preset_figure ~= Store_character_current_preset_figure then 
  637. 		Store_character_current_preset_figure = menu_data.preset_figure 
  638. 		update_regional_preset = true; 
  639. 	end 
  640. 		 
  641. 	if update_preset == true then 
  642. 		local preset_name = Store_character_current_preset_gender .. "_" .. Store_character_current_preset_race 
  643. 		local regional_preset_name = Store_character_current_preset_gender .. "_" .. Store_character_current_preset_figure; 
  644. 		pcr_apply_preset(preset_name, "figure", regional_preset_name, true) 
  645. 		pcr_set_triangle_cursor_pos(-1, -1) 
  646. 		pcr_mark_changed() 
  647. 		Store_character_confirm_randomize = true 
  648. 	else 
  649. 		if update_regional_preset == true then 
  650. 			pcr_apply_regional_preset("figure", Store_character_current_preset_gender .. "_" .. Store_character_current_preset_figure) 
  651. 			pcr_set_triangle_cursor_pos(-1, -1)			 
  652. 			pcr_mark_changed() 
  653. 			Store_character_confirm_randomize = true 
  654. 		end 
  655. 	end 
  656. end 
  657.  
  658. -- Player selected a preset with the "select" button.  We need to confirm if they really want to do this first. 
  659. -- 
  660. function store_character_select_preset(menu_data) 
  661.  
  662. 	store_character_enable_mouse(false) 
  663.  
  664. 	Store_common_popup:populate_list(Yes_no_choices, 2, STORE_COMMON_LIST_SIZE, 2)	 
  665. 	Store_common_popup:set_title("MENU_TITLE_WARNING") 
  666. 	Store_common_popup:set_text("PRESET_WARNING_BODY")		 
  667. 	Store_common_popup:nav_enable(true, "store_character_select_preset_final", "store_character_popup_nav") 
  668. 	Not_popup_grp:set_alpha(.5) 
  669. 	Active_list:set_visible(false)	 
  670. 	 
  671. 	Store_character_tentative_preset_data = menu_data 
  672. 	 
  673. 	return true 
  674. end 
  675.  
  676. function store_character_select_preset_final(event) 
  677. 	Store_common_popup:nav_enable(false, nil, nil) 
  678. 	Not_popup_grp:set_alpha(1) 
  679. 	Active_list:set_visible(true) 
  680. 	 
  681. 	-- The user hit the B button and cancelled the change 
  682. 	-- This is redundant to selecting "No" in the list 
  683. 	if event == "back" then 
  684. 		game_UI_audio_play("UI_Main_Menu_Nav_Back") 
  685. 		store_character_enable_mouse(true) 
  686. 		return 
  687. 	end 
  688. 	 
  689. 	game_UI_audio_play("UI_Main_Menu_Select")	 
  690. 	 
  691. 	-- Did we select yes?  This assumes yes is the first item 
  692. 	if Store_common_popup:get_selected_data() ~= 1 then 
  693. 		store_character_enable_mouse(true) 
  694. 		return 
  695. 	end 
  696.  
  697. 	-- Change to the preset 
  698. 	store_character_apply_preset(Store_character_tentative_preset_data) 
  699. 	store_common_back_menu() 
  700. end 
  701.  
  702. -- Player cancelled a preset with the "back" button. 
  703. -- 
  704. function store_character_revert_preset(menu_data) 
  705. 	-- Pass in an previous saved setting to do a revert. 
  706. 	Store_character_preset_update_data = nil 
  707. 	 
  708. 	-- do a revert if we had previous settings 
  709. 	if Store_character_preset_previous_settings ~= nil then 
  710. 		store_character_apply_preset(Store_character_preset_previous_settings) 
  711. 	end 
  712. end 
  713.  
  714. -- Save the current figure setting in case we need to revert. 
  715. -- 
  716. function store_character_preset_save_figure(menu_data) 
  717. 	Store_character_current_preset_gender, Store_character_current_preset_race, Store_character_current_preset_figure = pcr_get_player_preset() 
  718. 	local data = { preset_figure = Store_character_current_preset_figure } 
  719. 	Store_character_preset_previous_settings = data 
  720. end 
  721.  
  722. -- Save the current race setting in case we need to revert. 
  723. -- 
  724. function store_character_preset_save_race(menu_data) 
  725. 	Store_character_current_preset_gender, Store_character_current_preset_race, Store_character_current_preset_figure = pcr_get_player_preset() 
  726. 	local data = { preset_race = Store_character_current_preset_race } 
  727. 	Store_character_preset_previous_settings = data 
  728. end 
  729.  
  730. -- Save the current age setting in case we need to revert. 
  731. -- 
  732. function store_character_preset_save_age(menu_data) 
  733. 	local data = { preset_age = pcr_get_morph_value("Global Body", "old") } 
  734. 	Store_character_preset_previous_settings = data 
  735. end 
  736.  
  737. function store_character_preset_sex_fill(menu_data) 
  738.  
  739. 	local store_character_presets_sex = { 
  740. 		{ label = "PLAYER_CREATION_PRESET_MALE", name = "male", type = TYPE_BUTTON, on_select = store_character_select_preset, on_cancel = store_character_revert_preset, preset_gender = "male" }, 
  741. 		{ label = "PLAYER_CREATION_PRESET_FEMALE", name = "female", type = TYPE_BUTTON, on_select = store_character_select_preset, on_cancel = store_character_revert_preset, preset_gender = "female" }, 
  742. 	} 
  743.  
  744. 	store_character_preset_save_race(menu_data) 
  745. 	Store_common_sub_menu = store_character_presets_sex 
  746. 	for i = 1, #Store_common_sub_menu do 
  747. 		if Store_common_sub_menu[i].name == Store_character_current_preset_gender then 
  748. 			Store_common_sub_menu.start_index = i 
  749. 		end 
  750. 	end 
  751. end 
  752.  
  753.  
  754. function store_character_preset_race_fill(menu_data) 
  755.  
  756. 	local store_character_presets_race = {	 
  757. 		{ label = "RACE_AFRICAN", name = "black", type = TYPE_BUTTON, on_select = store_character_select_preset, on_cancel = store_character_revert_preset, on_nav = store_character_preset_nav, preset_race = "black" }, 
  758. 		{ label = "RACE_ASIAN", name = "asian", type = TYPE_BUTTON, on_select = store_character_select_preset, on_cancel = store_character_revert_preset, on_nav = store_character_preset_nav, preset_race = "asian" }, 
  759. 		{ label = "RACE_CAUCASIAN", name = "white", type = TYPE_BUTTON, on_select = store_character_select_preset, on_cancel = store_character_revert_preset, on_nav = store_character_preset_nav, preset_race = "white" }, 
  760. 		{ label = "RACE_HISPANIC", name = "hispanic", type = TYPE_BUTTON, on_select = store_character_select_preset, on_cancel = store_character_revert_preset, on_nav = store_character_preset_nav, preset_race = "hispanic" }, 
  761. 	} 
  762.  
  763. 	store_character_preset_save_race(menu_data) 
  764. 	Store_common_sub_menu = store_character_presets_race 
  765. 	for i = 1, #Store_common_sub_menu do 
  766. 		if Store_common_sub_menu[i].name == Store_character_current_preset_race then 
  767. 			Store_common_sub_menu.start_index = i 
  768. 		end 
  769. 	end 
  770. end 
  771.  
  772. -- Body menus 
  773. -------------------------------------------- 
  774.  
  775. -- Input constants 
  776. RAW_INPUT_DEAD_ZONE				= 0.1 
  777. LEFT_STICK_PIXELS_PER_FRAME	= 4 
  778.  
  779. Left_stick_current_input_x 	= 0 
  780. Left_stick_current_input_y 	= 0 
  781. Left_stick_input_thread 				= -1 
  782.  
  783. Mouse_x = -1 
  784. Mouse_y = -1 
  785.  
  786. -- Helper function to adjust the raw input based on dead zone and pixel speed 
  787. local function input_from_stick_value_and_speed(value, speed) 
  788. 	if value > RAW_INPUT_DEAD_ZONE then 
  789. 		return (value - RAW_INPUT_DEAD_ZONE) / (1 - RAW_INPUT_DEAD_ZONE) * LEFT_STICK_PIXELS_PER_FRAME 
  790. 	elseif value < -RAW_INPUT_DEAD_ZONE then 
  791. 		return (value + RAW_INPUT_DEAD_ZONE) / (1 - RAW_INPUT_DEAD_ZONE) * LEFT_STICK_PIXELS_PER_FRAME 
  792. 	else 
  793. 		return 0 
  794. 	end 
  795. end 
  796.  
  797. function store_character_move_left_x(event, value) 
  798. 	Left_stick_current_input_x = input_from_stick_value_and_speed(value, LEFT_STICK_PIXELS_PER_FRAME) 
  799. end 
  800.  
  801. function store_character_move_left_y(event, value) 
  802. 	Left_stick_current_input_y = input_from_stick_value_and_speed(value, LEFT_STICK_PIXELS_PER_FRAME) 
  803. end 
  804.  
  805. function store_character_move_left_stick_thread() 
  806. 	local loop_count = 0 
  807. 	local update_needed = false 
  808. 	local new_str, new_skin, new_fat, new_x, new_y 
  809. 	 
  810. 	while true do 
  811. 		if Left_stick_current_input_x ~= 0 or Left_stick_current_input_y ~= 0 then 
  812. 			if Store_common_popup:get_property("visible") ~= true then 
  813. 				local str, skin, fat, x, y = Triangle_select:move_left_stick(Left_stick_current_input_x, Left_stick_current_input_y)	 
  814. 				if str ~= nil then 
  815. 					new_str = str 
  816. 					new_skin = skin 
  817. 					new_fat = fat 
  818. 					new_x = x 
  819. 					new_y = y 
  820. 					update_needed = true 
  821. 				end 
  822. 			end 
  823. 		elseif Mouse_x ~= -1 and Mouse_y ~= -1 then 
  824. 			local str, skin, fat, x, y = Triangle_select:update_mouse(Mouse_x, Mouse_y) 
  825. 			if str ~= nil then 
  826. 				new_str = str 
  827. 				new_skin = skin 
  828. 				new_fat = fat 
  829. 				new_x = x 
  830. 				new_y = y				 
  831. 				update_needed = true 
  832. 			end 
  833. 			 
  834. 			-- Reset mouse values for the mouse event handlers to set in next frame 
  835. 			Mouse_x = -1 
  836. 			Mouse_y = -1 
  837. 		end 
  838. 		 
  839. 		debug_print("vint", "Thread Running... \n") 
  840. 		delay(1/20) -- Peg to 20 frames/sec 
  841. 		 
  842. 		-- only update the character's body at most every X times through this loop 
  843. 		if loop_count > 0 then 
  844. 			loop_count = 0 
  845. 			if update_needed then 
  846. 				-- actually morph the character 
  847. 				--game_UI_audio_play("UI_Customization_Triangle")				 
  848. 				pcr_apply_morph_value("Global Body", "body muscle", new_str) 
  849. 				pcr_apply_morph_value("Global Body", "body skinny", new_skin) 
  850. 				pcr_apply_morph_value("Global Body", "body fat", new_fat) 
  851. 				pcr_set_triangle_cursor_pos(new_x, new_y)	 
  852. 				 
  853. 				if floor(new_x) ~= floor(Store_character_build_cursor_x) or floor(new_y) ~= floor(Store_character_build_cursor_y) then 
  854. 					Store_character_cancel_confirm_needed = true 
  855. 				end				 
  856. 				 
  857. 				update_needed = false 
  858. 			end 
  859. 		end 
  860. 		loop_count = loop_count + 1 
  861. 		 
  862. 		if Left_stick_input_thread == -1 then 
  863. 			debug_print("vint", "Die... \n") 
  864. 			break 
  865. 		end 
  866. 	end 
  867. end 
  868.  
  869. -- empty function to take priority over normal input for the store while we're in the triangle selector 
  870. function store_character_null(event, value) 
  871. end 
  872.  
  873. function store_character_load_triangle() 
  874. 	store_unlock_controls() 
  875. 	Store_character_strength = pcr_get_morph_value("Global Body", "body muscle") 
  876. 	Store_character_skinny = pcr_get_morph_value("Global Body", "body skinny") 
  877. 	Store_character_fat = pcr_get_morph_value("Global Body", "body fat") 
  878. 	Store_character_build_cursor_x, Store_character_build_cursor_y = pcr_get_triangle_cursor_pos() 
  879.  
  880. 	Triangle_select:init_morphs(Store_character_strength, Store_character_skinny, Store_character_fat, Store_character_build_cursor_x, Store_character_build_cursor_y) 
  881. 	Triangle_select:set_visible(true) 
  882. 	 
  883. 	local title = nil 
  884. 	local title_crc = nil 
  885. 	title_crc = Menu_data[Active_list:get_selection()].label_crc 
  886. 	if title_crc == nil then 
  887. 		title = Menu_data[Active_list:get_selection()].label 
  888. 	end 
  889. 	Store_header:push_title( title_crc, title ) 
  890. end 
  891.  
  892. function store_character_morph_show(menu_data) 
  893. 	Current_tier = BUILD_TIER 
  894. 	Active_list:set_visible(false) 
  895. 	store_character_enable_mouse(false, false) 
  896. 	 
  897. 	if Input_tracker_body_morph_select == nil then 
  898. 		Input_tracker_body_morph_select = Vdo_input_tracker:new()	 
  899. 		Input_tracker_body_morph_select:add_input("left_joy_x", "store_character_move_left_x", 100, true) 
  900. 		Input_tracker_body_morph_select:add_input("left_joy_y", "store_character_move_left_y", 100, true)	 
  901. 		Input_tracker_body_morph_select:add_input("select", "store_character_morph_select", 100) 
  902. 		Input_tracker_body_morph_select:add_input("back", "store_character_morph_revert_confirm", 100)		 
  903. 		Input_tracker_body_morph_select:add_input("nav_up", "store_character_null", 100) 
  904. 		Input_tracker_body_morph_select:add_input("nav_down", "store_character_null", 100) 
  905. 		Input_tracker_body_morph_select:add_input("nav_left", "store_character_null", 100) 
  906. 		Input_tracker_body_morph_select:add_input("nav_right", "store_character_null", 100) 
  907. 		 
  908. 		if Game_platform == "PC" then 
  909. 			store_character_enable_mouse(false, false) 
  910. 	 
  911. 			-- Add mouse input for the "confirm selection" button 
  912. 			local confirm_handle = vint_object_find("btn_highlight", Triangle_select.handle) 
  913. 			Triangle_select_button_handle = vint_object_find("bg", confirm_handle) 
  914. 			Input_tracker_body_morph_select:add_mouse_input("mouse_click", "store_character_mouse_click", 100, Triangle_select_button_handle) 
  915. 			Input_tracker_body_morph_select:add_mouse_input("mouse_move", "store_character_mouse_move", 100, Triangle_select_button_handle) 
  916. 			 
  917. 			local text_handle = vint_object_find("btn_select", Triangle_select.handle) 
  918. 			Triangle_select_text_handle = vint_object_find("toggle_text", text_handle) 
  919. 			 
  920. 			-- Add mouse input for the build triangle 
  921. 			local triangle_handle = vint_object_find("triangle_base", Triangle_select.handle) 
  922. 			Input_tracker_body_morph_select:add_mouse_input("mouse_click", "store_character_mouse_click", 100, triangle_handle) 
  923. 			Input_tracker_body_morph_select:add_mouse_input("mouse_move", "store_character_mouse_move", 100, triangle_handle) 
  924. 			Input_tracker_body_morph_select:add_mouse_input("mouse_drag", "store_character_mouse_drag", 100, triangle_handle) 
  925. 			Input_tracker_body_morph_select:add_mouse_input("mouse_drag_release", "store_character_mouse_drag_release", 100, triangle_handle) 
  926. 		end 
  927. 	end 
  928. 	 
  929. 	Input_tracker_body_morph_select:subscribe(true) 
  930.  
  931. 	--Load triangle bitmap 
  932. 	game_peg_load_with_cb("store_character_load_triangle", 1, "ui_bms_pcr_tri") 
  933. 	store_lock_controls() 
  934. 	 
  935. 	Left_stick_input_thread = thread_new("store_character_move_left_stick_thread") 
  936. end 
  937.  
  938. function store_character_morph_select() 
  939. 	-- Nuke all button subscriptions 
  940. 	Input_tracker_body_morph_select:subscribe(false) 
  941. 	 
  942. 	game_UI_audio_play("UI_Main_Menu_Select") 
  943. 	 
  944. 	if Left_stick_input_thread ~= -1 then 
  945. 		thread_kill(Left_stick_input_thread) 
  946. 		Left_stick_input_thread = -1 
  947. 	end 
  948. 	 
  949. 	-- Unload triangle bitmap 
  950. 	game_peg_unload("ui_bms_pcr_tri")	 
  951. 		 
  952. 	Triangle_select:set_visible(false) 
  953. 	Active_list:set_visible(true) 
  954. 	 
  955. 	Current_tier = MENU_TIER 
  956. 	store_character_enable_mouse(true, false) 
  957. 	 
  958. 	Store_header:pop_title() 
  959. end 
  960.  
  961. -- If the player made changes to the triangle slider, ask if they want to throw them out. 
  962. -- 
  963. function store_character_morph_revert_confirm() 
  964. 	if Store_character_cancel_confirm_needed == false then 
  965. 		store_character_morph_revert() 
  966. 		return 
  967. 	end	 
  968. 	 
  969. 	store_character_enable_mouse(false) 
  970. 	if Input_tracker_body_morph_select ~= nil then 
  971. 		Input_tracker_body_morph_select:subscribe(false) 
  972. 	end 
  973. 	 
  974. 	Store_common_popup:populate_list(Yes_no_choices, 2, STORE_COMMON_LIST_SIZE, 2)	 
  975. 	Store_common_popup:set_title("MENU_TITLE_WARNING") 
  976. 	Store_common_popup:set_text("CANCEL_WARNING_BODY")		 
  977. 	Store_common_popup:nav_enable(true, "store_character_morph_revert_confirm_final", "store_character_popup_nav") 
  978. 	Not_popup_grp:set_alpha(.5)	 
  979. end 
  980.  
  981. -- Handle response to popup 
  982. -- 
  983. function store_character_morph_revert_confirm_final(event) 
  984. 	Store_common_popup:nav_enable(false, nil, nil) 
  985. 	Not_popup_grp:set_alpha(1) 
  986. 	 
  987. 	-- The user hit the B button and are cancelling the cancel :-) 
  988. 	-- This is redundant to selecting "No" in the list 
  989. 	if event == "back" then 
  990. 		game_UI_audio_play("UI_Main_Menu_Nav_Back") 
  991. 		--store_character_enable_mouse(true) 
  992. 		Input_tracker_body_morph_select:subscribe(true) 
  993. 		if Hint_bar_mouse_input_tracker ~= -1 then 
  994. 			Hint_bar_mouse_input_tracker:subscribe(true) 
  995. 		end 
  996. 		return 
  997. 	end 
  998. 	 
  999. 	game_UI_audio_play("UI_Main_Menu_Select")	 
  1000. 	 
  1001. 	-- Did we select yes?  This assumes yes is the first item 
  1002. 	if Store_common_popup:get_selected_data() ~= 1 then 
  1003. 		--store_character_enable_mouse(true) 
  1004. 		Input_tracker_body_morph_select:subscribe(true) 
  1005. 		if Hint_bar_mouse_input_tracker ~= -1 then 
  1006. 			Hint_bar_mouse_input_tracker:subscribe(true) 
  1007. 		end 
  1008. 		return 
  1009. 	end 
  1010.  
  1011. 	-- Do the cancel 
  1012. 	Store_character_cancel_confirm_needed = false 
  1013. 	store_character_morph_revert() 
  1014. end 
  1015.  
  1016.  
  1017. -- Player reverted changes made in the triangle selector 
  1018. function store_character_morph_revert() 
  1019. 	-- Nuke all button subscriptions 
  1020. 	Input_tracker_body_morph_select:subscribe(false) 
  1021. 	 
  1022. 	if Left_stick_input_thread ~= -1 then 
  1023. 		thread_kill(Left_stick_input_thread) 
  1024. 		Left_stick_input_thread = -1 
  1025. 	end 
  1026. 	 
  1027. 	-- restore previous morph values 
  1028. 	pcr_apply_morph_value("Global Body", "body muscle", Store_character_strength) 
  1029. 	pcr_apply_morph_value("Global Body", "body skinny", Store_character_skinny) 
  1030. 	pcr_apply_morph_value("Global Body", "body fat", Store_character_fat)	 
  1031. 	pcr_set_triangle_cursor_pos(Store_character_build_cursor_x, Store_character_build_cursor_y) 
  1032. 	 
  1033. 	-- Unload triangle bitmap 
  1034. 	game_peg_unload("ui_bms_pcr_tri")	 
  1035. 		 
  1036. 	Triangle_select:set_visible(false) 
  1037. 	Active_list:set_visible(true) 
  1038. 	 
  1039. 	Current_tier = MENU_TIER 
  1040. 	store_character_enable_mouse(true) 
  1041. 	 
  1042. 	Store_header:pop_title()	 
  1043. end 
  1044.  
  1045. -- morph support 
  1046. -- 
  1047. function store_character_morph_change(menu_data)	 
  1048. 	pcr_apply_morph_value(menu_data.morph_set, menu_data.morph_id, menu_data.current_value) 
  1049. 	pcr_mark_changed() 
  1050. 	Store_character_confirm_randomize = true 
  1051. 	Store_character_cancel_confirm_needed = true 
  1052. end 
  1053.  
  1054.  
  1055. function store_character_skin_color_add(id, swatch_crc, label_crc, label_str, current) 
  1056.  
  1057. 	local menu_idx = #Color_grid_data + 1 
  1058.  
  1059. 	local item = { 
  1060. 		index = menu_idx, id = id, icon_crc = swatch_crc, label_crc = label_crc, label = label_str, color = {red = 1, green = 1, blue = 1}, 
  1061. 	} 
  1062.  
  1063. 	Color_grid_data[menu_idx] = item 
  1064.  
  1065. 	if current == true then 
  1066. 		Color_grid_idx = menu_idx 
  1067. 		Store_character_skin_color_current_setting = menu_idx 
  1068. 	end 
  1069. end 
  1070.  
  1071. function store_character_skin_grid_show(menu_data) 
  1072.  
  1073. 	--Store_character_original_values.skin_color = nil 
  1074. 	 
  1075. 	Color_grid_data = {} 
  1076. 	Color_grid_idx = 1 
  1077. 	pcr_report_skin_colors("store_character_skin_color_add") 
  1078.  
  1079. 	-- Load Hair Swatches 
  1080. 	game_peg_load_with_cb("store_character_skin_swatch_loaded",1,"ui_bms_pcr_skin") 
  1081. 	store_lock_controls()	 
  1082.  
  1083. 	store_set_camera_pos("body") 
  1084. end 
  1085.  
  1086. function store_character_skin_color_delayed_set() 
  1087. 	delay(0.4) 
  1088.  
  1089. 	pcr_change_skin_color(Store_character_skin_color_selected) 
  1090. 	Store_character_nav_value = nil 
  1091. 	Store_character_nav_thread = -1 
  1092. end 
  1093.  
  1094. function store_character_skin_color_grid_nav(event, value) 
  1095. 	store_character_grid_nav(event, value) 
  1096. 	 
  1097. 	-- set the color and preview the item 
  1098. 	local idx = Store_common_color_grid:return_selected_index() 
  1099. 	Store_character_skin_color_selected = Color_grid_data[idx].id 
  1100. 	 
  1101. 	if Store_character_nav_thread ~= -1 then 
  1102. 		thread_kill(Store_character_nav_thread) 
  1103. 		Store_character_nav_thread = -1 
  1104. 	end 
  1105. 	 
  1106. 	Store_character_nav_thread = thread_new("store_character_skin_color_delayed_set")	 
  1107. end 
  1108.  
  1109.  
  1110. function store_character_skin_swatch_loaded() 
  1111.  
  1112. 	store_unlock_controls() 
  1113.  
  1114. 	Store_common_color_grid:draw_items(Color_grid_data, Color_grid_idx, 5, 4, 83, 83, 26, nil, 1.1) 
  1115. 	Store_common_color_grid:nav_enable(true, "store_character_skin_color_selected", "store_character_skin_color_grid_nav")		 
  1116. 	Store_common_color_grid:set_visible(true)	 
  1117. 	Active_list:set_visible(false) 
  1118. 	 
  1119. 	Current_tier = SKIN_COLOR_TIER 
  1120. 	store_character_enable_mouse(false, false) 
  1121. 	 
  1122. 	-- set the titles on top 
  1123. 	Store_header:push_title( nil, "CUST_SKIN")	 
  1124. end 
  1125.  
  1126. function store_character_skin_color_selected(event) 
  1127. 	 
  1128. 	-- remove skin color title 
  1129. 	Store_header:pop_title() 
  1130. 	 
  1131. 	-- Did the player select a color? 
  1132. 	if event == "select" or event == "mouse_click" then 
  1133. 		 
  1134. 		game_UI_audio_play("UI_Main_Menu_Select") 
  1135. 		 
  1136. 		local idx = Store_common_color_grid:return_selected_index() 
  1137.  
  1138. 		if idx <= #Color_grid_data then 
  1139. 			pcr_change_skin_color(Color_grid_data[idx].id) 
  1140. 			pcr_mark_changed() 
  1141. 		end 
  1142. 	else 
  1143. 		game_UI_audio_play("UI_Main_Menu_Nav_Back") 
  1144. 		if Store_character_nav_thread > -1 then 
  1145. 			thread_kill(Store_character_nav_thread) 
  1146. 			Store_character_nav_thread = -1 
  1147. 		end 
  1148.  
  1149. 		-- player didn't accept; revert change 
  1150. 		if Store_character_skin_color_current_setting ~= -1 then 
  1151. 			pcr_change_skin_color(Color_grid_data[Store_character_skin_color_current_setting].id) 
  1152. 		end 
  1153. 	end	 
  1154. 	 
  1155. 	game_peg_unload("ui_bms_pcr_skin") 
  1156. 	 
  1157. 	Store_common_color_grid:nav_enable(false, nil, nil) 
  1158. 	Store_common_color_grid:cleanup()	 
  1159. 	Store_common_color_grid:set_visible(false) 
  1160. 	Active_list:set_visible(true) 
  1161. 	Color_grid_data = {} 
  1162. 	 
  1163. 	Current_tier = MENU_TIER 
  1164. 	store_character_enable_mouse(true, false) 
  1165. end 
  1166.  
  1167. function store_character_body_menu_return(menu_data)	 
  1168.  
  1169. 	store_character_creation_strip_clothes() 
  1170.  
  1171. 	-- check the current values for age and breast, since a preset will have reset them 
  1172. 	local current_age = pcr_get_morph_value("global body", "old") 
  1173. 	local current_breast = pcr_get_morph_value("global body", "breast")	 
  1174. 	 
  1175. 	menu_data[6].current_value = current_age 
  1176. 	menu_data[7].current_value = current_breast 
  1177. 	 
  1178. 	Store_character_current_preset_gender = pcr_get_player_preset()	 
  1179. 	 
  1180. 	local sex_camera 
  1181. 	if Store_character_current_preset_gender == STORE_CHARACTER_FEMALE_GENDER_NAME then 
  1182. 		sex_camera = "sex female" 
  1183. 	else 
  1184. 		sex_camera = "sex male" 
  1185. 	end	 
  1186. 	 
  1187. 	menu_data[7].camera = sex_camera 
  1188. 	 
  1189. 	-- Redraw the menu to show updated slider values and camera views 
  1190. 	local start_index = store_common_stack_get_index()	 
  1191. 	store_character_populate_list(menu_data, start_index)	 
  1192. end 
  1193.  
  1194. function store_character_camera_on_nav(menu_data) 
  1195. 	if menu_data.camera ~= nil then 
  1196. 		store_set_camera_pos(menu_data.camera) 
  1197. 	end 
  1198. end 
  1199.  
  1200. function store_character_fill_global_menu(menu_data) 
  1201.  
  1202. 	local current_age = pcr_get_morph_value("global body", "old") 
  1203. 	local current_breast = pcr_get_morph_value("global body", "breast") 
  1204.  
  1205. 	Store_character_current_preset_gender = pcr_get_player_preset()	 
  1206.  
  1207. 	local sex_camera 
  1208. 	if Store_character_current_preset_gender == STORE_CHARACTER_FEMALE_GENDER_NAME then 
  1209. 		sex_camera = "sex female" 
  1210. 	else 
  1211. 		sex_camera = "sex male" 
  1212. 	end 
  1213.  
  1214. 	local store_character_global_menu =	{ 
  1215. 		on_enter = store_character_body_menu_return, 
  1216. 		{ label = "CUST_PRESET_SEX",	type = TYPE_BUTTON, on_sub_menu_fill = store_character_preset_sex_fill,			camera = "body",	on_nav = store_character_camera_on_nav }, 
  1217. 		 
  1218. 		{ label = "CUST_PRESET_RACE",	type = TYPE_BUTTON, on_sub_menu_fill = store_character_preset_race_fill,		camera = "body",	on_nav = store_character_camera_on_nav },	 
  1219. 		 
  1220. 		{ label = "STORE_BUILD",		type = TYPE_BUTTON, on_select = store_character_morph_show,							camera = "body",	on_nav = store_character_camera_on_nav }, 
  1221. 		 
  1222. 		{ label = "CUST_SKIN",			type = TYPE_BUTTON, on_select = store_character_skin_grid_show,					camera = "body",	on_nav = store_character_camera_on_nav	},	 
  1223. 		 
  1224. 		{ label = "CUST_BODY_MASK",	type = TYPE_BUTTON, on_sub_menu_fill = store_character_composite_menu_build,	camera = "body",	on_nav = store_character_camera_on_nav,	composite_area = "body mask", }, 
  1225. 		 
  1226. 		{ label = "CUST_PRESET_AGE",	type = TYPE_SLIDER, on_value_update = store_character_morph_change,				camera = "head", on_nav = store_character_camera_on_nav, 
  1227. 		  morph_id = "old",		morph_set = "Global Body",		min = 0,		max = 1,		step = 0.01,		current_value = current_age,  	}, 
  1228. 		   
  1229. 		{ label = "CUST_SEX_APPEAL",	type = TYPE_SLIDER, on_value_update = store_character_morph_change, 				camera = sex_camera, on_nav = store_character_camera_on_nav, 
  1230. 		  morph_id = "breast",	morph_set = "Global Body", 	min = 0,		max = 1,		step = 0.01,		current_value = current_breast,  }, 
  1231. 	} 
  1232. 	 
  1233. 	Store_common_sub_menu = store_character_global_menu 
  1234. end 
  1235.  
  1236.  
  1237. -- Hair menus 
  1238. -------------------------------------------- 
  1239.  
  1240. -- Create the menu of hair style choices. 
  1241. -- 
  1242. function store_character_hair_style_show(menu_data) 
  1243. 	if Store_character_nav_thread > -1 then 
  1244. 		thread_kill(Store_character_nav_thread) 
  1245. 		Store_character_nav_thread = -1 
  1246. 	end 
  1247. 	 
  1248. 	-- save off current hair values 
  1249. 	store_character_hair_item_save()	 
  1250.  
  1251. 	local item = { 
  1252. 		type = TYPE_BUTTON,  
  1253. 		hair_item = -1, 
  1254. 		primary = Store_character_hair_values.primary, 
  1255. 		label = "HAIR_CAT_NONE",  
  1256. 		on_nav = store_character_hair_style_nav,  
  1257. 		on_select = store_character_hair_item_select,  
  1258. 		on_cancel = store_character_hair_item_revert, 
  1259. 	} 
  1260.  
  1261. 	local menu_idx = #Store_common_sub_menu + 1 
  1262. 	Store_common_sub_menu[menu_idx] = item 
  1263. 		 
  1264. 	pcr_report_hair_items(0, "store_character_hair_item_add") 
  1265. end 
  1266.  
  1267. -- Populate hair menus. 
  1268. -- 
  1269. function store_character_hair_item_add(hair_item, label_crc, label_str, is_current) 
  1270. 	local item = { 
  1271. 		type = TYPE_BUTTON,  
  1272. 		hair_item = hair_item, 
  1273. 		primary = Store_character_hair_values.primary, 
  1274. 		label = label_str,  
  1275. 		label_crc = label_crc,  
  1276. 		on_nav = store_character_hair_style_nav,  
  1277. 		on_select = store_character_hair_item_select,  
  1278. 		on_cancel = store_character_hair_item_revert 
  1279. 	} 
  1280. 	 
  1281. 	local menu_idx = #Store_common_sub_menu + 1 
  1282. 	Store_common_sub_menu[menu_idx] = item 
  1283. 	 
  1284. 	if is_current == true then 
  1285. 		Store_common_sub_menu.start_index = menu_idx 
  1286. 	end 
  1287. end 
  1288.  
  1289. -- Update hair preview while player navigates 
  1290. -- 
  1291. function store_character_hair_style_nav(menu_data) 
  1292. 	if Store_character_nav_thread ~= -1 then 
  1293. 		thread_kill(Store_character_nav_thread) 
  1294. 		Store_character_nav_thread = -1 
  1295. 	end 
  1296. 	 
  1297. 	Store_character_nav_value = menu_data 
  1298. 	Store_character_nav_thread = thread_new("store_character_delayed_set_hair_item") 
  1299. end 
  1300.  
  1301. -- Delayed previewing from thread of new hair style while navigating 
  1302. --  
  1303. function store_character_delayed_set_hair_item() 
  1304. 	delay(0.4) 
  1305. 	pcr_change_hair(0, Store_character_nav_value.hair_item, Store_character_nav_value.primary, 0) 
  1306. 	Store_character_nav_thread = -1 
  1307. end 
  1308.  
  1309. -- Player has chosen a hair style and hit accept.  Update, and choose hair colors 
  1310. -- 
  1311. function store_character_hair_item_select(menu_data) 
  1312.  
  1313. 	if Store_character_nav_thread ~= -1 then 
  1314. 		thread_kill(Store_character_nav_thread) 
  1315. 		Store_character_nav_thread = -1 
  1316. 	end 
  1317. 	 
  1318. 	pcr_change_hair(0, menu_data.hair_item, menu_data.primary, 0) 
  1319. 	 
  1320. 	pcr_mark_changed() 
  1321. 	Store_character_confirm_randomize = true 
  1322. 	 
  1323. 	-- Go on to color selection 
  1324. 	if menu_data.hair_item ~= -1 then 
  1325. 		store_character_hair_color_grid_show(menu_data) 
  1326. 	else 
  1327. 		-- Don't choose color if hair choice was "none" 
  1328. 		store_character_hair_item_save() 
  1329. 		store_common_back_menu() 
  1330. 	end 
  1331. end 
  1332.  
  1333. -- Player backed out of hair selection without hitting accept.  Revert to previous hair. 
  1334. -- 
  1335. function store_character_hair_item_revert(menu_data) 
  1336.  
  1337. 	if Store_character_nav_thread ~= -1 then 
  1338. 		thread_kill(Store_character_nav_thread) 
  1339. 		Store_character_nav_thread = -1 
  1340. 	end 
  1341. 	 
  1342. 	-- Do the revert 
  1343. 	pcr_change_hair(0, Store_character_hair_values.style, Store_character_hair_values.primary, 0) 
  1344. end 
  1345.  
  1346. function store_character_hair_item_save(menu_data) 
  1347. 	Store_character_hair_values.style, Store_character_hair_values.primary = pcr_get_hair_info(0) 
  1348. end 
  1349.  
  1350. -- Build the hair color selection grid list.  Start asynchronous load of hair color swatch. 
  1351. -- 
  1352. function store_character_hair_color_grid_show(menu_data)	 
  1353. 	Color_grid_data = {} 
  1354. 	 
  1355. 	-- menu_data.hair_item used if we've changed the hair style and directly went to color selection... otherwise used saved value if just picking color 
  1356. 	Color_grid_data.hair_item = menu_data.hair_item or Store_character_hair_values.style 
  1357. 	 
  1358. 	Color_grid_idx = 1 
  1359. 	 
  1360. 	pcr_report_hair_colors("store_character_hair_color_add") 
  1361.  
  1362. 	-- Load Hair Swatches 
  1363. 	game_peg_load_with_cb("store_character_hair_swatch_loaded",1,"ui_bms_pcr_hair") 
  1364. 	store_lock_controls()	 
  1365. end 
  1366.  
  1367. function store_character_hair_color_add(id, swatch_crc, label_crc, label_str, current, swatch_label) 
  1368. 	local menu_idx = #Color_grid_data + 1 
  1369.  
  1370. 	local item = { 
  1371. 		index = menu_idx,  
  1372. 		id = id,  
  1373. 		label_crc = label_crc,  
  1374. 		label = label_str,  
  1375. 		icon_crc = swatch_crc,  
  1376. 		color = {red = 1, green = 1, blue = 1}, 
  1377. 		hair_item = Color_grid_data.hair_item, 
  1378. 		primary = id, 
  1379. 	} 
  1380.  
  1381. 	-- set start index if this is the current hair color 
  1382. 	if current == true then 
  1383. 		Color_grid_idx = menu_idx 
  1384. 	end 
  1385.  
  1386. 	Color_grid_data[menu_idx] = item 
  1387. end	 
  1388.  
  1389. function store_character_hair_swatch_loaded() 
  1390.  
  1391. 	store_unlock_controls() 
  1392.  
  1393. 	Store_common_color_grid:draw_items(Color_grid_data, Color_grid_idx, 5, 4, 83, 83, 26, nil, 1.1) 
  1394. 	 
  1395. 	Store_common_color_grid:nav_enable(true, "store_character_hair_color_selected", "store_character_hair_color_nav")		 
  1396. 	Store_common_color_grid:set_visible(true)	 
  1397. 	Active_list:set_visible(false) 
  1398. 	 
  1399. 	Current_tier = HAIR_COLOR_TIER 
  1400. 	store_character_enable_mouse(false, false) 
  1401. 	 
  1402. 	-- set the titles on top 
  1403. 	Store_header:push_title(nil, "CUST_PRIMARY_COLOR")		 
  1404. end 
  1405.  
  1406. function store_character_hair_color_nav(event, value) 
  1407. 	store_character_grid_nav(event, value) 
  1408. 	 
  1409. 	-- set the color and preview the item 
  1410. 	local idx = Store_common_color_grid:return_selected_index() 
  1411. 	 
  1412. 	Store_character_nav_value = Color_grid_data[idx] 
  1413. 	 
  1414. 	if Store_character_nav_thread ~= -1 then 
  1415. 		thread_kill(Store_character_nav_thread) 
  1416. 		Store_character_nav_thread = -1 
  1417. 	end 
  1418. 	 
  1419. 	Store_character_nav_thread = thread_new("store_character_delayed_set_hair_item") 
  1420. end 
  1421.  
  1422. function store_character_hair_color_selected(event) 
  1423. 	 
  1424. 	-- always make sure to disable inputs, or we'll run out if we start another hair color grid 
  1425. 	Store_common_color_grid:nav_enable(false, nil, nil)	 
  1426. 	 
  1427. 	-- remove hair color title 
  1428. 	Store_header:pop_title() 
  1429. 	 
  1430. 	game_peg_unload("ui_bms_pcr_hair") 
  1431. 	 
  1432. 	Store_common_color_grid:set_visible(false) 
  1433. 	Active_list:set_visible(true)	 
  1434. 	 
  1435. 	Current_tier = MENU_TIER 
  1436. 	store_character_enable_mouse(true, false) 
  1437. 	 
  1438. 	-- Did the player select a color? 
  1439. 	if event == "select" or event == "mouse_click" then 
  1440. 		 
  1441. 		game_UI_audio_play("UI_Main_Menu_Select") 
  1442. 		 
  1443. 		if Store_character_nav_thread > -1 then 
  1444. 			thread_kill(Store_character_nav_thread) 
  1445. 			Store_character_nav_thread = -1 
  1446. 		end 
  1447.  
  1448. 		local idx = Store_common_color_grid:return_selected_index() 
  1449. 		local menu_data = Color_grid_data[idx] 
  1450.  
  1451. 		pcr_change_hair(0, menu_data.hair_item, menu_data.primary, 0)	 
  1452. 		pcr_mark_changed() 
  1453. 		 
  1454. 		store_character_hair_item_save() 
  1455. 		 
  1456. 		store_common_back_menu() 
  1457. 	else 
  1458. 		game_UI_audio_play("UI_Main_Menu_Nav_Back") 
  1459. 		-- reverse the hair color changes since user cancelled, unless they didn't make any changes yet 
  1460. 		if Store_character_nav_value ~= nil then 
  1461. 			pcr_change_hair(0, Store_character_nav_value.hair_item, Store_character_nav_value.primary, 0) 
  1462. 		end 
  1463. 	end 
  1464. 	 
  1465. 	Color_grid_data = {}	 
  1466. 	Store_common_color_grid:cleanup()	 
  1467. end 
  1468.  
  1469. function store_character_rebuild_hair_menu(menu_data) 
  1470.  
  1471. 	-- We need to rebuild the menu to update the accessory color choices available 
  1472. 	local menu_data = {} 
  1473. 	store_character_fill_hair_menu(menu_data) 
  1474. 	 
  1475. 	Menu_data = {} 
  1476. 	Menu_data = Store_common_sub_menu 
  1477. 	 
  1478. 	local index = Active_list:get_selection() 
  1479. 	store_character_populate_list(Menu_data, index) 
  1480.  
  1481. 	store_character_creation_strip_clothes() 
  1482. end 
  1483.  
  1484. function store_character_hair_randomize(menu_data) 
  1485. 	-- only head hair uses this now 
  1486. 	pcr_hair_randomize_all() 
  1487. 	 
  1488. 	-- randomize facial hair and eyebrows too 
  1489. 	pcr_set_random_composite("eyebrows") 
  1490. 	 
  1491. 	-- but don't do facial hair for females 
  1492. 	if Store_character_current_preset_gender ~= STORE_CHARACTER_FEMALE_GENDER_NAME then 
  1493. 		pcr_set_random_composite("facial hair") 
  1494. 	end 
  1495. 	 
  1496. 	-- Need to rebuild menu, so that "hair accessory color" is shown if necessary or not 
  1497. 	store_character_rebuild_hair_menu() 
  1498. end 
  1499.  
  1500. -- Callback to get a color option from C and add it to our color grid. 
  1501. -- 
  1502. -- color_index: 	indicates which color this is for 
  1503. -- label_crc:		crc to use for the toggle choice name. nil if string is used. 
  1504. -- label_str:		string to use for the toggle choice name.  nil if crc is used. 
  1505. -- red:				r value. 
  1506. -- green:			g value. 
  1507. -- blue:			b value. 
  1508. -- 
  1509. function store_character_hair_acc_color_add(color_index, label_crc, label_str, red, green, blue) 
  1510. 	local grid_idx = #Color_grid_data + 1 
  1511. 	 
  1512. 	Color_grid_data[grid_idx] = { 
  1513. 		icon = "ui_menu_veh_pnt_base", 
  1514. 		label = label_str, 
  1515. 		label_crc = label_crc, 
  1516. 		color = {red = red, green = green, blue = blue}, 
  1517. 		index = color_index, 
  1518. 	} 
  1519. 	 
  1520. 	if color_index == Store_character_hair_acc_info.colors[Color_slot_chosen].index then 
  1521. 		Color_grid_idx = grid_idx 
  1522. 	end 
  1523. end 
  1524.  
  1525. function store_character_hair_acc_color_selected(event) 
  1526. 	 
  1527. 	--Did the player select a color? 
  1528. 	if event == "select" or event == "mouse_click" then 
  1529. 		game_UI_audio_play("UI_Main_Menu_Select") 
  1530. 		-- We don't have to set the colors here... that was already done in our navigate funcion.				 
  1531. 	else 
  1532. 		game_UI_audio_play("UI_Main_Menu_Nav_Back") 
  1533. 		-- restore previous color 
  1534. 		Store_character_hair_acc_info.colors[Color_slot_chosen].index = Color_grid_data[Color_prev_color].index 
  1535. 		Store_character_hair_acc_info.colors[Color_slot_chosen].red = Color_grid_data[Color_prev_color].color.red 
  1536. 		Store_character_hair_acc_info.colors[Color_slot_chosen].green = Color_grid_data[Color_prev_color].color.green 
  1537. 		Store_character_hair_acc_info.colors[Color_slot_chosen].blue = Color_grid_data[Color_prev_color].color.blue	 
  1538.  
  1539. 		local t = Store_character_hair_acc_info 
  1540. 		pcu_set_slot_info(t.slot_index, t.item_index, t.variant_index, t.colors.num_colors, t.colors[0].index, 
  1541. 		t.colors[1].index, t.colors[2].index, t.wear_option_index, t.logo_index, t.logo_color_index, true, CHARACTER_COLOR_POOL_TYPE) 
  1542. 	end 
  1543. 	 
  1544. 	store_character_populate_list(Menu_data, Active_list:get_selection()) 
  1545. 		 
  1546. 	Store_common_color_grid:nav_enable(false, nil, nil) 
  1547. 	Store_common_color_grid:cleanup()	 
  1548. 	Store_common_color_grid:set_visible(false) 
  1549. 	Store_common_color_grid:cleanup() 
  1550. 	Active_list:set_visible(true) 
  1551. 	Color_grid_data = {} 
  1552. 	 
  1553. 	local t = Store_character_hair_acc_info 
  1554. 	 
  1555. 	t.slot_index, t.item_index, t.item_name_crc, t.item_name_str, 
  1556. 	t.num_variants, t.variant_index, t.variant_name_crc, t.variant_name_str, 
  1557. 	t.colors.num_colors, 
  1558. 	t.colors[0].index, t.colors[0].red, t.colors[0].green, t.colors[0].blue, 
  1559. 	t.colors[1].index, t.colors[1].red, t.colors[1].green, t.colors[1].blue, 
  1560. 	t.colors[2].index, t.colors[2].red, t.colors[2].green, t.colors[2].blue, 
  1561. 	t.num_wear_options, t.wear_option_index, t.wear_option_name_crc, t.wear_option_name_str, 
  1562. 	t.num_logos, t.logo_index, t.logo_name_crc, t.logo_name_str, t.logo_color_index, t.logo_color_red, t.logo_color_green, t.logo_color_blue, 
  1563. 	t.item_style, t.item_price, 
  1564. 	t.player_style_level, t.player_style_percent 
  1565. 	= pcu_get_slot_info(HAIR_ITEM_SLOT, CHARACTER_COLOR_POOL_TYPE) 
  1566. 		 
  1567. 	store_character_enable_mouse(true) 
  1568. 	Current_tier = MENU_TIER 
  1569. end 
  1570.  
  1571. function store_character_hair_acc_color_nav(event, value) 
  1572. 	 
  1573. 	if event == "nav_up" then	 
  1574. 		Store_common_color_grid:move_cursor(-2)	 
  1575. 	elseif event == "nav_down" then 
  1576. 		Store_common_color_grid:move_cursor(2) 
  1577. 	elseif event == "nav_left" then 
  1578. 		Store_common_color_grid:move_cursor(-1) 
  1579. 	elseif event == "nav_right" then 
  1580. 		Store_common_color_grid:move_cursor(1) 
  1581. 	 
  1582. 	elseif event == "mouse_move" then 
  1583. 		-- value contains the target_handle in this case 
  1584. 		local new_index = Store_common_color_grid:get_data_index(value) 
  1585. 		if new_index ~= 0 then 
  1586. 			Store_common_color_grid:set_selection(new_index) 
  1587. 			Store_common_color_grid:move_cursor(0, false, true) 
  1588. 		end 
  1589. 		 
  1590. 	else 
  1591. 		--do nothing 
  1592. 	end 
  1593. 	 
  1594. 	-- set the color and preview the item 
  1595. 	local idx = Store_common_color_grid:return_selected_index() 
  1596. 	Store_character_hair_acc_info.colors[Color_slot_chosen].index = Color_grid_data[idx].index 
  1597. 	Store_character_hair_acc_info.colors[Color_slot_chosen].red = Color_grid_data[idx].color.red 
  1598. 	Store_character_hair_acc_info.colors[Color_slot_chosen].green = Color_grid_data[idx].color.green 
  1599. 	Store_character_hair_acc_info.colors[Color_slot_chosen].blue = Color_grid_data[idx].color.blue	 
  1600. 		 
  1601. 	local t = Store_character_hair_acc_info		 
  1602. 	pcu_set_slot_info(t.slot_index, t.item_index, t.variant_index, t.colors.num_colors, t.colors[0].index, 
  1603. 	t.colors[1].index, t.colors[2].index, t.wear_option_index, t.logo_index, t.logo_color_index, true, CHARACTER_COLOR_POOL_TYPE) 
  1604. end 
  1605.  
  1606. function store_character_hair_acc_color_select(menu_data) 
  1607. 	Active_list:set_visible(false) 
  1608. 	 
  1609. 	game_UI_audio_play("UI_Main_Menu_Select") 
  1610. 	 
  1611. 	-- get the colors for the palette 
  1612. 	Color_grid_data = {} 
  1613. 	Color_slot_chosen = menu_data.id 
  1614. 	Color_grid_idx = 1 
  1615. 	pcu_report_item_colors("store_character_hair_acc_color_add", 0, CHARACTER_COLOR_POOL_TYPE) 
  1616. 	 
  1617. 	-- display the grid 
  1618. 	Store_common_color_grid:draw_items(Color_grid_data, Color_grid_idx, 9, 7, 53.5, 53.5, 15, nil, 1.1, true, true, -7, true) 
  1619. 	Store_common_color_grid:set_visible(true) 
  1620. 	Store_common_color_grid:nav_enable(true, "store_character_hair_acc_color_selected", "store_character_hair_acc_color_nav")	 
  1621. 	Color_prev_color = Color_grid_idx 
  1622. 	 
  1623. 	if Mouse_input_tracker ~= 0 then 
  1624. 		Mouse_input_tracker:subscribe(false) 
  1625. 	end 
  1626. 	Current_tier = HAIR_COLOR_TIER 
  1627. end 
  1628.  
  1629. function store_character_fill_hair_menu(menu_data) 
  1630.  
  1631. 	local menu = 	{ 
  1632. 		on_enter = store_character_rebuild_hair_menu,	 
  1633. 		{ label = "CUST_CAT_HAIR_HEAD",		type = TYPE_BUTTON, on_sub_menu_fill = store_character_hair_style_show,			rand_func = store_character_hair_randomize,	camera = "head" }, 
  1634. 		{ label = "CUST_CAT_HAIR_FACIAL",	type = TYPE_BUTTON, on_sub_menu_fill = store_character_composite_menu_build,	rand_func = store_character_hair_randomize,	composite_area = "facial hair",					camera = "facial hair"}, 
  1635. 		{ label = "CUST_CAT_HAIR_EYEBROWS",	type = TYPE_BUTTON, on_sub_menu_fill = store_character_composite_menu_build,	rand_func = store_character_hair_randomize,	composite_area = "eyebrows",						camera = "facial hair"}, 
  1636. 	} 
  1637.  
  1638. 	Store_common_sub_menu = menu 
  1639. 	 
  1640. 	local t = Store_character_hair_acc_info 
  1641. 	 
  1642. 	t.slot_index, t.item_index, t.item_name_crc, t.item_name_str, 
  1643. 	t.num_variants, t.variant_index, t.variant_name_crc, t.variant_name_str, 
  1644. 	t.colors.num_colors, 
  1645. 	t.colors[0].index, t.colors[0].red, t.colors[0].green, t.colors[0].blue, 
  1646. 	t.colors[1].index, t.colors[1].red, t.colors[1].green, t.colors[1].blue, 
  1647. 	t.colors[2].index, t.colors[2].red, t.colors[2].green, t.colors[2].blue, 
  1648. 	t.num_wear_options, t.wear_option_index, t.wear_option_name_crc, t.wear_option_name_str, 
  1649. 	t.num_logos, t.logo_index, t.logo_name_crc, t.logo_name_str, t.logo_color_index, t.logo_color_red, t.logo_color_green, t.logo_color_blue, 
  1650. 	t.item_style, t.item_price, 
  1651. 	t.player_style_level, t.player_style_percent 
  1652. 	= pcu_get_slot_info(HAIR_ITEM_SLOT, CHARACTER_COLOR_POOL_TYPE) 
  1653. 	 
  1654. 	local menu_idx = #Store_common_sub_menu + 1 
  1655. 	 
  1656. 	-- color selections 
  1657. 	if t.colors.num_colors ~= nil and t.colors.num_colors > 0 then 
  1658. 		Store_common_sub_menu[menu_idx] = { label = "CUST_HAIR_ACCESSORY_COLOR",		type = TYPE_BUTTON, on_sub_menu_fill = store_character_hair_acc_color_menu_fill,	rand_func = store_character_hair_randomize,	camera = "head" } 
  1659. 	end 
  1660. 	 
  1661. end	 
  1662.  
  1663. function store_character_hair_acc_color_menu_fill(menu_data) 
  1664.  
  1665. 	local menu_idx = #Store_common_sub_menu 
  1666. 	 
  1667. 	local t = Store_character_hair_acc_info	 
  1668. 	 
  1669. 	-- color selections 
  1670. 	if t.colors.num_colors ~= nil and t.colors.num_colors > 0 then 
  1671. 		local c = t.colors 
  1672. 		 
  1673. 		for i = 0, c.num_colors - 1 do 
  1674. 			local color_label 
  1675. 			if i == 0 then 
  1676. 				color_label = "STORE_PRIMARY_COLOR" 
  1677. 			elseif i == 1 then 
  1678. 				color_label = "STORE_SECONDARY_COLOR" 
  1679. 			elseif i == 2 then 
  1680. 				color_label = "STORE_TERTIARY_COLOR" 
  1681. 			else 
  1682. 				color_label = "STORE_DETAIL_COLOR" 
  1683. 			end 
  1684. 			 
  1685. 			menu_idx = menu_idx + 1 
  1686. 			local new_item = { 
  1687. 				type = TYPE_TOGGLE_COLOR, 
  1688. 				id = i, 
  1689. 				label = color_label, 
  1690. 				label_crc = nil, 
  1691. 				color = c[i], 
  1692. 				on_select = store_character_hair_acc_color_select, 
  1693. 			}	 
  1694. 			Store_common_sub_menu[menu_idx] = new_item	 
  1695. 		end 
  1696. 	end 
  1697. end 
  1698.  
  1699. -- Makeup menus 
  1700. -------------------------------------------- 
  1701.  
  1702. function store_character_makeup_randomize(menu_data) 
  1703.  
  1704. 	-- randomize from the makeup selections 
  1705. 	local areas = {"makeup eyeliner", "makeup eyeshadow", "makeup cheeks", "makeup entire face", "fingernails", "face items"} 
  1706. 	 
  1707. 	for index, composite_area in pairs(areas) do 
  1708. 		pcr_set_random_composite(composite_area) 
  1709. 	end	 
  1710. 	 
  1711. 	pcr_lips_randomize() 
  1712. end 
  1713.  
  1714. function store_character_makeup_enter_menu() 
  1715.  
  1716. 	store_character_creation_strip_clothes() 
  1717. 	store_set_camera_pos("head") 
  1718. end 
  1719.  
  1720. -- Face menus 
  1721. -------------------------------------------- 
  1722.  
  1723. function store_character_randomize_one_morph(id, name_crc, name_str, value, gender, step_rate, rand_range) 
  1724. 	pcr_apply_morph_value(Store_character_randomizing_morph_set, id, rand_float(0.5 - rand_range, 0.5 + rand_range)) 
  1725. 	pcr_mark_changed() 
  1726. end 
  1727.  
  1728. function store_character_randomize_all_morphs(menu_data) 
  1729.  
  1730. 	local morph_sets = {"Brow", "Crown", "Forehead", "Eyes", "Nose", "Cheekbones", "Ears", "Chin", "Mouth", "Jaw"} 
  1731. 	 
  1732. 	for index, morph_set_id in pairs(morph_sets) do 
  1733. 		Store_character_randomizing_morph_set = morph_set_id 
  1734. 		pcr_report_avail_morphs(morph_set_id, "store_character_randomize_one_morph") 
  1735. 	end 
  1736. 	 
  1737. 	pcr_randomize_eye_colors() 
  1738. 	 
  1739. 	Store_character_randomizing_morph_set = -1 
  1740. 	 
  1741. 	-- Now remove all facial features, then pick random one(s) 
  1742. 	pcr_report_composite_items("face features", "store_character_composite_face_features_remove")	 
  1743. 	 
  1744. 	-- super easy algorithm to pick feature, but favor less features over more. 
  1745. 	local one_more_chance = 0.6 -- tweak this value to lower or raise expected number of features 
  1746. 	local random_features = 0 
  1747. 	 
  1748. 	while random_features < MAX_FACIAL_FEATURES do 
  1749. 		if rand_float(0.0, 1.0) > one_more_chance then 
  1750. 			-- we're done! 
  1751. 			random_features = MAX_FACIAL_FEATURES 
  1752. 		else 
  1753. 			pcr_set_random_composite("face features", true) 
  1754. 			random_features = random_features + 1 
  1755. 		end 
  1756. 	end 
  1757. end 
  1758.  
  1759. function store_character_composite_face_features_remove(composite_index, name_crc, name_str, current, colorized, alpha_select, unused_price, unused_respect) 
  1760. 	-- only remove if it's set 
  1761. 	if current then 
  1762. 		pcr_change_composite("face features", composite_index, -1, -1, COMPOSITE_REMOVE) 
  1763. 	end 
  1764. end 
  1765.  
  1766. function store_character_randomize_morph_set(menu_data) 
  1767. 	for i = 1, #Menu_data do 
  1768. 		local curr_item = Menu_data[i] 
  1769. 		local v = rand_float(0.5 - curr_item.rand_range, 0.5 + curr_item.rand_range) 
  1770. 		curr_item.current_value = v 
  1771. 		pcr_apply_morph_value(curr_item.morph_set, curr_item.morph_id, v) 
  1772. 	end 
  1773. 	 
  1774. 	-- redraw the sliders with new values 
  1775. 	local current_index = Active_list:get_selection()	 
  1776. 	store_character_populate_list(Menu_data, current_index)	 
  1777. 	 
  1778. 	pcr_mark_changed() 
  1779. end 
  1780.  
  1781. -- Player accepted morph changes on slider menu 
  1782. -- 
  1783. function store_character_morph_accept() 
  1784. 	game_UI_audio_play("UI_Main_Menu_Select") 
  1785. 	store_common_back_menu() 
  1786. end 
  1787.  
  1788. -- Player hit cancel on slider menu 
  1789. -- 
  1790. function store_character_morph_cancel() 
  1791. 	 
  1792. 	-- restore all to original values 
  1793. 	for i = 1, #Menu_data do 
  1794. 		local curr_item = Menu_data[i] 
  1795. 		pcr_apply_morph_value(curr_item.morph_set, curr_item.morph_id, curr_item.orig_value) 
  1796. 	end	 
  1797. end 
  1798.  
  1799. -- Player hit cancel on slider menu - check if we need to confirm with player before proceeding. 
  1800. -- Return true if a confirm is needed, false if we can proceed. 
  1801. -- 
  1802. function store_character_morph_cancel_confirm() 
  1803. 	if Store_character_cancel_confirm_needed == false then 
  1804. 		return false 
  1805. 	end	 
  1806. 	 
  1807. 	store_character_enable_mouse(false) 
  1808.  
  1809. 	Store_common_popup:populate_list(Yes_no_choices, 2, STORE_COMMON_LIST_SIZE, 2)	 
  1810. 	Store_common_popup:set_title("MENU_TITLE_WARNING") 
  1811. 	Store_common_popup:set_text("CANCEL_WARNING_BODY")		 
  1812. 	Store_common_popup:nav_enable(true, "store_character_morph_cancel_final", "store_character_popup_nav") 
  1813. 	Not_popup_grp:set_alpha(.5)	 
  1814. 	Active_list:set_visible(false) 
  1815. 	 
  1816. 	return true 
  1817. end 
  1818.  
  1819. function store_character_morph_cancel_final(event) 
  1820. 	Store_common_popup:nav_enable(false, nil, nil) 
  1821. 	Not_popup_grp:set_alpha(1) 
  1822. 	Active_list:set_visible(true) 
  1823. 	 
  1824. 	-- The user hit the B button and are cancelling the cancel :-) 
  1825. 	-- This is redundant to selecting "No" in the list 
  1826. 	if event == "back" then 
  1827. 		game_UI_audio_play("UI_Main_Menu_Nav_Back") 
  1828. 		store_character_enable_mouse(true) 
  1829. 		return 
  1830. 	end 
  1831. 	 
  1832. 	game_UI_audio_play("UI_Main_Menu_Select")	 
  1833. 	 
  1834. 	-- Did we select yes?  This assumes yes is the first item 
  1835. 	if Store_common_popup:get_selected_data() ~= 1 then 
  1836. 		store_character_enable_mouse(true) 
  1837. 		return 
  1838. 	end 
  1839.  
  1840. 	-- Do the cancel 
  1841. 	Store_character_cancel_confirm_needed = false 
  1842.  
  1843. 	store_common_button_b() 
  1844. end 
  1845.  
  1846. function store_character_morph_add(id, name_crc, name_str, value, gender, step_value, rand_range) 
  1847. 	local item = { 
  1848. 		type = TYPE_SLIDER, morph_id = id, morph_set = Store_character_building_morph_set, rand_func = store_character_randomize_morph_set, 
  1849. 		is_gender = gender, on_value_update = store_character_morph_change, label_crc = name_crc, label = name_str, 
  1850. 		orig_value = value, current_value = value, min = 0, max = 1, step = step_value, rand_range = rand_range, 
  1851. 		on_select = store_character_morph_accept, on_cancel = store_character_morph_cancel, on_cancel_confirm = store_character_morph_cancel_confirm 
  1852. 	} 
  1853.  
  1854. 	local menu_idx = #Store_common_sub_menu + 1 
  1855. 	Store_common_sub_menu[menu_idx] = item 
  1856. end 
  1857.  
  1858. function store_character_morph_menu_build(menu_data) 
  1859.  
  1860. 	Store_character_building_morph_set = {} 
  1861. 	Store_character_building_morph_set = menu_data.morph_set 
  1862. 	 
  1863. 	pcr_report_avail_morphs(menu_data.morph_set, "store_character_morph_add") 
  1864.  
  1865. 	Store_character_cancel_confirm_needed = false 
  1866. 	 
  1867. 	if menu_data.camera ~= nil then 
  1868. 		store_set_camera_pos(menu_data.camera) 
  1869. 	end 
  1870. end 
  1871.  
  1872. function store_character_eye_color_add(id, swatch_crc, label_crc, label_str, current) 
  1873.  
  1874. 	local menu_idx = #Color_grid_data + 1 
  1875.  
  1876. 	local item = { 
  1877. 		index = menu_idx, id = id, icon_crc = swatch_crc, label_crc = label_crc, label = label_str, color = {red = 1, green = 1, blue = 1}, 
  1878. 	} 
  1879.  
  1880. 	Color_grid_data[menu_idx] = item 
  1881.  
  1882. 	if current == true then 
  1883. 		Color_grid_idx = menu_idx 
  1884. 		Store_character_orig_eye_color = id 
  1885. 	end 
  1886. end 
  1887.  
  1888. function store_character_eye_grid_show(menu_data) 
  1889. 	-- Disable mouse input for hint buttons 
  1890. 	if Hint_bar_mouse_input_tracker ~= -1 then 
  1891. 		Hint_bar_mouse_input_tracker:remove_all() 
  1892. 	end 
  1893.  
  1894. 	--Store_character_original_values.eyes_color = nil 
  1895. 	 
  1896. 	Color_grid_data = {} 
  1897. 	Color_grid_idx = 1 
  1898. 	pcr_report_eye_colors("store_character_eye_color_add") 
  1899.  
  1900. 	-- Load Hair Swatches 
  1901. 	game_peg_load_with_cb("store_character_eye_swatch_loaded",1,"ui_bms_pcr_eyes") 
  1902. 	store_lock_controls()		 
  1903.  
  1904. 	store_set_camera_pos("eyes") 
  1905. 	 
  1906. 	-- take randomize choice out of hints 
  1907. 	local hint_data = { {CTRL_MENU_BUTTON_B, "MENU_BACK"} } 
  1908. 	Store_common_hint_bar:set_hints(hint_data) 
  1909. 	 
  1910. 	-- Re-enable mouse input for hint buttons 
  1911. 	if Hint_bar_mouse_input_tracker ~= -1 then 
  1912. 		Store_common_hint_bar:add_mouse_inputs("store_character", Hint_bar_mouse_input_tracker) 
  1913. 		Hint_bar_mouse_input_tracker:subscribe(true) 
  1914. 	end 
  1915. end 
  1916.  
  1917. -- Leaving head/face submenu. Currently just makes sure we reposition the camera. 
  1918. -- 
  1919. function store_character_face_menu_back(menu_data) 
  1920. 	store_set_camera_pos("head") 
  1921. 	 
  1922. 	store_character_creation_strip_clothes()	 
  1923. end 
  1924.  
  1925. function store_character_eye_delayed_set() 
  1926. 	delay(0.4) 
  1927.  
  1928. 	pcr_change_eye_color(Store_character_eye_selected) 
  1929. 	Store_character_nav_value = nil 
  1930. 	Store_character_nav_thread = -1 
  1931. end 
  1932.  
  1933. function store_character_eye_grid_nav(event, value) 
  1934. 	store_character_grid_nav(event, value) 
  1935. 	 
  1936. 	-- set the color and preview the item 
  1937. 	local idx = Store_common_color_grid:return_selected_index() 
  1938. 	Store_character_eye_selected = Color_grid_data[idx].id 
  1939. 	 
  1940. 	if Store_character_nav_thread ~= -1 then 
  1941. 		thread_kill(Store_character_nav_thread) 
  1942. 		Store_character_nav_thread = -1 
  1943. 	end 
  1944. 	 
  1945. 	Store_character_nav_thread = thread_new("store_character_eye_delayed_set")	 
  1946. end 
  1947.  
  1948.  
  1949. function store_character_eye_swatch_loaded() 
  1950.  
  1951. 	store_unlock_controls() 
  1952.  
  1953. 	Store_common_color_grid:draw_items(Color_grid_data, Color_grid_idx, 7, 2, 59, 64, 25) 
  1954. 	Store_common_color_grid:nav_enable(true, "store_character_eye_color_selected", "store_character_eye_grid_nav")		 
  1955. 	Store_common_color_grid:set_visible(true)	 
  1956. 	Active_list:set_visible(false) 
  1957. 	 
  1958. 	Current_tier = EYE_COLOR_TIER 
  1959. 	store_character_enable_mouse(false, false) 
  1960. 	 
  1961. 	-- set the titles on top 
  1962. 	Store_header:push_title(nil, "CUST_EYE_COLOR")		 
  1963. end 
  1964.  
  1965. function store_character_eye_color_selected(event) 
  1966. 	 
  1967. 	-- remove hair color title 
  1968. 	Store_header:pop_title()	 
  1969. 	 
  1970. 	-- Did the player select a color? 
  1971. 	if event == "select" or event == "mouse_click" then 
  1972. 	 
  1973. 		game_UI_audio_play("UI_Main_Menu_Select") 
  1974. 		 
  1975. 		local idx = Store_common_color_grid:return_selected_index() 
  1976.  
  1977. 		if idx <= #Color_grid_data then 
  1978. 			pcr_change_eye_color(Color_grid_data[idx].id) 
  1979. 			pcr_mark_changed() 
  1980. 		end 
  1981. 	else 
  1982. 		if Store_character_nav_thread > -1 then 
  1983. 			thread_kill(Store_character_nav_thread) 
  1984. 			Store_character_nav_thread = -1 
  1985. 		end 
  1986. 		 
  1987. 		pcr_change_eye_color(Store_character_orig_eye_color) 
  1988. 	end	 
  1989. 	 
  1990. 	game_peg_unload("ui_bms_pcr_eyes") 
  1991. 	 
  1992. 	Store_common_color_grid:nav_enable(false, nil, nil) 
  1993. 	Store_common_color_grid:cleanup()	 
  1994. 	Store_common_color_grid:set_visible(false) 
  1995. 	Active_list:set_visible(true) 
  1996. 	Color_grid_data = {} 
  1997. 	 
  1998. 	Current_tier = MENU_TIER 
  1999. 	store_character_enable_mouse(true, false) 
  2000.  
  2001. 	-- restore camera back to head position 
  2002. 	store_character_face_menu_back()	 
  2003. 	 
  2004. 	-- repopulate menu to restore hints 
  2005. 	store_character_populate_list(Menu_data, Active_list:get_selection()) 
  2006. end 
  2007.  
  2008.  
  2009. -- Personality menus 
  2010. -------------------------------------------- 
  2011.  
  2012. -- voice 
  2013. function store_character_set_voice(menu_data) 
  2014. 	pcr_set_voice(menu_data.voice, false) 
  2015. 	pcr_mark_changed() 
  2016. 	 
  2017. 	-- back out of the menu 
  2018. 	store_common_button_b() 
  2019. end 
  2020.  
  2021. function store_character_preview_voice(menu_data) 
  2022. 	pcr_set_voice(menu_data.voice, true) 
  2023. end 
  2024.  
  2025. function store_character_movement_select(menu_data) 
  2026. 	pcr_set_anim(menu_data.anim_grp, menu_data.anim_id) 
  2027. 	store_common_back_menu() 
  2028. end 
  2029.  
  2030. function store_character_movement_revert(menu_data) 
  2031. 	pcr_set_anim(menu_data.anim_grp, Store_character_original_anim_id) 
  2032. end 
  2033.  
  2034. function store_character_movement_stop() 
  2035. 	pcr_preview_anim(nil) 
  2036. end 
  2037.  
  2038. function store_character_movement_nav(menu_data) 
  2039. 	pcr_preview_anim(menu_data.anim_grp) 
  2040. 	pcr_set_anim(menu_data.anim_grp, menu_data.anim_id) 
  2041. end 
  2042.  
  2043. function store_character_movement_add_item(display_name, id, current) 
  2044.  
  2045. 	local menu_idx = #Store_common_sub_menu + 1 
  2046.  
  2047. 	local item = { label = display_name, type = TYPE_BUTTON, anim_id = id, anim_grp = Store_character_movement_anim_grp,  
  2048. 		on_nav = store_character_movement_nav, on_select = store_character_movement_select, on_cancel = store_character_movement_revert, 
  2049. 	} 
  2050. 	 
  2051. 	if current == true then 
  2052. 		Store_character_original_anim_id = id 
  2053. 		Store_common_sub_menu.start_index = menu_idx 
  2054. 	end 
  2055. 	 
  2056. 	Store_common_sub_menu[menu_idx] = item 
  2057. end 
  2058.  
  2059. function store_character_movement_show(menu_data) 
  2060. 	Store_common_sub_menu.start_index = 1 
  2061. 	Store_character_movement_anim_grp = menu_data.anim_group 
  2062. 	pcr_report_anims(menu_data.anim_group, "store_character_movement_add_item") 
  2063. 	if #Store_common_sub_menu == 0 then 
  2064. 		Store_common_sub_menu[1] = { label = "NO_OPTIONS_RIGHT_NOW", type = TYPE_BUTTON, anim_grp = -1, anim_id = -1 } 
  2065. 	else		 
  2066. 		store_character_movement_nav(Store_common_sub_menu[Store_common_sub_menu.start_index]) 
  2067. 	end 
  2068. end 
  2069.  
  2070.  
  2071. function store_character_voice_menu_fill(menu_data) 
  2072.  
  2073. 	local store_character_presets_voice_menu = { 
  2074. 		{ label = "CUST_VOICE_MALE_WHITE",		type = TYPE_BUTTON, on_nav = store_character_preview_voice, on_select = store_character_set_voice, voice = "MALE_WHITE" }, 
  2075. 		{ label = "CUST_VOICE_MALE_BLACK", 		type = TYPE_BUTTON, on_nav = store_character_preview_voice, on_select = store_character_set_voice, voice = "MALE_BLACK" }, 
  2076. 		{ label = "CUST_VOICE_MALE_LATINO", 	type = TYPE_BUTTON, on_nav = store_character_preview_voice, on_select = store_character_set_voice, voice = "MALE_WHITE_ACCENT" }, 
  2077. 		{ label = "CUST_VOICE_FEMALE_WHITE",	type = TYPE_BUTTON, on_nav = store_character_preview_voice, on_select = store_character_set_voice, voice = "FEMALE_WHITE" }, 
  2078. 		{ label = "CUST_VOICE_FEMALE_BLACK", 	type = TYPE_BUTTON, on_nav = store_character_preview_voice, on_select = store_character_set_voice, voice = "FEMALE_BLACK" }, 
  2079. 		{ label = "CUST_VOICE_FEMALE_LATINO", 	type = TYPE_BUTTON, on_nav = store_character_preview_voice, on_select = store_character_set_voice, voice = "FEMALE_LATINO" }, 
  2080. 		{ label = "CUST_VOICE_ZOMBIE", 			type = TYPE_BUTTON, on_nav = store_character_preview_voice, on_select = store_character_set_voice, voice = "ZOMBIE" },	 
  2081. 	} 
  2082.  
  2083. 	Store_common_sub_menu = store_character_presets_voice_menu 
  2084. 	 
  2085. 	-- get index of current voice setting; add 1 because lua menu starts at index 1 instead of 0 
  2086. 	local selected_voice = pcr_get_voice() + 1 
  2087. 	 
  2088. 	-- check for valid range 
  2089. 	if selected_voice >= 1 and selected_voice <= #store_character_presets_voice_menu then 
  2090. 		-- set as highlighted option 
  2091. 		Store_common_sub_menu.start_index = selected_voice 
  2092. 		 
  2093. 		-- and play a preview of it 
  2094. 		store_character_preview_voice(store_character_presets_voice_menu[selected_voice]) 
  2095. 	end 
  2096. end 
  2097.  
  2098. -- Main menu 
  2099. -------------------------------------------- 
  2100.  
  2101. function store_character_exit_final(event, value) 
  2102. 	Store_common_popup:nav_enable(false, nil, nil) 
  2103. 	 
  2104. 	-- The user hit the B button and is exiting 
  2105. 	-- This is redundant to selecting "No" in the list 
  2106. 	if event == "back" then 
  2107. 		game_UI_audio_play("UI_Main_Menu_Nav_Back")	 
  2108. 		Not_popup_grp:set_alpha(1) 
  2109. 		Active_list:set_visible(true) 
  2110. 		store_character_enable_mouse(true) 
  2111. 		return 
  2112. 	end 
  2113. 	 
  2114. 	game_UI_audio_play("UI_Main_Menu_Select") 
  2115. 	 
  2116. 	-- Make sure the popup is set to the correct selection when the user clicks on a button 
  2117. 	if event == "mouse_click" then 
  2118. 		local new_index = Store_common_popup.list:get_button_index(value) 
  2119. 		if new_index ~= 0 then 
  2120. 			Store_common_popup.list:set_selection(new_index) 
  2121. 		end 
  2122. 	end 
  2123. 	 
  2124. 	-- Did we select yes?  This assumes yes is the first item 
  2125. 	if Store_common_popup:get_selected_data() ~= 1 then 
  2126. 		Not_popup_grp:set_alpha(1) 
  2127. 		Active_list:set_visible(true) 
  2128. 		store_character_enable_mouse(true) 
  2129. 		return 
  2130. 	end 
  2131. 	 
  2132. 	store_lock_controls() 
  2133. 	 
  2134. 	Not_popup_grp:set_alpha(0) 
  2135. 	 
  2136. 	-- exit the interface.  for police lineup, we need to wait for both players in co-op 
  2137. 	if pcr_is_plastic_surgeon() == true then 
  2138. 		pop_screen() 
  2139. 	else 
  2140. 		pcr_creation_complete() 
  2141. 	end 
  2142. end 
  2143.  
  2144. -- Player has requested to leave the store.  Get confirmation before doing so. 
  2145. -- 
  2146. function store_character_exit(menu_data) 
  2147.  
  2148. 	local body 
  2149. 	local heading = "MENU_TITLE_WARNING" 
  2150. 	 
  2151. 	-- Not allowed to leave store until streaming of character assets is done 
  2152. 	if pcu_is_streaming_done() == false then 
  2153. 		return 
  2154. 	end 
  2155. 	 
  2156. 	if pcr_is_plastic_surgeon() == true then 
  2157. 		body = "SURGEON_FINISHED_FULL" 
  2158. 	else 
  2159. 		body = "CUST_EXIT_WARNING_BODY" 
  2160. 	end 
  2161. 	 
  2162. 	store_character_enable_mouse(false) 
  2163. 	 
  2164. 	Store_common_popup:populate_list(Yes_no_choices, 2, STORE_COMMON_LIST_SIZE, 2)	 
  2165. 	Store_common_popup:set_title(heading) 
  2166. 	Store_common_popup:set_text(body)		 
  2167. 	Store_common_popup:nav_enable(true, "store_character_exit_final", "store_character_popup_nav") 
  2168. 	Not_popup_grp:set_alpha(.5)	 
  2169. 	Active_list:set_visible(false) 
  2170. end 
  2171.  
  2172. -- We have returned to the top level menu.  Currently restores camera position and 
  2173. -- makes sure the thread for preset updates is killed.  Also returns clothes on the player in creation. 
  2174. -- 
  2175. function store_character_return_main(menu_data) 
  2176. 	store_character_preset_cleanup() 
  2177. 	store_set_camera_pos("body")	 
  2178. 	store_character_creation_add_clothes()	 
  2179. 	 
  2180. 	Color_grid_idx			= 1 
  2181. 	Color_slot_chosen		= 0 
  2182. 	Color_grid_data		= {} 
  2183. 	Prev_index = -1 
  2184. 	Store_character_randomizing_morph_set = -1 
  2185. 	Store_character_building_morph_set = -1 
  2186. 	Store_character_preset_previous_settings = -1 
  2187. 	Store_character_current_composite_area = -1 
  2188. 	Store_character_current_composite_item = -1 
  2189. 	Store_character_current_composite_color = -1 
  2190. 	Store_character_current_composite_alpha = -1 
  2191. 	Store_character_allow_multiple_composites = -1 
  2192. 	Store_character_composites_allowed = -1 
  2193. 	Store_character_composites_used = -1 
  2194. 	Store_character_hair_acc_info = { 
  2195. 		colors = { [0] = { }, [1] = { }, [2] = { } } 
  2196. 	} 
  2197. 	Color_prev_color		= 0 
  2198. 	Store_character_hair_values = {} 
  2199. 	Store_character_skin_color_current_setting = -1 
  2200. 	Store_character_skin_color_selected = 0 
  2201. 	Store_character_eye_selected = 0 
  2202. 	Store_character_movement_anim_grp = -1 
  2203. 	Store_character_orig_eye_color = -1 
  2204. 	Store_character_strength = -1 
  2205. 	Store_character_skinny = -1 
  2206. 	Store_character_fat = -1 
  2207. 	Store_character_tentative_preset_data = -1 
  2208. 	 
  2209. 	-- kill update thread if it's still around 
  2210. 	if Store_character_nav_thread ~= -1 then 
  2211. 		thread_kill(Store_character_nav_thread) 
  2212. 		Store_character_nav_thread = -1 
  2213. 	end	 
  2214. end 
  2215.  
  2216. function store_character_set_start_camera() 
  2217. 	if Store_character_init_camera_moved == false then 
  2218. 		store_set_camera_pos("body")	 
  2219. 		store_start_lighting_change() 
  2220. 		Store_character_init_camera_moved = true 
  2221. 	end 
  2222. end 
  2223.  
  2224. -- Load the online character gallery. 
  2225. -- 
  2226. function store_character_load_gallery() 
  2227. 	Store_character_new_state_on_validation = GALLERY_FULL_STATE 
  2228. 	Online_check_thread = thread_new("store_character_check_online_for_gallery") 
  2229. end 
  2230.  
  2231. function store_character_check_online_for_gallery() 
  2232. 	online_and_privilege_validator_begin(false, true, true, true, true, true)	-- Check we're signed in and we have content permissions 
  2233. 	while Online_validator_result == ONLINE_VALIDATOR_IN_PROGRESS do 
  2234. 		thread_yield() 
  2235. 	end 
  2236. 	 
  2237. 	if Online_validator_result ~= ONLINE_VALIDATOR_PASSED then 
  2238. 		return 
  2239. 	end 
  2240.  
  2241. 	if main_menu_check_user_content() == false then 
  2242. 		dialog_box_message("MENU_TITLE_WARNING", "USER_CONTENT_PRIV_DENIED") 
  2243. 		return 
  2244. 	end 
  2245. 	 
  2246. 	pcr_restore_clothing() 
  2247.  
  2248. 	-- proceed to the character gallery (could be full menu or download only, based on where we're coming from) 
  2249. 	store_character_change_state(Store_character_new_state_on_validation) 
  2250.  
  2251. 	Online_check_thread = -1 
  2252. end 
  2253.  
  2254. function store_character_face_menu_fill() 
  2255.  
  2256. 	local face_menu = { 
  2257. 		on_enter = store_character_face_menu_back, 
  2258. 		{ label = "CUST_FACIAL_FEATURES",		type = TYPE_BUTTON, on_sub_menu_fill = store_character_composite_menu_build, 	rand_func = store_character_randomize_all_morphs, 	composite_area = "face features", 						max_selections = MAX_FACIAL_FEATURES,			camera = "eyes",},	 
  2259. 		{ label = "cust_morph_cat_crown",		type = TYPE_BUTTON, on_sub_menu_fill = store_character_morph_menu_build, 		rand_func = store_character_randomize_all_morphs, 	morph_set = "crown", 		camera = "crown",}, 
  2260. 		{ label = "cust_morph_cat_forehead",	type = TYPE_BUTTON, on_sub_menu_fill = store_character_morph_menu_build, 		rand_func = store_character_randomize_all_morphs, 	morph_set = "forehead", 	camera = "forehead",}, 
  2261. 		{ label = "cust_morph_cat_brow",			type = TYPE_BUTTON, on_sub_menu_fill = store_character_morph_menu_build, 		rand_func = store_character_randomize_all_morphs, 	morph_set = "brow", 			camera = "brow",}, 
  2262. 		{ label = "cust_morph_cat_eyes",			type = TYPE_BUTTON, on_sub_menu_fill = store_character_morph_menu_build, 		rand_func = store_character_randomize_all_morphs, 	morph_set = "eyes", 			camera = "eyes",}, 
  2263. 		{ label = "CUST_EYE_COLOR",				type = TYPE_BUTTON, on_select = store_character_eye_grid_show, 					rand_func = store_character_randomize_all_morphs, 	on_back = store_character_face_menu_back,													camera = "eyes",}, 
  2264. 		{ label = "cust_morph_cat_ears",			type = TYPE_BUTTON, on_sub_menu_fill = store_character_morph_menu_build, 		rand_func = store_character_randomize_all_morphs, 	morph_set = "ears", 			camera = "ears",}, 
  2265. 		{ label = "cust_morph_cat_cheekbones", type = TYPE_BUTTON, on_sub_menu_fill = store_character_morph_menu_build, 		rand_func = store_character_randomize_all_morphs, 	morph_set = "cheekbones",	camera = "cheekbones",}, 
  2266. 		{ label = "cust_morph_cat_nose",			type = TYPE_BUTTON, on_sub_menu_fill = store_character_morph_menu_build, 		rand_func = store_character_randomize_all_morphs, 	morph_set = "nose", 			camera = "nose",}, 
  2267. 		{ label = "cust_morph_cat_mouth",		type = TYPE_BUTTON, on_sub_menu_fill = store_character_morph_menu_build, 		rand_func = store_character_randomize_all_morphs, 	morph_set = "mouth", 		camera = "mouth",}, 
  2268. 		{ label = "cust_morph_cat_chin",			type = TYPE_BUTTON, on_sub_menu_fill = store_character_morph_menu_build, 		rand_func = store_character_randomize_all_morphs, 	morph_set = "chin", 			camera = "chin",}, 
  2269. 		{ label = "cust_morph_cat_jaw",			type = TYPE_BUTTON, on_sub_menu_fill = store_character_morph_menu_build, 		rand_func = store_character_randomize_all_morphs, 	morph_set = "jaw", 			camera = "jaw",}, 
  2270. 	} 
  2271.  
  2272. 	Store_common_sub_menu = face_menu 
  2273. end 
  2274.  
  2275. function store_character_makeup_menu_fill() 
  2276.  
  2277. 	local makeup_menu = { 
  2278. 		on_enter = store_character_makeup_enter_menu, 
  2279. 		{ label = "CUST_EYELINER",						type = TYPE_BUTTON, on_sub_menu_fill = store_character_composite_menu_build, rand_func = store_character_makeup_randomize, composite_area = "makeup eyeliner",		camera = "eyes", }, 
  2280. 		{ label = "CUST_EYESHADOW", 					type = TYPE_BUTTON, on_sub_menu_fill = store_character_composite_menu_build, rand_func = store_character_makeup_randomize, composite_area = "makeup eyeshadow",	camera = "eyes", }, 
  2281. 		{ label = "CUST_CAT_MAKEUP_CHEEKS", 		type = TYPE_BUTTON, on_sub_menu_fill = store_character_composite_menu_build, rand_func = store_character_makeup_randomize, composite_area = "makeup cheeks",		camera = "head", }, 
  2282. 		{ label = "CUST_CAT_MAKEUP_MOUTH",			type = TYPE_BUTTON, on_sub_menu_fill = store_character_composite_menu_build, rand_func = store_character_makeup_randomize, composite_area = "lips", 					camera = "head" }, 
  2283. 		{ label = "CUST_CAT_MAKEUP_ENTIRE_FACE",	type = TYPE_BUTTON, on_sub_menu_fill = store_character_composite_menu_build, rand_func = store_character_makeup_randomize, composite_area = "makeup entire face", camera = "head", }, 
  2284. 		{ label = "CUST_FACIAL_ITEMS", 				type = TYPE_BUTTON, on_sub_menu_fill = store_character_composite_menu_build, rand_func = store_character_makeup_randomize, composite_area = "face items", 			camera = "entire face", },	 
  2285. 		{ label = "CUST_CAT_FINGERNAILS",			type = TYPE_BUTTON, on_sub_menu_fill = store_character_composite_menu_build, rand_func = store_character_makeup_randomize, composite_area = "fingernails", 			camera = "hand left", }, 
  2286. 	} 
  2287.  
  2288. 	Store_common_sub_menu = makeup_menu 
  2289. end 
  2290.  
  2291. function store_character_personality_menu_fill() 
  2292.  
  2293. 	local personality_menu = { 
  2294. 		on_enter = 	store_character_movement_stop, 
  2295. 		{ label = "CUST_VOICE",						type = TYPE_BUTTON, on_sub_menu_fill = store_character_voice_menu_fill }, 
  2296. 		{ label = "CUST_MOVEMENT_COMPLIMENT", 	type = TYPE_BUTTON, on_sub_menu_fill = store_character_movement_show, anim_group = "compliment_style",  }, 
  2297. 		{ label = "CUST_MOVEMENT_TAUNT", 		type = TYPE_BUTTON, on_sub_menu_fill = store_character_movement_show, anim_group = "taunt_style", }, 
  2298. 	} 
  2299.  
  2300. 	Store_common_sub_menu = personality_menu 
  2301. end 
  2302.  
  2303. function store_character_main_menu_fill() 
  2304.  
  2305. 	local main_menu = { 
  2306. 		on_enter = store_character_return_main, 
  2307. 		{ label = "CUST_MENU_GLOBAL", 			type = TYPE_BUTTON, id = 2, on_sub_menu_fill = store_character_fill_global_menu, 		camera = "body", }, 
  2308. 		{ label = "CUST_MENU_FINE_TUNING", 		type = TYPE_BUTTON, id = 3, on_sub_menu_fill = store_character_face_menu_fill, 			camera = "head", }, 
  2309. 		{ label = "CUST_MENU_HAIR", 				type = TYPE_BUTTON, id = 4, on_sub_menu_fill = store_character_fill_hair_menu, 			camera = "head", }, 
  2310. 		{ label = "CUST_MENU_MAKEUP", 			type = TYPE_BUTTON, id = 5, on_sub_menu_fill = store_character_makeup_menu_fill, 		camera = "head", }, 
  2311. 		{ label = "CUST_MENU_MOVEMENT", 			type = TYPE_BUTTON, id = 6, on_sub_menu_fill = store_character_personality_menu_fill,	camera = "body", }, 
  2312. 		{ label = "STORE_CHARACTER_GALLERY", 	type = TYPE_BUTTON, 			 on_select = store_character_load_gallery, 										  	  }, 
  2313. 		{ label = "STORE_EXIT", 					type = TYPE_BUTTON, id = 7, on_select = store_character_exit 													  	  } 
  2314. 	} 
  2315. 	 
  2316. 	Menu_data = main_menu 
  2317. end 
  2318.  
  2319.  
  2320.  
  2321. ---------------------------------------------------------------------------  
  2322. -- Initialize Character Store 
  2323. --------------------------------------------------------------------------- 
  2324. function store_character_init() 
  2325.  
  2326. 	if pcr_is_plastic_surgeon() then 
  2327. 		Store_common_current_highlight_color = COLOR_STORE_CHARACTER_PRIMARY 
  2328. 	else 
  2329. 		Store_common_current_highlight_color = COLOR_SAINTS_PURPLE 
  2330. 	end 
  2331.  
  2332. 	Game_platform = game_get_platform() 
  2333. 	 
  2334. 	-- unload the full screen map to pillage memory 
  2335. 	pause_map_dump() 
  2336. 	 
  2337. 	-- Find doc handle 
  2338. 	Store_character_doc_handle = vint_document_find("store_character") 
  2339.  
  2340. 	-- Set up some callbacks for the common store script 
  2341. 	Store_common_allow_input_cb	= store_character_allow_input 
  2342. 	Store_common_populate_list_cb = store_character_populate_list 
  2343. 	Store_common_exit_cb				= store_character_exit 
  2344.  
  2345. 	-- Subscribe to the button presses we need, Input_tracker is created in store_common.lua 
  2346. 	Input_tracker:add_input("alt_select", "store_character_confirm_randomize", 50)	 
  2347. 	store_lock_controls() 
  2348. 	 
  2349. 	if Game_platform == "PC" then 
  2350. 		Hint_bar_mouse_input_tracker = Vdo_input_tracker:new() 
  2351. 	end 
  2352. 	 
  2353. 	--Setup Button Hints 
  2354. 	local hint_data = { 
  2355. 		{CTRL_MENU_BUTTON_B, "MENU_BACK"}, 
  2356. 	} 
  2357. 	Store_common_hint_bar:set_hints(hint_data)  
  2358. 	Store_common_hint_bar:set_visible(true)	 
  2359. 	 
  2360. 	if game_is_active_input_gamepad() then 
  2361. 		local hint_rotate_data = { 
  2362. 			{CTRL_BUTTON_RS, "STORE_ZOOM_ROTATE"}, 
  2363. 		} 
  2364. 		Store_common_rotate_hint:set_hints(hint_rotate_data) 	 
  2365. 		Store_common_rotate_hint:enable_text_shadow(true) 
  2366. 		if game_get_platform() ~= "PC" then 
  2367. 			Store_common_rotate_hint:set_visible(true) 
  2368. 		end 
  2369. 	end 
  2370. 	 
  2371. 	Store_header:set_visible(true)		 
  2372. 		 
  2373. 	-- Everything that is not in the popup so we can fade it when the popup is active 
  2374. 	Not_popup_grp = Vdo_base_object:new("not_popup_grp", 0, Store_common_doc_handle) 
  2375.  
  2376. 	-- Setup purchase popup 
  2377. 	Store_common_popup:set_visible(false) 
  2378. 	Store_common_popup:set_size(STORE_COMMON_LIST_SIZE, (LIST_BUTTON_HEIGHT * 5) + (LIST_BUTTON_SPACE * 5)) 
  2379. 	 
  2380. 	-- Setup Color grid 
  2381. 	Store_common_color_grid:set_visible(false) 
  2382. 	Store_common_color_grid:set_ui_screen("store_character") 
  2383. 	 
  2384. 	-- Setup Triangle Select 
  2385. 	Triangle_select = Vdo_triangle_select:new("store_character_triangle", 0, Store_character_doc_handle) 
  2386. 	Triangle_select:set_visible(false) 
  2387. 	 
  2388. 	-- Populate the areas and draw the first menu 
  2389. 	store_character_main_menu_fill() 
  2390. 	 
  2391. 	local is_plastic_surgeon = pcr_is_plastic_surgeon()		 
  2392. 	 
  2393. 	Store_character_confirm_randomize = is_plastic_surgeon 
  2394. 	 
  2395. 	-- If we're in the character lineup, change the text on the "exit" choice 
  2396. 	if is_plastic_surgeon == false then 
  2397. 		Menu_data[#Menu_data].label = "CUST_MENU_EXIT" 
  2398. 		Menu_data[#Menu_data].is_new = true 
  2399. 		Active_list:set_highlight_color(COLOR_SAINTS_PURPLE, COLOR_PLAYER_CREATION_SECONDARY, COLOR_PLAYER_CREATION_TERTIARY)		 
  2400. 	end 
  2401. 	 
  2402. 	-- Pass the table data to the megalist vdo. 
  2403. 	store_character_populate_list(Menu_data, 1) 
  2404. 	 
  2405. 	-- Hide background animations 
  2406. 	local player_creation_grp = Vdo_base_object:new("player_creation_grp", 0, Store_character_doc_handle) 
  2407. 	local iad_bg_grp = Vdo_base_object:new("iad_bg_grp", 0, Store_character_doc_handle) 
  2408. 	 
  2409. 	player_creation_grp:set_visible(false)	 
  2410. 	player_creation_grp:set_property("background", false) 
  2411. 	 
  2412. 	iad_bg_grp:set_visible(false) 
  2413.  
  2414. 	local color_primary, color_secondary, color_tertiary	 
  2415. 	 
  2416. 	--setup common anims and tweens to both stores 
  2417. 	Store_character_in_anim = Vdo_anim_object:new("store_common_in_anim", 0, Store_common_doc_handle) 
  2418. 	local list_x, list_y = Active_list:get_anchor() 
  2419. 	local grid_x, grid_y = Store_common_color_grid:get_anchor() 
  2420. 	Active_list:set_anchor(list_x, STORE_COMMON_LIST_NO_PRICE_Y) 
  2421. 	Store_common_color_grid:set_anchor(grid_x, STORE_COMMON_GRID_NO_PRICE_Y) 
  2422. 	 
  2423. 	-- reset this variable since we might be coming from IAD 
  2424. 	Store_lineup_is_loaded = true 
  2425. 	 
  2426. 	-- What store are we in? 
  2427. 	if is_plastic_surgeon == false then 
  2428. 	 
  2429. 		Store_character_current_state = LINEUP_STATE 
  2430. 	 
  2431. 		--Handle input for character line-up component 
  2432. 			 
  2433. 		-- Gets rid of the repsect meter in player creation 
  2434. 		Store_header:reformat_and_resize(true,435) 
  2435. 		 
  2436. 		-- Change colors for player creation 
  2437. 		color_primary = COLOR_SAINTS_PURPLE 
  2438. 		--color_primary = COLOR_PLAYER_CREATION_PRIMARY 
  2439. 		color_secondary = COLOR_PLAYER_CREATION_SECONDARY 
  2440. 		color_tertiary = COLOR_PLAYER_CREATION_TERTIARY		 
  2441.  
  2442. 		-- Set background animations  
  2443. 		Store_character_out_anim = Vdo_anim_object:new("store_common_anim_out", 0, Store_common_doc_handle)			 
  2444. 		Player_creation_bg_anim = Vdo_anim_object:new("player_creation_bg_anim", 0, Store_character_doc_handle)	 
  2445. 	 
  2446. 		vint_apply_start_values(Store_character_in_anim.handle) 
  2447. 		vint_apply_start_values(Player_creation_bg_anim.handle)		 
  2448. 		 
  2449. 		local twn_h = vint_object_find("new_tween1", Player_creation_bg_anim.handle) 
  2450. 		vint_set_property(twn_h, "end_event", "store_character_bg_anim_done") 
  2451. 		 
  2452. 		-- MWA - make call to unload the city loading bitmaps - there is weird case where 
  2453. 		-- we enter customization screen right as city is done loading and we need to unload them 
  2454. 		-- Honnigford fixed this, but they were unloading too early.  I'm moving the unload to 
  2455. 		-- be immediately before we need screen. 
  2456. 		--local city_load_doc_h = vint_document_find( "city_load" ) 
  2457. 		--if city_load_doc_h ~= 0 then 
  2458. 		--	city_load_hide_images( ) 
  2459. 		--end 
  2460. 		 
  2461. 		game_peg_load_with_cb("store_character_line_up_is_loaded", 1, "ui_bms_store_line_up") 
  2462. 		Store_lineup_is_loaded = false 
  2463. 		 
  2464. 		Active_list:set_visible(false) 
  2465. 		Store_header:set_visible(false) 
  2466. 		Store_common_rotate_hint:set_visible(false) 
  2467. 		 
  2468. 		vint_set_property(vint_object_find("police_logo"), "visible", false)		 
  2469. 		 
  2470. 		-- Change the top level exit callback so that we go back to the character lineup instead of the game. 
  2471. 		Store_common_exit_cb = store_character_lineup_return_confirm 
  2472. 		 
  2473. 		-- Change hint text 
  2474. 		local hint_data = { 
  2475. 			{CTRL_MENU_BUTTON_A, "CUST_CHOOSE_CHARACTER"}, 
  2476. 		} 
  2477. 		Store_common_hint_bar:set_hints(hint_data) 		 
  2478. 		 
  2479. 		character_enable_mouse_drag(false) 
  2480. 		 
  2481. 	else	 
  2482. 	 
  2483. 		Store_character_current_state = CUSTOMIZATION_STATE 
  2484. 	 
  2485. 		-- Change colors for store character 
  2486. 		color_primary = COLOR_STORE_CHARACTER_PRIMARY 
  2487. 		color_secondary = COLOR_STORE_CHARACTER_SECONDARY 
  2488. 		color_tertiary = COLOR_STORE_CHARACTER_TERTIARY	 
  2489. 		 
  2490. 		-- Set animations  
  2491. 		Iad_bg_anim = Vdo_anim_object:new("iad_bg_anim", 0, Store_character_doc_handle)	 
  2492. 		Iad_logo_anim = Vdo_anim_object:new("iad_logo_anim", 0, Store_character_doc_handle)	 
  2493. 		 
  2494. 		-- Set tweens 
  2495. 		local end_event_twn = Vdo_tween_object:new("end_event_twn", Store_character_in_anim.handle) 
  2496. 		end_event_twn:set_end_event("store_unlock_controls") 
  2497. 		 
  2498. 		local iad_end_event_twn = Vdo_tween_object:new("iad_bg_end_event",Iad_bg_anim.handle,Store_character_doc_handle) 
  2499. 		iad_end_event_twn:set_end_event("store_loop_bg_anims") 
  2500. 		 
  2501. 		local twn_h = vint_object_find("new_tween23", Iad_bg_anim.handle) 
  2502. 		vint_set_property(twn_h, "end_event", "store_character_bg_anim_done") 
  2503. 	 
  2504. 		vint_apply_start_values(Iad_bg_anim.handle) 
  2505. 		vint_apply_start_values(Store_character_in_anim.handle) 
  2506. 		vint_apply_start_values(Iad_logo_anim.handle) 
  2507. 		 
  2508. 		ui_audio_post_event("enter_image_as_designed") 
  2509. 		 
  2510. 		-- Stream store graphic then play animation in callback 
  2511. 		game_peg_load_with_cb("store_character_bg_is_loaded", 1, "ui_bms_store_iad") 
  2512. 		 
  2513. 		character_enable_mouse_drag(true) 
  2514. 	end 
  2515. 	 
  2516. 	-- Set colors 
  2517. 	Store_header:set_color(color_primary, color_secondary, color_tertiary)		 
  2518. 	Active_list:set_highlight_color(color_primary, color_secondary, color_tertiary)		 
  2519. 	Store_common_color_grid:set_highlight_color(color_primary, color_secondary, color_tertiary)		 
  2520. 	Triangle_select:set_highlight_color(color_primary, color_secondary, color_tertiary)	 
  2521. 	Store_common_popup:set_color(color_primary, color_secondary, color_tertiary)	 
  2522. 	 
  2523. 	-- Set initial titles 
  2524. 	if pcr_is_plastic_surgeon() == false then 
  2525. 		Store_header:push_title(nil, "STORE_CHOOSE_A_CATEGORY") 
  2526. 	else 
  2527. 		Store_header:set_title() 
  2528. 	end 
  2529. 	 
  2530. end 
  2531.  
  2532. function store_lock_controls() 
  2533.  
  2534. 	Input_tracker:subscribe(false) 
  2535. 	store_character_enable_mouse(false) 
  2536. 	if Input_tracker_body_morph_select ~= nil then 
  2537. 		Input_tracker_body_morph_select:subscribe(false) 
  2538. 	end 
  2539. end 
  2540.  
  2541. function store_unlock_controls() 
  2542.  
  2543. 	Input_tracker:subscribe(true) 
  2544. 	 
  2545. 	if Current_tier == BUILD_TIER then 
  2546. 		if Input_tracker_body_morph_select ~= nil then 
  2547. 			Input_tracker_body_morph_select:subscribe(true) 
  2548. 		end 
  2549. 		if Hint_bar_mouse_input_tracker ~= -1 then 
  2550. 			Hint_bar_mouse_input_tracker:subscribe(true) 
  2551. 		end 
  2552. 	else 
  2553. 		store_character_enable_mouse(true) 
  2554. 	end 
  2555. end 
  2556.  
  2557. function store_loop_bg_anims(tween_handle) 
  2558. 	local animation = vint_object_parent(tween_handle) 
  2559. 	 
  2560. 	-- Loop bg anim starting at frame 40 
  2561. 	lua_play_anim(animation, -1) 
  2562. end 
  2563.  
  2564. -- Callback for when background and related images for lineup are loaded. 
  2565. -- 
  2566. function store_character_line_up_is_loaded() 
  2567.  
  2568. 	local player_creation_grp = Vdo_base_object:new("player_creation_grp", 0, Store_character_doc_handle) 
  2569. 	player_creation_grp:set_visible(true) 
  2570. 	 
  2571. 	image_streamer_add_image("ui_store_lineup_mugshot_01") 
  2572. 	image_streamer_add_image("ui_store_lineup_mugshot_02") 
  2573. 	image_streamer_add_image("ui_store_lineup_mugshot_03") 
  2574. 	image_streamer_add_image("ui_store_lineup_mugshot_04") 
  2575. 	image_streamer_add_image("ui_store_lineup_mugshot_05") 
  2576. 	image_streamer_add_image("ui_store_lineup_mugshot_06") 
  2577. 	image_streamer_add_image("ui_store_lineup_mugshot_07") 
  2578. 	image_streamer_add_image("ui_store_lineup_mugshot_08") 
  2579. 	image_streamer_add_image("ui_store_lineup_mugshot_09")		 
  2580.  
  2581. 	local susan = Vdo_susan:new("susan", 0, Store_character_doc_handle, "store_character.lua", "Susan_object") 
  2582. 	Susan_object = susan 
  2583. 	 
  2584. 	Susan_object:set_visible(false) 
  2585.  
  2586. 	image_streamer_start_streaming(STORE_CHARACTER_NUM_LINEUP_IMAGES - 1, STORE_CHARACTER_NUM_LINEUP_IMAGES_LOADED, store_character_lineup_images_loaded) 
  2587.  
  2588. 	-- Turn off customization inputs 
  2589. 	store_lock_controls() 
  2590. 	 
  2591. 	-- subscribe to inputs for the character lineup 
  2592. 	Lineup_input_tracker = Vdo_input_tracker:new() 
  2593. 	Lineup_input_tracker:add_input("nav_left", "store_character_lineup_nav", 50) 
  2594. 	Lineup_input_tracker:add_input("nav_right", "store_character_lineup_nav", 50)	 
  2595. 	Lineup_input_tracker:add_input("select", "store_character_lineup_select", 50)		 
  2596. 	Lineup_input_tracker:subscribe(true) 
  2597. 	 
  2598. 	Susan_mouse_area_img_h = vint_object_find("susan_mouse_area_img", 0 ,Store_character_doc_handle) 
  2599. 	 
  2600. 	if game_get_platform() == "PC" then		 
  2601. 		Lineup_mouse_input_tracker = Vdo_input_tracker:new()		 
  2602. 		Lineup_mouse_input_tracker:add_mouse_input("mouse_click", "store_character_mouse_click", 25, Susan_mouse_area_img_h) 
  2603. 		Lineup_mouse_input_tracker:add_mouse_input("mouse_click", "store_character_mouse_click", 50, Susan_object.arrow_left.handle) 
  2604. 		Lineup_mouse_input_tracker:add_mouse_input("mouse_click", "store_character_mouse_click", 50, Susan_object.arrow_right.handle) 
  2605. 		Lineup_mouse_input_tracker:add_mouse_input("mouse_move", "store_character_mouse_move", 50, Susan_object.arrow_left.handle) 
  2606. 		Lineup_mouse_input_tracker:add_mouse_input("mouse_move", "store_character_mouse_move", 50, Susan_object.arrow_right.handle) 
  2607. 		Lineup_mouse_input_tracker:subscribe(true) 
  2608. 	end 
  2609. 	store_character_enable_mouse_split(false, true, true) 
  2610. 	Current_tier = LINEUP_TIER 
  2611.  
  2612. 	Store_lineup_is_loaded = true 
  2613. 	 
  2614. end 
  2615.  
  2616. -- Callback for when lineup images are done loading. 
  2617. -- 
  2618. function store_character_lineup_images_loaded() 
  2619. 	if Store_character_lineup_init_complete == false then 
  2620. 		Store_character_in_anim:play(0) 
  2621. 		Player_creation_bg_anim:play(0) 
  2622. 		 
  2623. 		Susan_object:set_images(image_streamer_get_images())		 
  2624. 		Susan_object:play_intro() 
  2625. 		Susan_object:set_visible(true) 
  2626.  
  2627. 		Store_character_lineup_init_complete = true 
  2628. 		 
  2629. 		store_character_lineup_loaded() 
  2630. 	end 
  2631. end 
  2632.  
  2633. function store_character_is_lineup_loaded() 
  2634. 	return Store_lineup_is_loaded 
  2635. end 
  2636.  
  2637. function store_character_bg_is_loaded() 
  2638. 	Store_character_in_anim:play(0) 
  2639. 	Iad_bg_anim:play(0) 
  2640. 	Iad_logo_anim:play(0) 
  2641. 	 
  2642. 	-- Unhide background  
  2643. 	local iad_bg_grp = Vdo_base_object:new("iad_bg_grp", 0, Store_character_doc_handle) 
  2644. 	iad_bg_grp:set_visible(true) 
  2645. end 
  2646.  
  2647. ---------------------------------------------------------------------------  
  2648. -- Cleanup Character Store 
  2649. --------------------------------------------------------------------------- 
  2650. function store_character_cleanup() 
  2651.  
  2652. 	-- we needed to add a second temporary persona to the player in pcr_set_voice.  This needs to be cleared out on exit 
  2653. 	pcr_cleanup_player_voice() 
  2654.  
  2655. 	-- Nuke all button subscriptions 
  2656. 	store_lock_controls() 
  2657. 	 
  2658. 	game_peg_unload("ui_bms_pcr_tri")	 
  2659. 	game_peg_unload("ui_bms_pcr_skin")	 
  2660. 	game_peg_unload("ui_bms_pcr_eyes")	 
  2661. 	game_peg_unload("ui_bms_pcr_hair")	 
  2662. 	game_peg_unload("ui_bms_store_iad")		 
  2663. 	game_peg_unload("ui_bms_store_line_up") 
  2664. 	 
  2665. 	-- Remove any images from the character lineup 
  2666. 	image_streamer_end_streaming() 
  2667. 	image_streamer_remove_all_images()	 
  2668. 	 
  2669. 	-- reload the full screen map 
  2670. 	pause_map_restore() 
  2671. 	 
  2672. 	character_enable_mouse_drag(false) 
  2673. 	 
  2674. 	-- Some things need to be cleaned up right away when a store doc is unloading, particular disabled inputs which have 
  2675. 	-- callbacks to the script that is unloading. 
  2676. 	store_common_cleanup_current_store()	 
  2677. 	 
  2678. 	if Online_check_thread ~= -1 then 
  2679. 		thread_kill(Online_check_thread) 
  2680. 	end		 
  2681. 	 
  2682. 	if Store_character_clothing_load_thread ~= -1 then 
  2683. 		thread_kill(Store_character_clothing_load_thread) 
  2684. 	end		 
  2685. end 
  2686.  
  2687. -- Populate the active megalist menu, and hide the previous menu 
  2688. -- 
  2689. -- list_data: 		this table contains the data to populate the megalist 
  2690. -- current_index: 	the current index in the menu that's selected 
  2691. -- 
  2692. function store_character_populate_list(list_data, current_index) 
  2693. 	Active_list:draw_items(list_data, current_index, STORE_COMMON_LIST_SIZE, 12, SCALE_FONT_STORE_CHARACTER_LIST) 
  2694. 	Active_list:set_visible(true) 
  2695. 	 
  2696. 	-- Update the hint bar 
  2697. 	 
  2698. 	-- Are we on the main screen? 
  2699. 	local back_hint 
  2700. 	if store_common_stack_get_menu() ~= nil then 
  2701. 		back_hint = {CTRL_MENU_BUTTON_B, "MENU_BACK"} 
  2702. 	else 
  2703. 		-- Are we in plastic surgeon or character creation? 
  2704. 		if pcr_is_plastic_surgeon() then 
  2705. 			back_hint = {CTRL_MENU_BUTTON_B, "STORE_EXIT"}		 
  2706. 		else 
  2707. 			back_hint = {CTRL_MENU_BUTTON_B, "MENU_BACK"} 
  2708. 		end 
  2709. 	end 
  2710. 	 
  2711. 	-- build hint data 
  2712. 	local hint_data = {} 
  2713. 	local hint_count = 0 
  2714. 	 
  2715. 	-- If all the items in the menu are sliders (no submenus) then add an "accept" hint 
  2716. 	-- restore all to original values 
  2717. 	local has_buttons = false 
  2718. 	for i = 1, #list_data do 
  2719. 		if list_data[i].type == TYPE_BUTTON or list_data[i].type == TYPE_TOGGLE_COLOR then 
  2720. 			has_buttons = true 
  2721. 		end 
  2722. 	end 
  2723. 	 
  2724. 	if has_buttons == false then 
  2725. 		hint_count = hint_count + 1 
  2726. 		hint_data[hint_count] = {CTRL_MENU_BUTTON_A, "PAUSE_MENU_ACCEPT"} 
  2727. 	end 
  2728. 	 
  2729. 	-- add back choice 
  2730. 	hint_count = hint_count + 1 
  2731. 	hint_data[hint_count] = back_hint 
  2732. 	 
  2733. 	-- Is there a randomize function? 
  2734. 	if list_data[1].rand_func ~= nil then 
  2735. 		hint_count = hint_count + 1 
  2736. 		hint_data[hint_count] = {CTRL_BUTTON_X, "PLAYER_CREATION_RANDOMIZE"}  
  2737. 	end 
  2738. 	 
  2739. 	Store_common_hint_bar:set_hints(hint_data) 
  2740. 	 
  2741. 	if Game_platform == "PC" then 
  2742. 		Mouse_input_tracker:remove_all() 
  2743. 		Hint_bar_mouse_input_tracker:remove_all() 
  2744. 		 
  2745. 		Active_list:set_store("store_character") 
  2746. 		Active_list:add_mouse_inputs("store_common", Mouse_input_tracker) 
  2747. 		Store_common_hint_bar:add_mouse_inputs("store_character", Hint_bar_mouse_input_tracker) 
  2748. 		store_character_enable_mouse(true) 
  2749. 	end 
  2750. end 
  2751.  
  2752. -- Callback that's called when asynchronous image loading is complete 
  2753. -- 
  2754. function store_character_set_logo() 
  2755. 	-- TODO 
  2756. end 
  2757.  
  2758. -- Handle navigating grid 
  2759. function store_character_grid_nav(event, value) 
  2760.  
  2761. 	if event == "nav_up" then	 
  2762. 		Store_common_color_grid:move_cursor(-2)	 
  2763. 	elseif event == "nav_down" then 
  2764. 		Store_common_color_grid:move_cursor(2) 
  2765. 	elseif event == "nav_left" then 
  2766. 		Store_common_color_grid:move_cursor(-1) 
  2767. 	elseif event == "nav_right" then 
  2768. 		Store_common_color_grid:move_cursor(1) 
  2769. 	elseif event == "mouse_move" then 
  2770. 		-- value contains the target_handle in this case 
  2771. 		local new_index = Store_common_color_grid:get_data_index(value) 
  2772. 		if new_index ~= 0 then 
  2773. 			Store_common_color_grid:set_selection(new_index) 
  2774. 			Store_common_color_grid:move_cursor(0, false, true) 
  2775. 		end 
  2776. 	 
  2777. 	else 
  2778. 		--do nothing 
  2779. 	end 
  2780. end 
  2781.  
  2782. function store_character_confirm_randomize() 
  2783.  
  2784. 	-- Is the active list visible? 
  2785. 	if Active_list:get_visible() == false then 
  2786. 		return 
  2787. 	end 
  2788.  
  2789. 	-- Does a randomization function exist for this data? 
  2790. 	local current_index = Active_list:get_selection() 
  2791.  
  2792. 	if Menu_data[current_index].rand_func == nil then 
  2793. 		return 
  2794. 	end 
  2795.  
  2796. 	-- if we don't need to warn the player first, just randomize 
  2797. 	if Store_character_confirm_randomize == false then 
  2798. 		 
  2799. 		game_UI_audio_play("UI_Main_Menu_Select") 
  2800. 		 
  2801. 		-- Do the randomization 
  2802. 		local current_index = Active_list:get_selection() 
  2803. 		Menu_data[current_index].rand_func(Menu_data[current_index]) 
  2804. 		return 
  2805. 	end 
  2806. 	 
  2807. 	store_character_enable_mouse(false) 
  2808. 	 
  2809. 	Store_common_popup:populate_list(Yes_no_choices, 2, STORE_COMMON_LIST_SIZE, 2)	 
  2810. 	Store_common_popup:set_title("RANDOM_WARNING_HEADING") 
  2811. 	Store_common_popup:set_text("RANDOM_WARNING_BODY")		 
  2812. 	Store_common_popup:nav_enable(true, "store_character_randomize_final", "store_character_popup_nav") 
  2813. 	Not_popup_grp:set_alpha(.5)	 
  2814. 	Active_list:set_visible(false) 
  2815. 	 
  2816. end 
  2817.  
  2818. function store_character_randomize_final(event) 
  2819. 	Store_common_popup:nav_enable(false, nil, nil) 
  2820. 	Not_popup_grp:set_alpha(1) 
  2821. 	Active_list:set_visible(true) 
  2822. 	 
  2823. 	-- The user hit the B button and are cancelling the purchase 
  2824. 	-- This is redundant to selecting "No" in the list 
  2825. 	if event == "back" then 
  2826. 		game_UI_audio_play("UI_Main_Menu_Nav_Back") 
  2827. 		store_character_enable_mouse(true) 
  2828. 		return 
  2829. 	end 
  2830. 	 
  2831. 	game_UI_audio_play("UI_Main_Menu_Select")	 
  2832. 	 
  2833. 	-- Did we select yes?  This assumes yes is the first item 
  2834. 	if Store_common_popup:get_selected_data() ~= 1 then 
  2835. 		store_character_enable_mouse(true) 
  2836. 		return 
  2837. 	end 
  2838.  
  2839. 	-- Do the randomization 
  2840. 	Store_character_confirm_randomize = false 
  2841. 	local current_index = Active_list:get_selection() 
  2842. 	Menu_data[current_index].rand_func(Menu_data[current_index]) 
  2843. 	store_character_enable_mouse(true) 
  2844. 	 
  2845. 	-- We'll now need to confirm if they want to throw the changes out 
  2846. 	Store_character_cancel_confirm_needed = true 
  2847. end 
  2848.  
  2849. function store_character_popup_nav(event, value) 
  2850. 	 
  2851. 	if event == "mouse_move" then 
  2852. 		vint_set_mouse_cursor("") 
  2853. 	end 
  2854. 	 
  2855. 	if event == "nav_up" then	 
  2856. 		Store_common_popup.list:move_cursor(-1)	 
  2857. 	elseif event == "nav_down" then 
  2858. 		Store_common_popup.list:move_cursor(1) 
  2859. 	elseif event == "mouse_move" then 
  2860. 		-- value contains the target_handle in this case 
  2861. 		local new_index = Store_common_popup.list:get_button_index(value) 
  2862. 		if new_index ~= 0 then 
  2863. 			Store_common_popup.list:set_selection(new_index) 
  2864. 			Store_common_popup.list:move_cursor(0, true) 
  2865. 		end 
  2866. 		 
  2867. 	else 
  2868. 		--do nothing 
  2869. 	end 
  2870. 		 
  2871. end 
  2872.  
  2873. function store_character_play_exit_anim() 
  2874. 	 
  2875. 	ui_audio_post_event("UI_Store_Exit") 
  2876. 	 
  2877. 	local anim_out = Vdo_anim_object:new("iad_anim_out", 0, Store_character_doc_handle) 
  2878. 	local end_event_twn = Vdo_tween_object:new("iad_end_event", anim_out.handle) 
  2879. 	 
  2880. 	end_event_twn:set_end_event("store_unload_doc") 
  2881. 	 
  2882. 	anim_out:play(0) 
  2883. 	store_common_play_anim_out() 
  2884.  
  2885. end 
  2886.  
  2887. function store_unload_doc() 
  2888.  
  2889. 	vint_document_unload() 
  2890. 	 
  2891. end 
  2892.  
  2893.  
  2894. -- ===================================== 
  2895. --       Mouse Specific Functions 
  2896. -- ===================================== 
  2897.  
  2898. -- Subscribes or removes subscriptions to all mouse input trackers 
  2899. -- 
  2900. function store_character_enable_mouse(enable, set_hint_bar) 
  2901. 	if Game_platform == "PC" and enable ~= nil then 
  2902. 		if Mouse_input_tracker ~= 0 then 
  2903. 			Mouse_input_tracker:subscribe(enable) 
  2904. 		end 
  2905. 		 
  2906. 		Active_list:enable_toggle_input(enable) 
  2907. 		 
  2908. 		-- The hint bar is defaulted to be subscribed with the other input trackers unless specified 
  2909. 		if set_hint_bar == nil then 
  2910. 			set_hint_bar = true 
  2911. 		end 
  2912. 		if Hint_bar_mouse_input_tracker ~= -1 and set_hint_bar then 
  2913. 			Hint_bar_mouse_input_tracker:subscribe(enable) 
  2914. 		end 
  2915. 	end 
  2916. end 
  2917.  
  2918. -- Subscribes or removes subscriptions to specific mouse input trackers 
  2919. -- 
  2920. function store_character_enable_mouse_split(enable_active_list, enable_hint_bar, enable_lineup) 
  2921. 	if Game_platform == "PC" then 
  2922. 		if Mouse_input_tracker ~= nil then 
  2923. 			Mouse_input_tracker:subscribe(enable_active_list) 
  2924. 		end 
  2925. 		if Hint_bar_mouse_input_tracker ~= -1 then 
  2926. 			Hint_bar_mouse_input_tracker:subscribe(enable_hint_bar) 
  2927. 		end 
  2928. 		if Lineup_mouse_input_tracker ~= nil then 
  2929. 			Lineup_mouse_input_tracker:subscribe(enable_lineup) 
  2930. 		end 
  2931. 	end 
  2932. end 
  2933.  
  2934. function store_character_mouse_click(event, target_handle, mouse_x, mouse_y) 
  2935. 	-- Check if the user clicked on the hint bar 
  2936. 	local hint_index = Store_common_hint_bar:get_hint_index(target_handle) 
  2937. 	if hint_index ~= 0 then 
  2938. 		-- Depending on the current tier, clicking on the "Back" button on the hint bar needs 
  2939. 		-- to call different functions 
  2940. 		if Store_common_hint_bar.hint_data[hint_index][1] == CTRL_BUTTON_X then 
  2941. 			store_character_confirm_randomize() 
  2942. 		elseif Current_tier == LINEUP_TIER and Store_character_current_state == LINEUP_STATE then 
  2943. 			store_character_lineup_select(event) 
  2944. 		elseif Store_common_hint_bar.hint_data[hint_index][1] == CTRL_MENU_BUTTON_B then 
  2945. 			if Current_tier == BUILD_TIER then 
  2946. 				store_character_morph_revert_confirm() 
  2947. 			elseif Current_tier == SKIN_COLOR_TIER then 
  2948. 				store_character_skin_color_selected("back") 
  2949. 			elseif Current_tier == EYE_COLOR_TIER then 
  2950. 				store_character_eye_color_selected("back") 
  2951. 			elseif Current_tier == HAIR_COLOR_TIER then 
  2952. 				store_character_hair_color_selected("back") 
  2953. 			elseif Current_tier == MAKEUP_COLOR_TIER then 
  2954. 				store_character_composite_color_select("back") 
  2955. 			else --Current tier == MENU_TIER 
  2956. 				store_common_button_b() 
  2957. 			end 
  2958. 		elseif Store_common_hint_bar.hint_data[hint_index][1] == CTRL_MENU_BUTTON_A then 
  2959. 			store_common_button_a() 
  2960. 		end 
  2961. 		 
  2962. 		return 
  2963. 	end 
  2964. 	 
  2965. 	-- Check if the user clicked on a susan arrow 
  2966. 	if Susan_object ~= nil and Susan_object ~= -1 then 
  2967. 		if target_handle == Susan_object.arrow_left.handle then 
  2968. 			-- Navigate left 
  2969. 			store_character_lineup_nav("nav_left") 
  2970. 		elseif target_handle == Susan_object.arrow_right.handle then 
  2971. 			-- Navigate right 
  2972. 			store_character_lineup_nav("nav_right") 
  2973. 		elseif target_handle == Susan_mouse_area_img_h then 
  2974. 			-- Select character from lineup 
  2975. 			if Current_tier == LINEUP_TIER then 
  2976. 				store_character_lineup_select(event)	 
  2977. 			end 
  2978. 		end 
  2979. 	end 
  2980. 	 
  2981. 	-- Check if the user clicked on the confirm button or triangle on the build screen 
  2982. 	if Left_stick_input_thread ~= -1 and Triangle_select_button_handle == target_handle then 
  2983. 		store_character_morph_select() 
  2984. 	end 
  2985. 	 
  2986. 	local triangle_handle = vint_object_find("triangle_base", Triangle_select.handle) 
  2987. 	if Left_stick_input_thread ~= -1 and triangle_handle == target_handle then 
  2988. 		Mouse_x = mouse_x 
  2989. 		Mouse_y = mouse_y 
  2990. 	end 
  2991. end 
  2992.  
  2993. function store_character_mouse_move(event, target_handle) 
  2994.  
  2995. 	vint_set_mouse_cursor("") 
  2996. 	store_common_mouse_zoom(0.0) 
  2997.  
  2998. 	-- Reset highlights 
  2999. 	Store_common_hint_bar:set_highlight(0) 
  3000. 	Active_list:highlight_left_arrow(false) 
  3001. 	Active_list:highlight_right_arrow(false) 
  3002. 	 
  3003. 	-- Check if the user is over the hint bar 
  3004. 	local hint_index = Store_common_hint_bar:get_hint_index(target_handle) 
  3005. 	if hint_index ~= 0 then 
  3006. 		if pcr_is_plastic_surgeon() then 
  3007. 			Store_common_hint_bar:set_highlight(hint_index, Store_common_current_highlight_color) 
  3008. 		else 
  3009. 			Store_common_hint_bar:set_highlight(hint_index, COLOR_SAINTS_PURPLE) --COLOR_PLAYER_CREATION_PRIMARY) 
  3010. 		end 
  3011. 	end 
  3012. 	 
  3013. 	-- Check if the user is over a button on the list 
  3014. 	local old_index = Active_list:get_selection() 
  3015. 	local new_index = Active_list:get_button_index(target_handle) 
  3016. 	if new_index ~= 0 and new_index ~= old_index then 
  3017. 		Active_list:set_selection(new_index) 
  3018. 		Active_list:move_cursor(0, true) 
  3019. 		 
  3020. 		-- If the item has a callback for navigation, do it (such as putting clothes on) 
  3021. 		local data_item = Active_list:return_selected_data() 
  3022. 		if data_item.on_nav ~= nil then 
  3023. 			data_item.on_nav(data_item) 
  3024. 		end 
  3025. 	end 
  3026. 	 
  3027. 	-- Check if the user is over the toggle/slider arrows 
  3028. 	local current_selection = Active_list:return_selected_data() 
  3029. 	if current_selection.type == TYPE_SLIDER then 
  3030. 		if Active_list:is_left_arrow(target_handle) then 
  3031. 			Active_list:highlight_left_arrow(true) 
  3032. 		elseif Active_list:is_right_arrow(target_handle) then 
  3033. 			Active_list:highlight_right_arrow(true) 
  3034. 		end 
  3035. 	end 
  3036. 	 
  3037. 	-- Custom highlighting for the select build button 
  3038. 	vint_set_property(Triangle_select_text_handle, "tint", 0, 0, 0) 
  3039. 	if Left_stick_input_thread ~= -1 and Triangle_select_button_handle == target_handle then 
  3040. 		vint_set_property(Triangle_select_text_handle, "tint", 220/255, 220/255, 220/255) 
  3041. 	end 
  3042. 	 
  3043. 	local SUSAN_ARROW_SCALE = 1.5 
  3044. 	-- Custom highlighting for the lineup arrows 
  3045. 	if Susan_object ~= nil and Susan_object ~= -1 then 
  3046. 		Susan_object.arrow_left:set_scale(SUSAN_ARROW_SCALE, SUSAN_ARROW_SCALE) 
  3047. 		Susan_object.arrow_right:set_scale(SUSAN_ARROW_SCALE, SUSAN_ARROW_SCALE) 
  3048. 		if target_handle == Susan_object.arrow_left.handle then 
  3049. 			Susan_object.arrow_left:set_scale(SUSAN_ARROW_SCALE * 1.15, SUSAN_ARROW_SCALE * 1.15) 
  3050. 		elseif target_handle == Susan_object.arrow_right.handle then 
  3051. 			Susan_object.arrow_right:set_scale(SUSAN_ARROW_SCALE * 1.15, SUSAN_ARROW_SCALE * 1.15) 
  3052. 		end 
  3053. 	end 
  3054. end 
  3055.  
  3056. function store_character_mouse_scroll(event, target_handle, mouse_x, mouse_y, scroll_lines) 
  3057. 	if scroll_lines ~= 0 then 
  3058. 		if Store_common_color_grid.bg.handle == target_handle then 
  3059. 			Store_common_color_grid:scroll_list(scroll_lines * -1) 
  3060. 		end 
  3061. 	end 
  3062. end 
  3063.  
  3064. function store_character_mouse_drag(event, target_handle, mouse_x, mouse_y) 
  3065. 	if Store_common_color_grid.scrollbar.tab.handle == target_handle then 
  3066. 		local new_start_index = Store_common_color_grid.scrollbar:drag_scrolltab(mouse_y, Store_common_color_grid.rows - (Store_common_color_grid.max_height - 1)) 
  3067. 		Store_common_color_grid:scroll_list(0, new_start_index) 
  3068. 		return 
  3069. 	end 
  3070. 	 
  3071. 	-- Set the mouse's position to start the update 
  3072. 	local triangle_handle = vint_object_find("triangle_base", Triangle_select.handle) 
  3073. 	if Left_stick_input_thread ~= -1 and triangle_handle == target_handle then 
  3074. 		Mouse_x = mouse_x 
  3075. 		Mouse_y = mouse_y 
  3076. 	end 
  3077. end 
  3078.  
  3079. function store_character_mouse_drag_release(event, target_handle, mouse_x, mouse_y) 
  3080. 	-- Rebuild the mouse tracker and snap the scrolltab to the index's notch 
  3081. 	if Store_common_color_grid.scrollbar.tab.handle == target_handle then 
  3082. 		local start_row = Store_common_color_grid:get_visible_rows() 
  3083. 		Store_common_color_grid.scrollbar:release_scrolltab(start_row, Store_common_color_grid.rows - (Store_common_color_grid.max_height - 1)) 
  3084. 		Store_common_color_grid:update_mouse_inputs() 
  3085. 		return 
  3086. 	end 
  3087. 	 
  3088. 	-- Reset the mouse's tracked position, so the build screen doesn't constantly update 
  3089. 	local triangle_handle = vint_object_find("triangle_base", Triangle_select.handle) 
  3090. 	if triangle_handle == target_handle then 
  3091. 		Mouse_x = -1 
  3092. 		Mouse_y = -1 
  3093. 	end 
  3094. end 
  3095.  
  3096. -- Navigate left and right events are handled for the character lineup here. 
  3097. -- 
  3098. -- event: only accepts left and right navs. 
  3099. -- 
  3100. function store_character_lineup_nav(event) 
  3101. 	if event == "nav_left" then 
  3102. 		if not image_streamer_is_stream_in_progress() and not Susan_object:is_in_progress() and Susan_object:get_index() > 1 then 
  3103. 			Susan_object:move_right() 
  3104. 			game_UI_audio_play("UI_Main_Menu_Nav_Page_Right") 
  3105. 			if image_streamer_nav_index(-1) == false then 
  3106. 				assert_msg(false, "nav_left failed") 
  3107. 			end 
  3108. 		end 
  3109. 	elseif event == "nav_right" then 
  3110. 		if not image_streamer_is_stream_in_progress() and not Susan_object:is_in_progress() and Susan_object:get_index() < STORE_CHARACTER_NUM_LINEUP_IMAGES then	 
  3111. 			Susan_object:move_left() 
  3112. 			game_UI_audio_play("UI_Main_Menu_Nav_Page_Right") 
  3113. 			if image_streamer_nav_index(1) == false then 
  3114. 				assert_msg(false, "nav_right failed") 
  3115. 			end 
  3116. 		end 
  3117. 	else 
  3118. 		--do nothing 
  3119. 	end 
  3120. 	 
  3121. 	local index = Susan_object:get_index() 
  3122. 	 
  3123. 	if index == STORE_CHARACTER_NUM_LINEUP_IMAGES then 
  3124. 		if index ~= Prev_index then 
  3125. 			Susan_object:show_text("LINEUP_DOWNLOAD_CHARACTER", "LINEUP_DOWNLOAD_CHARACTER_DESC", true) 
  3126. 		end 
  3127. 	else 
  3128. 		Susan_object:show_text(nil, nil, false) 
  3129. 	end 
  3130. 	 
  3131. 	Prev_index = index 
  3132. 	 
  3133. end 
  3134.  
  3135. -- The player has selected a picture from the character lineup, and this function will take us to the character customization screen. 
  3136. -- 
  3137. function store_character_lineup_select(event) 
  3138.  
  3139. 	local new_state 
  3140. 	local index = Susan_object:get_index() 
  3141. 	 
  3142. 	Store_character_current_state = LINEUP_STATE	 
  3143. 	 
  3144. 	-- Special case: the last choice is for the Agora character gallery choice 
  3145. 	if index == STORE_CHARACTER_NUM_LINEUP_IMAGES then 
  3146. 		Store_character_new_state_on_validation = GALLERY_DOWNLOAD_STATE 
  3147. 		Online_check_thread = thread_new("store_character_check_online_for_gallery") 
  3148. 	else 
  3149. 		store_character_change_state(CUSTOMIZATION_STATE) 
  3150. 	end 
  3151. end 
  3152.  
  3153. -- Player selected a preset with the "select" button.  We need to confirm if they really want to do this first. 
  3154. -- 
  3155. function store_character_lineup_return_confirm() 
  3156.  
  3157. 	store_character_enable_mouse(false) 
  3158.  
  3159. 	Store_common_popup:populate_list(Yes_no_choices, 2, STORE_COMMON_LIST_SIZE, 2)	 
  3160. 	Store_common_popup:set_title("MENU_TITLE_WARNING") 
  3161. 	Store_common_popup:set_text("LINEUP_WARNING_BODY")		 
  3162. 	Store_common_popup:nav_enable(true, "store_character_lineup_return_confirm2", "store_character_popup_nav") 
  3163. 	Not_popup_grp:set_alpha(.5) 
  3164. 	Active_list:set_visible(false) 
  3165. 	 
  3166. 	return true 
  3167. end 
  3168.  
  3169. function store_character_lineup_return_confirm2(event) 
  3170. 	Store_common_popup:nav_enable(false, nil, nil) 
  3171. 	Not_popup_grp:set_alpha(1) 
  3172. 	Active_list:set_visible(true) 
  3173. 	 
  3174. 	-- The user hit the B button and cancelled the change 
  3175. 	-- This is redundant to selecting "No" in the list 
  3176. 	if event == "back" then 
  3177. 		game_UI_audio_play("UI_Main_Menu_Nav_Back") 
  3178. 		store_character_enable_mouse(true) 
  3179. 		return 
  3180. 	end 
  3181. 	 
  3182. 	game_UI_audio_play("UI_Main_Menu_Select")	 
  3183. 	 
  3184. 	-- Did we select yes?  This assumes yes is the first item 
  3185. 	if Store_common_popup:get_selected_data() ~= 1 then 
  3186. 		store_character_enable_mouse(true) 
  3187. 		return 
  3188. 	end 
  3189.  
  3190. 	-- return to the lineup 
  3191. 	store_character_change_state(LINEUP_STATE) 
  3192. end 
  3193.  
  3194.  
  3195. function store_character_lineup_susan_in_done() 
  3196. 	Store_character_anim_done = true 
  3197. 	Lineup_input_tracker:subscribe(true) 
  3198. 	 
  3199. 	store_character_enable_mouse_split(false, true, true) 
  3200. 	Current_tier = LINEUP_TIER 
  3201. end 
  3202.  
  3203. function store_character_lineup_susan_out_done() 
  3204. 	Store_character_anim_done = true 
  3205. 	Input_tracker:subscribe(true) 
  3206. 	 
  3207. 	store_character_enable_mouse_split(true, true, false) 
  3208. 	Current_tier = MENU_TIER 
  3209. 	 
  3210. 	image_streamer_end_streaming() 
  3211. end 
  3212.  
  3213. function store_character_allow_input() 
  3214. 	return Store_character_anim_done 
  3215. end 
  3216.  
  3217. -- Called when this interface becomes the top one on the stack again. 
  3218. -- 
  3219. function store_character_gained_focus() 
  3220.  
  3221. 	local is_plastic_surgeon = pcr_is_plastic_surgeon() 
  3222.  
  3223. 	local new_state 
  3224. 	 
  3225. 	if Store_character_current_state == GALLERY_DOWNLOAD_STATE and Store_common_gallery_cancel then 
  3226. 		new_state = LINEUP_STATE 
  3227. 	else 
  3228. 		new_state = CUSTOMIZATION_STATE 
  3229. 		character_enable_mouse_drag(true) 
  3230. 	end 
  3231.  
  3232. 	Store_common_gallery_cancel = false 
  3233. 	store_character_change_state(new_state) 
  3234. 	 
  3235. 	if is_plastic_surgeon == false and Store_common_gallery_download_only == true then 
  3236. 		vint_set_property(vint_object_find("police_logo"), "visible", true)		 
  3237. 	end 
  3238.  
  3239. 	if Hint_bar_mouse_input_tracker ~= -1 then 
  3240. 		Hint_bar_mouse_input_tracker:subscribe(true) 
  3241. 	end 
  3242. 	 
  3243. end 
  3244.  
  3245. function store_character_lost_focus() 
  3246.  
  3247. 	if Hint_bar_mouse_input_tracker ~= -1 then 
  3248. 		Hint_bar_mouse_input_tracker:subscribe(false) 
  3249. 	end 
  3250.  
  3251. end 
  3252.  
  3253. function store_character_bg_anim_done() 
  3254. 	store_common_bg_anim_complete() 
  3255. end 
  3256.  
  3257.  
  3258. --******************************* State transition functions ******************************************************* 
  3259.  
  3260. function store_character_lineup_to_gallery_download() 
  3261.  
  3262. 	if push_screen("store_gallery") == true then 
  3263.  
  3264. 		Store_common_gallery_download_only = true	 
  3265. 		 
  3266. 		Lineup_input_tracker:subscribe(false) 
  3267. 		store_character_enable_mouse_split(false, false, false) 
  3268. 		 
  3269. 		store_character_creation_add_clothes() 
  3270. 	 
  3271. 	else 
  3272.  
  3273. 		Store_character_current_state = LINEUP_STATE 
  3274.  
  3275. 	end 
  3276.  
  3277. end 
  3278.  
  3279.  
  3280. function store_character_lineup_to_customization() 
  3281.  
  3282. 	-- reset callbacks 
  3283. 	Store_common_populate_list_cb = store_character_populate_list 
  3284. 	Store_common_exit_cb				= store_character_lineup_return_confirm 
  3285.  
  3286. 	vint_apply_start_values(Store_character_in_anim.handle) 
  3287. 	vint_apply_start_values(Player_creation_bg_anim.handle) 
  3288. 		 
  3289. 	-- Get the index of the picture the player picked 
  3290. 	local index = Susan_object:get_index() 
  3291. 	local info = Store_character_lineup_presets[index] 
  3292.  
  3293. 	-- switch input from lineup to customization 
  3294. 	Lineup_input_tracker:subscribe(false) 
  3295. 	store_character_enable_mouse_split(false, false, false) 
  3296. 	 
  3297. 	-- load in our preset character 
  3298. 	local preset_name = info.gender .. "_" .. info.race 
  3299. 	local regional_preset_name = info.gender .. "_" .. info.figure 
  3300. 	pcr_apply_preset(preset_name, "figure", regional_preset_name, false) 
  3301. 	pcr_mark_changed() 
  3302. 	 
  3303. 	-- We want the character to have clothes on at the top menu, and we need to change to preset clothing 
  3304. 	pcr_add_default_clothing() 
  3305. 	 
  3306. 	-- transition to customization interface 
  3307. 	Store_character_anim_done = false 
  3308. 	 
  3309. 	ui_audio_post_event("Police_Lineup") 
  3310. 	 
  3311. 	local pcr_anim_in = Vdo_anim_object:new("player_creation_fade_in_anim") 
  3312. 	local end_tween = Vdo_anim_object:new("susan_anchor_out_twn")	 
  3313. 	 
  3314. 	end_tween:set_property("end_event","store_character_lineup_susan_out_done") 
  3315. 	 
  3316. 	vint_set_property(vint_object_find("player_creation_grp"), "background", true) 
  3317. 	 
  3318. 	game_UI_audio_play("UI_Main_Menu_Select") 
  3319. 	 
  3320. 	Active_list:set_visible(true) 
  3321. 	Store_header:set_visible(true) 
  3322. 	if game_get_platform() ~= "PC" then 
  3323. 		Store_common_rotate_hint:set_visible(true) 
  3324. 	end 
  3325. 	 
  3326. 	vint_set_property(vint_object_find("police_logo"), "visible", true)	 
  3327.  
  3328. 	pcr_anim_in:play()	 
  3329. 	Store_character_in_anim:play(0) 
  3330. 	Player_creation_bg_anim:play(0)	 
  3331.  
  3332. 	-- Change hint buttons 
  3333. 	local hint_data = { 
  3334. 		{CTRL_MENU_BUTTON_B, "MENU_BACK"}, 
  3335. 	} 
  3336. 	Store_common_hint_bar:set_hints(hint_data) 	 
  3337. 	 
  3338. 	character_enable_mouse_drag(true) 
  3339. end 
  3340.  
  3341.  
  3342. function store_character_gallery_download_to_lineup() 
  3343.  
  3344. 	-- reset callbacks 
  3345. 	Store_common_populate_list_cb = store_character_populate_list 
  3346. 	Store_common_exit_cb				= store_character_lineup_return_confirm	 
  3347. 	 
  3348. 	vint_apply_start_values(Store_character_in_anim.handle) 
  3349. 	vint_apply_start_values(Player_creation_bg_anim.handle) 
  3350.  
  3351. 	store_character_populate_list(Menu_data, Active_list:get_selection())	 
  3352. 	Active_list:set_visible(false) 
  3353. 	Store_header:set_visible(false) 
  3354. 	Store_common_rotate_hint:set_visible(false) 
  3355.  
  3356. 	vint_set_property(vint_object_find("police_logo"), "visible", false)			 
  3357. 	 
  3358. 	Store_character_in_anim:play(0) 
  3359. 	Player_creation_bg_anim:play(0) 
  3360. 	 
  3361. 	local anim = Vdo_anim_object:new("player_creation_fade_out_anim") 
  3362. 	anim:play() 
  3363. 	Susan_object:play_intro() 
  3364. 	vint_set_property(vint_object_find("player_creation_grp"), "background", false) 
  3365. 	 
  3366. 	Store_character_anim_done = false 
  3367. 	 
  3368. 	local end_tween = Vdo_anim_object:new("gradient_alpha_in_twn") 
  3369. 	end_tween:set_property("end_event","store_character_lineup_susan_in_done") 
  3370. 	 
  3371. 	-- start streaming images again 
  3372. 	-- Get the index of the picture the player picked 
  3373. 	local index = Susan_object:get_index() 
  3374. 	 
  3375. 	-- Decrement the index to load the images before current highlight 
  3376. 	index = index - 2 
  3377. 	if index < 1 then 
  3378. 		index = index + STORE_CHARACTER_NUM_LINEUP_IMAGES 
  3379. 	end 
  3380. 	 
  3381. 	image_streamer_start_streaming(index, STORE_CHARACTER_NUM_LINEUP_IMAGES_LOADED) 
  3382.  
  3383. 	-- switch inputs back to lineup mode 
  3384. 	Input_tracker:subscribe(false) 
  3385. 	store_character_enable_mouse_split(false, false, false) 
  3386. 	 
  3387. 	-- Change hint buttons 
  3388. 	local hint_data = { 
  3389. 		{CTRL_MENU_BUTTON_A, "CUST_CHOOSE_CHARACTER"}, 
  3390. 	} 
  3391. 	Store_common_hint_bar:set_hints(hint_data) 	 
  3392. 	Store_common_hint_bar:set_visible(true) 
  3393. 	 
  3394. 	character_enable_mouse_drag(false)	 
  3395. 	 
  3396. 	Store_common_gallery_download_only = false	 
  3397. 	 
  3398. 	Store_header:clear_titles()	 
  3399. 	Store_header:push_title(nil, "STORE_CHOOSE_A_CATEGORY")	 
  3400. 	 
  3401. 	vint_set_property(vint_object_find("player_creation_grp", 0, Store_character_doc_handle), "background", false) 
  3402. 	bg_saints_set_background(false)	 
  3403. end 
  3404.  
  3405.  
  3406. function store_character_gallery_download_to_customization() 
  3407.  
  3408. 	-- reset callbacks 
  3409. 	Store_common_populate_list_cb = store_character_populate_list 
  3410. 	Store_common_exit_cb				= store_character_lineup_return_confirm 
  3411.  
  3412. 	vint_apply_start_values(Store_character_in_anim.handle) 
  3413. 	 
  3414. 	vint_set_property(vint_object_find("police_logo"), "visible", true)		 
  3415. 	 
  3416. 	local pcr_anim_in = Vdo_anim_object:new("player_creation_fade_in_anim") 
  3417. 	 
  3418. 	Store_common_gallery_download_only = false 
  3419. 	Store_header:set_visible(true) 
  3420. 	Active_list:set_visible(true) 
  3421. 	if game_get_platform() ~= "PC" then 
  3422. 		Store_common_rotate_hint:set_visible(true) 
  3423. 	end 
  3424. 		 
  3425. 	Susan_object:set_visible(false)	 
  3426. 		 
  3427. 	pcr_anim_in:play(0)	 
  3428. 	Store_character_in_anim:play(0) 
  3429. 	 
  3430. 	store_unlock_controls() 
  3431. 	 
  3432. 	Store_header:clear_titles()	 
  3433. 	Store_header:push_title(nil, "STORE_CHOOSE_A_CATEGORY")	 
  3434.  
  3435. 	store_character_populate_list(Menu_data, Active_list:get_selection()) 
  3436. 	 
  3437. 	-- Cleans up images in the image streamer for lineup 
  3438. 	store_character_lineup_susan_out_done()	 
  3439. end 
  3440.  
  3441.  
  3442. function store_character_customization_to_lineup() 
  3443. 	vint_apply_start_values(Store_character_in_anim.handle) 
  3444. 	vint_apply_start_values(Player_creation_bg_anim.handle) 
  3445.  
  3446. 	Active_list:set_visible(false) 
  3447. 	Store_header:set_visible(false) 
  3448. 	Store_common_rotate_hint:set_visible(false) 
  3449.  
  3450. 	vint_set_property(vint_object_find("police_logo"), "visible", false)			 
  3451. 	 
  3452. 	Store_character_in_anim:play(0) 
  3453. 	Player_creation_bg_anim:play(0) 
  3454. 	 
  3455. 	local anim = Vdo_anim_object:new("player_creation_fade_out_anim") 
  3456. 	anim:play() 
  3457. 	Susan_object:play_intro() 
  3458. 	vint_set_property(vint_object_find("player_creation_grp"), "background", false) 
  3459. 	 
  3460. 	Store_character_anim_done = false 
  3461. 	 
  3462. 	local end_tween = Vdo_anim_object:new("gradient_alpha_in_twn") 
  3463. 	end_tween:set_property("end_event","store_character_lineup_susan_in_done") 
  3464. 	 
  3465. 	-- start streaming images again 
  3466. 	-- Get the index of the picture the player picked 
  3467. 	local index = Susan_object:get_index() 
  3468. 	 
  3469. 	-- Decrement the index to load the images before current highlight 
  3470. 	index = index - 2 
  3471. 	if index < 1 then 
  3472. 		index = index + STORE_CHARACTER_NUM_LINEUP_IMAGES 
  3473. 	end 
  3474. 	 
  3475. 	image_streamer_start_streaming(index, STORE_CHARACTER_NUM_LINEUP_IMAGES_LOADED) 
  3476.  
  3477. 	-- switch inputs back to lineup mode 
  3478. 	Input_tracker:subscribe(false) 
  3479. 	store_character_enable_mouse_split(false, false, false) 
  3480. 	 
  3481. 	-- Change hint buttons 
  3482. 	local hint_data = { 
  3483. 		{CTRL_MENU_BUTTON_A, "CUST_CHOOSE_CHARACTER"}, 
  3484. 	} 
  3485. 	Store_common_hint_bar:set_hints(hint_data) 	 
  3486. 	 
  3487. 	character_enable_mouse_drag(false) 
  3488. 	 
  3489. 	Susan_object:set_visible(true)	 
  3490. end 
  3491.  
  3492.  
  3493. function store_character_customization_to_gallery_full() 
  3494. 	if (push_screen("store_gallery") ~= true) then 
  3495. 		Store_character_current_state = CUSTOMIZATION_STATE 
  3496. 	end 
  3497. end 
  3498.  
  3499.  
  3500. function store_character_customization_to_finished() 
  3501.  
  3502. end 
  3503.  
  3504.  
  3505. function store_character_gallery_full_to_customization() 
  3506. 	Store_common_gallery_download_only = false 
  3507. 	 
  3508. 	pcr_strip_clothing() 
  3509.  
  3510. 	store_unlock_controls() 
  3511. 	 
  3512. 	-- reset our store stacks 
  3513. 	store_common_stack_clear_menu() 
  3514. 	store_common_stack_clear_id() 
  3515. 	store_common_stack_clear_index()	 
  3516. 	 
  3517. 	-- Populate the areas and draw the first menu 
  3518. 	store_character_main_menu_fill()	 
  3519. 	 
  3520. 	-- If we're in the character lineup, change the text on the "exit" choice, and what happens on back 
  3521. 	local is_plastic_surgeon = pcr_is_plastic_surgeon() 
  3522. 	if is_plastic_surgeon == false then 
  3523. 		Menu_data[#Menu_data].label = "CUST_MENU_EXIT" 
  3524. 		Menu_data[#Menu_data].is_new 	= true 
  3525. 		Store_common_exit_cb	= store_character_lineup_return_confirm					 
  3526. 	else		 
  3527. 		Store_common_exit_cb	= store_character_exit			 
  3528. 	end 
  3529. 	 
  3530. 	if game_get_platform() ~= "PC" then 
  3531. 		Store_common_rotate_hint:set_visible(true) 
  3532. 	end 
  3533. 	 
  3534. 	-- Pass the table data to the megalist vdo. 
  3535. 	store_character_populate_list(Menu_data, 1) 
  3536. 	 
  3537. 	-- Set up some callbacks for the common store script 
  3538. 	Store_common_populate_list_cb = store_character_populate_list 
  3539. end 
  3540.  
  3541. local Creation_state_transitions = { 
  3542. 	[LINEUP_STATE] = { 
  3543. 		[GALLERY_DOWNLOAD_STATE]		= store_character_lineup_to_gallery_download, 
  3544. 		[CUSTOMIZATION_STATE]			= store_character_lineup_to_customization, 
  3545. 	}, 
  3546. 	 
  3547. 	[GALLERY_DOWNLOAD_STATE] = { 
  3548. 		[LINEUP_STATE]						= store_character_gallery_download_to_lineup, 
  3549. 		[CUSTOMIZATION_STATE]			= store_character_gallery_download_to_customization, 
  3550. 	}, 
  3551.  
  3552. 	[CUSTOMIZATION_STATE] = { 
  3553. 		[LINEUP_STATE]						= store_character_customization_to_lineup, 
  3554. 		[GALLERY_FULL_STATE]				= store_character_customization_to_gallery_full, 
  3555. 		[FINISHED_STATE]					= store_character_customization_to_finished, 
  3556. 	}, 
  3557. 	 
  3558. 	[GALLERY_FULL_STATE] = { 
  3559. 		[CUSTOMIZATION_STATE]			= store_character_gallery_full_to_customization, 
  3560. 	}, 
  3561. } 
  3562.  
  3563. function store_character_change_state(new_state) 
  3564.  
  3565. 	local state_change_func = Creation_state_transitions[Store_character_current_state][new_state] 
  3566.  
  3567. 	-- don't do anything on an invalid state change 
  3568. 	if state_change_func ~= nil then 
  3569. 		Store_character_current_state = new_state 
  3570. 		state_change_func() 
  3571. 	end 
  3572. end 
  3573.