|  | @ -1,6 +1,6 @@ | 
		
	
		
			
				|  |  | 
 |  |  | 
 | 
		
	
		
			
				|  |  | game = false -- flag to tell if there is a game running |  |  | game = false -- flag to tell if there is a game running | 
		
	
		
			
				|  |  | state = {} |  |  |  | 
		
	
		
			
				|  |  |  |  |  | game_state = {} | 
		
	
		
			
				|  |  | 
 |  |  | 
 | 
		
	
		
			
				|  |  | -- top right display types |  |  | -- top right display types | 
		
	
		
			
				|  |  | -- f1 toggles what is displayed in the top right of the screen |  |  | -- f1 toggles what is displayed in the top right of the screen | 
		
	
	
		
			
				|  | @ -48,10 +48,10 @@ local function get_initial_game_state(seed) | 
		
	
		
			
				|  |  | end |  |  | end | 
		
	
		
			
				|  |  | 
 |  |  | 
 | 
		
	
		
			
				|  |  | local function get_wave_timer_text() |  |  | local function get_wave_timer_text() | 
		
	
		
			
				|  |  |     if state.spawning then |  |  |  | 
		
	
		
			
				|  |  |         return string.format("WAVE (%d) OVER: %.2f", state.current_wave, state.time_until_next_break) |  |  |  | 
		
	
		
			
				|  |  |  |  |  |     if game_state.spawning then | 
		
	
		
			
				|  |  |  |  |  |         return string.format("WAVE (%d) OVER: %.2f", game_state.current_wave, game_state.time_until_next_break) | 
		
	
		
			
				|  |  |     else |  |  |     else | 
		
	
		
			
				|  |  |         return string.format("NEXT WAVE (%d): %.2f", state.current_wave, state.time_until_next_wave) |  |  |  | 
		
	
		
			
				|  |  |  |  |  |         return string.format("NEXT WAVE (%d): %.2f", game_state.current_wave, game_state.time_until_next_wave) | 
		
	
		
			
				|  |  |     end |  |  |     end | 
		
	
		
			
				|  |  | end |  |  | end | 
		
	
		
			
				|  |  | 
 |  |  | 
 | 
		
	
	
		
			
				|  | @ -73,10 +73,10 @@ local function get_top_right_display_text(hex, evenq, centered_evenq, display_ty | 
		
	
		
			
				|  |  |         str = table.tostring(am.perf_stats()) |  |  |         str = table.tostring(am.perf_stats()) | 
		
	
		
			
				|  |  | 
 |  |  | 
 | 
		
	
		
			
				|  |  |     elseif display_type == TRDTS.SEED then |  |  |     elseif display_type == TRDTS.SEED then | 
		
	
		
			
				|  |  |         str = "SEED: " .. state.map.seed |  |  |  | 
		
	
		
			
				|  |  |  |  |  |         str = "SEED: " .. game_state.map.seed | 
		
	
		
			
				|  |  | 
 |  |  | 
 | 
		
	
		
			
				|  |  |     elseif display_type == TRDTS.TILE then |  |  |     elseif display_type == TRDTS.TILE then | 
		
	
		
			
				|  |  |         str = table.tostring(hex_map_get(state.map, hex)) |  |  |  | 
		
	
		
			
				|  |  |  |  |  |         str = table.tostring(hex_map_get(game_state.map, hex)) | 
		
	
		
			
				|  |  |     end |  |  |     end | 
		
	
		
			
				|  |  |     return str |  |  |     return str | 
		
	
		
			
				|  |  | end |  |  | end | 
		
	
	
		
			
				|  | @ -91,14 +91,14 @@ end | 
		
	
		
			
				|  |  | 
 |  |  | 
 | 
		
	
		
			
				|  |  | local BASE_BREAK_TIME = 20 |  |  | local BASE_BREAK_TIME = 20 | 
		
	
		
			
				|  |  | local function get_break_time(current_wave) |  |  | local function get_break_time(current_wave) | 
		
	
		
			
				|  |  |     return BASE_BREAK_TIME - math.min(BASE_BREAK_TIME, BASE_BREAK_TIME / (1 / math.log(state.current_wave + 1))) |  |  |  | 
		
	
		
			
				|  |  |  |  |  |     return BASE_BREAK_TIME - math.min(BASE_BREAK_TIME, BASE_BREAK_TIME / (1 / math.log(game_state.current_wave + 1))) | 
		
	
		
			
				|  |  | end |  |  | end | 
		
	
		
			
				|  |  | 
 |  |  | 
 | 
		
	
		
			
				|  |  | local function do_day_night_cycle() |  |  | local function do_day_night_cycle() | 
		
	
		
			
				|  |  |     -- this is a bad idea, atleast with the current bad rendering strategy of not using a single draw call |  |  |     -- this is a bad idea, atleast with the current bad rendering strategy of not using a single draw call | 
		
	
		
			
				|  |  |     -- i get flickering as the light level increases |  |  |     -- i get flickering as the light level increases | 
		
	
		
			
				|  |  |     --local tstep = (math.sin(state.time * am.delta_time) + 1) / 100 |  |  |  | 
		
	
		
			
				|  |  |     --state.world"negative_mask".color = vec4(tstep){a=1} |  |  |  | 
		
	
		
			
				|  |  |  |  |  |     --local tstep = (math.sin(game_state.time * am.delta_time) + 1) / 100 | 
		
	
		
			
				|  |  |  |  |  |     --game_state.world"negative_mask".color = vec4(tstep){a=1} | 
		
	
		
			
				|  |  | end |  |  | end | 
		
	
		
			
				|  |  | 
 |  |  | 
 | 
		
	
		
			
				|  |  | local function game_pause() |  |  | local function game_pause() | 
		
	
	
		
			
				|  | @ -110,48 +110,48 @@ end | 
		
	
		
			
				|  |  | local function game_deserialize(json_string) |  |  | local function game_deserialize(json_string) | 
		
	
		
			
				|  |  |     local new_state = am.parse_json(json_string) |  |  |     local new_state = am.parse_json(json_string) | 
		
	
		
			
				|  |  | 
 |  |  | 
 | 
		
	
		
			
				|  |  |     if new_state.version ~= version then |  |  |  | 
		
	
		
			
				|  |  |  |  |  |     if new_game_state.version ~= version then | 
		
	
		
			
				|  |  |         log("loading incompatible old save data. starting a fresh game instead.") |  |  |         log("loading incompatible old save data. starting a fresh game instead.") | 
		
	
		
			
				|  |  |         return get_initial_game_state() |  |  |         return get_initial_game_state() | 
		
	
		
			
				|  |  |     end |  |  |     end | 
		
	
		
			
				|  |  | 
 |  |  | 
 | 
		
	
		
			
				|  |  |     new_state.map = random_map(new_state.seed) |  |  |  | 
		
	
		
			
				|  |  |     new_state.world = make_hex_grid_scene(new_state.map) |  |  |  | 
		
	
		
			
				|  |  |     new_state.seed = nil |  |  |  | 
		
	
		
			
				|  |  |  |  |  |     new_game_state.map = random_map(new_game_state.seed) | 
		
	
		
			
				|  |  |  |  |  |     new_game_state.world = make_hex_grid_scene(new_game_state.map) | 
		
	
		
			
				|  |  |  |  |  |     new_game_state.seed = nil | 
		
	
		
			
				|  |  | 
 |  |  | 
 | 
		
	
		
			
				|  |  |     for i,t in pairs(new_state.towers) do |  |  |  | 
		
	
		
			
				|  |  |  |  |  |     for i,t in pairs(new_game_state.towers) do | 
		
	
		
			
				|  |  |         if t then |  |  |         if t then | 
		
	
		
			
				|  |  |             new_state.towers[i] = tower_deserialize(t) |  |  |  | 
		
	
		
			
				|  |  |  |  |  |             new_game_state.towers[i] = tower_deserialize(t) | 
		
	
		
			
				|  |  | 
 |  |  | 
 | 
		
	
		
			
				|  |  |             for _,h in pairs(new_state.towers[i].hexes) do |  |  |  | 
		
	
		
			
				|  |  |                 local tile = hex_map_get(new_state.map, h.x, h.y) |  |  |  | 
		
	
		
			
				|  |  |                 tile.elevation = tile.elevation + new_state.towers[i].height |  |  |  | 
		
	
		
			
				|  |  |  |  |  |             for _,h in pairs(new_game_state.towers[i].hexes) do | 
		
	
		
			
				|  |  |  |  |  |                 local tile = hex_map_get(new_game_state.map, h.x, h.y) | 
		
	
		
			
				|  |  |  |  |  |                 tile.elevation = tile.elevation + new_game_state.towers[i].height | 
		
	
		
			
				|  |  |             end |  |  |             end | 
		
	
		
			
				|  |  | 
 |  |  | 
 | 
		
	
		
			
				|  |  |             -- @STATEFUL, shouldn't be done here |  |  |             -- @STATEFUL, shouldn't be done here | 
		
	
		
			
				|  |  |             new_state.world:append(new_state.towers[i].node) |  |  |  | 
		
	
		
			
				|  |  |  |  |  |             new_game_state.world:append(new_game_state.towers[i].node) | 
		
	
		
			
				|  |  |         end |  |  |         end | 
		
	
		
			
				|  |  |     end |  |  |     end | 
		
	
		
			
				|  |  | 
 |  |  | 
 | 
		
	
		
			
				|  |  |     -- after we have re-constituted all of the towers and modified the map's elevations accordingly, |  |  |     -- after we have re-constituted all of the towers and modified the map's elevations accordingly, | 
		
	
		
			
				|  |  |     -- we should re-calc the flow-field |  |  |     -- we should re-calc the flow-field | 
		
	
		
			
				|  |  |     apply_flow_field(new_state.map, generate_flow_field(new_state.map, HEX_GRID_CENTER), new_state.world) |  |  |  | 
		
	
		
			
				|  |  |  |  |  |     apply_flow_field(new_game_state.map, generate_flow_field(new_game_state.map, HEX_GRID_CENTER), new_game_state.world) | 
		
	
		
			
				|  |  | 
 |  |  | 
 | 
		
	
		
			
				|  |  |     for i,m in pairs(new_state.mobs) do |  |  |  | 
		
	
		
			
				|  |  |  |  |  |     for i,m in pairs(new_game_state.mobs) do | 
		
	
		
			
				|  |  |         if m then |  |  |         if m then | 
		
	
		
			
				|  |  |             new_state.mobs[i] = mob_deserialize(m) |  |  |  | 
		
	
		
			
				|  |  |  |  |  |             new_game_state.mobs[i] = mob_deserialize(m) | 
		
	
		
			
				|  |  | 
 |  |  | 
 | 
		
	
		
			
				|  |  |             -- @STATEFUL, shouldn't be done here |  |  |             -- @STATEFUL, shouldn't be done here | 
		
	
		
			
				|  |  |             new_state.world:append(new_state.mobs[i].node) |  |  |  | 
		
	
		
			
				|  |  |  |  |  |             new_game_state.world:append(new_game_state.mobs[i].node) | 
		
	
		
			
				|  |  |         end |  |  |         end | 
		
	
		
			
				|  |  |     end |  |  |     end | 
		
	
		
			
				|  |  | 
 |  |  | 
 | 
		
	
		
			
				|  |  |     for i,p in pairs(new_state.projectiles) do |  |  |  | 
		
	
		
			
				|  |  |  |  |  |     for i,p in pairs(new_game_state.projectiles) do | 
		
	
		
			
				|  |  |         if p then |  |  |         if p then | 
		
	
		
			
				|  |  |             new_state.projectiles[i] = projectile_deserialize(p) |  |  |  | 
		
	
		
			
				|  |  |  |  |  |             new_game_state.projectiles[i] = projectile_deserialize(p) | 
		
	
		
			
				|  |  | 
 |  |  | 
 | 
		
	
		
			
				|  |  |             -- @STATEFUL, shouldn't be done here |  |  |             -- @STATEFUL, shouldn't be done here | 
		
	
		
			
				|  |  |             new_state.world:append(new_state.projectiles[i].node) |  |  |  | 
		
	
		
			
				|  |  |  |  |  |             new_game_state.world:append(new_game_state.projectiles[i].node) | 
		
	
		
			
				|  |  |         end |  |  |         end | 
		
	
		
			
				|  |  |     end |  |  |     end | 
		
	
		
			
				|  |  | 
 |  |  | 
 | 
		
	
	
		
			
				|  | @ -162,7 +162,7 @@ local function game_serialize() | 
		
	
		
			
				|  |  |     local serialized = table.shallow_copy(state) |  |  |     local serialized = table.shallow_copy(state) | 
		
	
		
			
				|  |  |     serialized.version = version |  |  |     serialized.version = version | 
		
	
		
			
				|  |  | 
 |  |  | 
 | 
		
	
		
			
				|  |  |     serialized.seed = state.map.seed |  |  |  | 
		
	
		
			
				|  |  |  |  |  |     serialized.seed = game_state.map.seed | 
		
	
		
			
				|  |  |     serialized.map = nil -- we re-generate the entire map from the seed on de-serialize |  |  |     serialized.map = nil -- we re-generate the entire map from the seed on de-serialize | 
		
	
		
			
				|  |  | 
 |  |  | 
 | 
		
	
		
			
				|  |  |     -- in order to serialize the game state, we have to convert all relevant userdata into |  |  |     -- in order to serialize the game state, we have to convert all relevant userdata into | 
		
	
	
		
			
				|  | @ -174,21 +174,21 @@ local function game_serialize() | 
		
	
		
			
				|  |  |     -- this is dumb and if i forsaw this i would have probably used float arrays instead of vectors |  |  |     -- this is dumb and if i forsaw this i would have probably used float arrays instead of vectors | 
		
	
		
			
				|  |  | 
 |  |  | 
 | 
		
	
		
			
				|  |  |     serialized.towers = {} |  |  |     serialized.towers = {} | 
		
	
		
			
				|  |  |     for i,t in pairs(state.towers) do |  |  |  | 
		
	
		
			
				|  |  |  |  |  |     for i,t in pairs(game_state.towers) do | 
		
	
		
			
				|  |  |         if t then |  |  |         if t then | 
		
	
		
			
				|  |  |             serialized.towers[i] = tower_serialize(t) |  |  |             serialized.towers[i] = tower_serialize(t) | 
		
	
		
			
				|  |  |         end |  |  |         end | 
		
	
		
			
				|  |  |     end |  |  |     end | 
		
	
		
			
				|  |  | 
 |  |  | 
 | 
		
	
		
			
				|  |  |     serialized.mobs = {} |  |  |     serialized.mobs = {} | 
		
	
		
			
				|  |  |     for i,m in pairs(state.mobs) do |  |  |  | 
		
	
		
			
				|  |  |  |  |  |     for i,m in pairs(game_state.mobs) do | 
		
	
		
			
				|  |  |         if m then |  |  |         if m then | 
		
	
		
			
				|  |  |             serialized.mobs[i] = mob_serialize(m) |  |  |             serialized.mobs[i] = mob_serialize(m) | 
		
	
		
			
				|  |  |         end |  |  |         end | 
		
	
		
			
				|  |  |     end |  |  |     end | 
		
	
		
			
				|  |  | 
 |  |  | 
 | 
		
	
		
			
				|  |  |     serialized.projectiles = {} |  |  |     serialized.projectiles = {} | 
		
	
		
			
				|  |  |     for i,p in pairs(state.projectiles) do |  |  |  | 
		
	
		
			
				|  |  |  |  |  |     for i,p in pairs(game_state.projectiles) do | 
		
	
		
			
				|  |  |         if p then |  |  |         if p then | 
		
	
		
			
				|  |  |             serialized.projectiles[i] = projectile_serialize(p) |  |  |             serialized.projectiles[i] = projectile_serialize(p) | 
		
	
		
			
				|  |  |         end |  |  |         end | 
		
	
	
		
			
				|  | @ -202,35 +202,35 @@ local function deselect_tile() | 
		
	
		
			
				|  |  | end |  |  | end | 
		
	
		
			
				|  |  | 
 |  |  | 
 | 
		
	
		
			
				|  |  | local function game_action(scene) |  |  | local function game_action(scene) | 
		
	
		
			
				|  |  |     if state.score < 0 then game_end() return true end |  |  |  | 
		
	
		
			
				|  |  |  |  |  |     if game_state.score < 0 then game_end() return true end | 
		
	
		
			
				|  |  | 
 |  |  | 
 | 
		
	
		
			
				|  |  |     local perf = am.perf_stats() |  |  |     local perf = am.perf_stats() | 
		
	
		
			
				|  |  |     state.time = state.time + am.delta_time |  |  |  | 
		
	
		
			
				|  |  |     state.score = state.score + am.delta_time |  |  |  | 
		
	
		
			
				|  |  |  |  |  |     game_state.time = game_state.time + am.delta_time | 
		
	
		
			
				|  |  |  |  |  |     game_state.score = game_state.score + am.delta_time | 
		
	
		
			
				|  |  | 
 |  |  | 
 | 
		
	
		
			
				|  |  |     if state.spawning then |  |  |  | 
		
	
		
			
				|  |  |         state.time_until_next_break = state.time_until_next_break - am.delta_time |  |  |  | 
		
	
		
			
				|  |  |  |  |  |     if game_state.spawning then | 
		
	
		
			
				|  |  |  |  |  |         game_state.time_until_next_break = game_state.time_until_next_break - am.delta_time | 
		
	
		
			
				|  |  | 
 |  |  | 
 | 
		
	
		
			
				|  |  |         if state.time_until_next_break <= 0 then |  |  |  | 
		
	
		
			
				|  |  |             state.time_until_next_break = 0 |  |  |  | 
		
	
		
			
				|  |  |             state.current_wave = state.current_wave + 1 |  |  |  | 
		
	
		
			
				|  |  |  |  |  |         if game_state.time_until_next_break <= 0 then | 
		
	
		
			
				|  |  |  |  |  |             game_state.time_until_next_break = 0 | 
		
	
		
			
				|  |  |  |  |  |             game_state.current_wave = game_state.current_wave + 1 | 
		
	
		
			
				|  |  | 
 |  |  | 
 | 
		
	
		
			
				|  |  |             state.spawning = false |  |  |  | 
		
	
		
			
				|  |  |  |  |  |             game_state.spawning = false | 
		
	
		
			
				|  |  | 
 |  |  | 
 | 
		
	
		
			
				|  |  |             state.time_until_next_wave = get_break_time(state.current_wave) |  |  |  | 
		
	
		
			
				|  |  |  |  |  |             game_state.time_until_next_wave = get_break_time(game_state.current_wave) | 
		
	
		
			
				|  |  |         end |  |  |         end | 
		
	
		
			
				|  |  |     else |  |  |     else | 
		
	
		
			
				|  |  |         state.time_until_next_wave = state.time_until_next_wave - am.delta_time |  |  |  | 
		
	
		
			
				|  |  |  |  |  |         game_state.time_until_next_wave = game_state.time_until_next_wave - am.delta_time | 
		
	
		
			
				|  |  | 
 |  |  | 
 | 
		
	
		
			
				|  |  |         if state.time_until_next_wave <= 0 then |  |  |  | 
		
	
		
			
				|  |  |             state.time_until_next_wave = 0 |  |  |  | 
		
	
		
			
				|  |  |  |  |  |         if game_state.time_until_next_wave <= 0 then | 
		
	
		
			
				|  |  |  |  |  |             game_state.time_until_next_wave = 0 | 
		
	
		
			
				|  |  | 
 |  |  | 
 | 
		
	
		
			
				|  |  |             state.spawning = true |  |  |  | 
		
	
		
			
				|  |  |  |  |  |             game_state.spawning = true | 
		
	
		
			
				|  |  | 
 |  |  | 
 | 
		
	
		
			
				|  |  |             -- calculate spawn chance for next wave |  |  |             -- calculate spawn chance for next wave | 
		
	
		
			
				|  |  |             state.spawn_chance = math.log(state.current_wave)/80 + 0.002 |  |  |  | 
		
	
		
			
				|  |  |  |  |  |             game_state.spawn_chance = math.log(game_state.current_wave)/80 + 0.002 | 
		
	
		
			
				|  |  | 
 |  |  | 
 | 
		
	
		
			
				|  |  |             state.time_until_next_break = get_wave_time(state.current_wave) |  |  |  | 
		
	
		
			
				|  |  |  |  |  |             game_state.time_until_next_break = get_wave_time(game_state.current_wave) | 
		
	
		
			
				|  |  |         end |  |  |         end | 
		
	
		
			
				|  |  |     end |  |  |     end | 
		
	
		
			
				|  |  | 
 |  |  | 
 | 
		
	
	
		
			
				|  | @ -240,18 +240,18 @@ local function game_action(scene) | 
		
	
		
			
				|  |  |     local evenq          = hex_to_evenq(hex) |  |  |     local evenq          = hex_to_evenq(hex) | 
		
	
		
			
				|  |  |     local centered_evenq = evenq{ y = -evenq.y } - vec2(math.floor(HEX_GRID_WIDTH/2) |  |  |     local centered_evenq = evenq{ y = -evenq.y } - vec2(math.floor(HEX_GRID_WIDTH/2) | 
		
	
		
			
				|  |  |                                                       , math.floor(HEX_GRID_HEIGHT/2)) |  |  |                                                       , math.floor(HEX_GRID_HEIGHT/2)) | 
		
	
		
			
				|  |  |     local tile = hex_map_get(state.map, hex) |  |  |  | 
		
	
		
			
				|  |  |  |  |  |     local tile = hex_map_get(game_state.map, hex) | 
		
	
		
			
				|  |  | 
 |  |  | 
 | 
		
	
		
			
				|  |  |     local interactable = evenq_is_in_interactable_region(evenq{ y = -evenq.y }) |  |  |     local interactable = evenq_is_in_interactable_region(evenq{ y = -evenq.y }) | 
		
	
		
			
				|  |  |     local buildable = tower_type_is_buildable_on(hex, tile, state.selected_tower_type) |  |  |  | 
		
	
		
			
				|  |  |  |  |  |     local buildable = tower_type_is_buildable_on(hex, tile, game_state.selected_tower_type) | 
		
	
		
			
				|  |  | 
 |  |  | 
 | 
		
	
		
			
				|  |  |     if win:mouse_pressed"left" then |  |  |     if win:mouse_pressed"left" then | 
		
	
		
			
				|  |  |         deselect_tile() |  |  |         deselect_tile() | 
		
	
		
			
				|  |  | 
 |  |  | 
 | 
		
	
		
			
				|  |  |         if interactable then |  |  |         if interactable then | 
		
	
		
			
				|  |  |             if buildable then |  |  |             if buildable then | 
		
	
		
			
				|  |  |                 local broken, flow_field = building_tower_breaks_flow_field(state.selected_tower_type, hex) |  |  |  | 
		
	
		
			
				|  |  |                 local cost = get_tower_cost(state.selected_tower_type) |  |  |  | 
		
	
		
			
				|  |  |  |  |  |                 local broken, flow_field = building_tower_breaks_flow_field(game_state.selected_tower_type, hex) | 
		
	
		
			
				|  |  |  |  |  |                 local cost = get_tower_cost(game_state.selected_tower_type) | 
		
	
		
			
				|  |  | 
 |  |  | 
 | 
		
	
		
			
				|  |  |                 if broken then |  |  |                 if broken then | 
		
	
		
			
				|  |  |                     local node = win.scene("cursor"):child(2) |  |  |                     local node = win.scene("cursor"):child(2) | 
		
	
	
		
			
				|  | @ -260,7 +260,7 @@ local function game_action(scene) | 
		
	
		
			
				|  |  |                     play_sfx(SOUNDS.BIRD2) |  |  |                     play_sfx(SOUNDS.BIRD2) | 
		
	
		
			
				|  |  |                     alert("closes the circle") |  |  |                     alert("closes the circle") | 
		
	
		
			
				|  |  | 
 |  |  | 
 | 
		
	
		
			
				|  |  |                 elseif cost > state.money then |  |  |  | 
		
	
		
			
				|  |  |  |  |  |                 elseif cost > game_state.money then | 
		
	
		
			
				|  |  |                     local node = win.scene("cursor"):child(2) |  |  |                     local node = win.scene("cursor"):child(2) | 
		
	
		
			
				|  |  |                     node.color = COLORS.CLARET |  |  |                     node.color = COLORS.CLARET | 
		
	
		
			
				|  |  |                     node:action(am.tween(0.1, { color = COLORS.TRANSPARENT })) |  |  |                     node:action(am.tween(0.1, { color = COLORS.TRANSPARENT })) | 
		
	
	
		
			
				|  | @ -269,10 +269,10 @@ local function game_action(scene) | 
		
	
		
			
				|  |  | 
 |  |  | 
 | 
		
	
		
			
				|  |  |                 else |  |  |                 else | 
		
	
		
			
				|  |  |                     update_money(-cost) |  |  |                     update_money(-cost) | 
		
	
		
			
				|  |  |                     build_tower(hex, state.selected_tower_type, flow_field) |  |  |  | 
		
	
		
			
				|  |  |  |  |  |                     build_tower(hex, game_state.selected_tower_type, flow_field) | 
		
	
		
			
				|  |  | 
 |  |  | 
 | 
		
	
		
			
				|  |  |                     if flow_field then |  |  |                     if flow_field then | 
		
	
		
			
				|  |  |                         apply_flow_field(state.map, flow_field, state.world) |  |  |  | 
		
	
		
			
				|  |  |  |  |  |                         apply_flow_field(game_state.map, flow_field, game_state.world) | 
		
	
		
			
				|  |  |                     end |  |  |                     end | 
		
	
		
			
				|  |  |                 end |  |  |                 end | 
		
	
		
			
				|  |  |             else |  |  |             else | 
		
	
	
		
			
				|  | @ -307,19 +307,19 @@ local function game_action(scene) | 
		
	
		
			
				|  |  |         game_pause() |  |  |         game_pause() | 
		
	
		
			
				|  |  | 
 |  |  | 
 | 
		
	
		
			
				|  |  |     elseif win:key_pressed"f1" then |  |  |     elseif win:key_pressed"f1" then | 
		
	
		
			
				|  |  |         state.selected_top_right_display_type = (state.selected_top_right_display_type + 1) % #table.keys(TRDTS) |  |  |  | 
		
	
		
			
				|  |  |  |  |  |         game_state.selected_top_right_display_type = (game_state.selected_top_right_display_type + 1) % #table.keys(TRDTS) | 
		
	
		
			
				|  |  | 
 |  |  | 
 | 
		
	
		
			
				|  |  |     elseif win:key_pressed"f2" then |  |  |     elseif win:key_pressed"f2" then | 
		
	
		
			
				|  |  |         state.world"flow_field".hidden = not state.world"flow_field".hidden |  |  |  | 
		
	
		
			
				|  |  |  |  |  |         game_state.world"flow_field".hidden = not game_state.world"flow_field".hidden | 
		
	
		
			
				|  |  | 
 |  |  | 
 | 
		
	
		
			
				|  |  |     elseif win:key_pressed"f3" then |  |  |     elseif win:key_pressed"f3" then | 
		
	
		
			
				|  |  |         game_save() |  |  |         game_save() | 
		
	
		
			
				|  |  | 
 |  |  | 
 | 
		
	
		
			
				|  |  |     elseif win:key_pressed"tab" then |  |  |     elseif win:key_pressed"tab" then | 
		
	
		
			
				|  |  |         if win:key_down"lshift" then |  |  |         if win:key_down"lshift" then | 
		
	
		
			
				|  |  |             select_toolbelt_button((state.selected_toolbelt_button + table.count(TOWER_TYPE) - 2) % table.count(TOWER_TYPE) + 1) |  |  |  | 
		
	
		
			
				|  |  |  |  |  |             select_toolbelt_button((game_state.selected_toolbelt_button + table.count(TOWER_TYPE) - 2) % table.count(TOWER_TYPE) + 1) | 
		
	
		
			
				|  |  |         else |  |  |         else | 
		
	
		
			
				|  |  |             select_toolbelt_button((state.selected_toolbelt_button) % table.count(TOWER_TYPE) + 1) |  |  |  | 
		
	
		
			
				|  |  |  |  |  |             select_toolbelt_button((game_state.selected_toolbelt_button) % table.count(TOWER_TYPE) + 1) | 
		
	
		
			
				|  |  |         end |  |  |         end | 
		
	
		
			
				|  |  |     elseif win:key_pressed"1" then select_toolbelt_button( 1) |  |  |     elseif win:key_pressed"1" then select_toolbelt_button( 1) | 
		
	
		
			
				|  |  |     elseif win:key_pressed"2" then select_toolbelt_button( 2) |  |  |     elseif win:key_pressed"2" then select_toolbelt_button( 2) | 
		
	
	
		
			
				|  | @ -336,7 +336,7 @@ local function game_action(scene) | 
		
	
		
			
				|  |  |     end |  |  |     end | 
		
	
		
			
				|  |  | 
 |  |  | 
 | 
		
	
		
			
				|  |  |     do_entity_updates() |  |  |     do_entity_updates() | 
		
	
		
			
				|  |  |     do_mob_spawning(state.spawn_chance) |  |  |  | 
		
	
		
			
				|  |  |  |  |  |     do_mob_spawning(game_state.spawn_chance) | 
		
	
		
			
				|  |  |     do_day_night_cycle() |  |  |     do_day_night_cycle() | 
		
	
		
			
				|  |  | 
 |  |  | 
 | 
		
	
		
			
				|  |  |     -- update the cursor |  |  |     -- update the cursor | 
		
	
	
		
			
				|  | @ -344,7 +344,7 @@ local function game_action(scene) | 
		
	
		
			
				|  |  |         win.scene("cursor").hidden = true |  |  |         win.scene("cursor").hidden = true | 
		
	
		
			
				|  |  | 
 |  |  | 
 | 
		
	
		
			
				|  |  |     else |  |  |     else | 
		
	
		
			
				|  |  |         if state.selected_tower_type then |  |  |  | 
		
	
		
			
				|  |  |  |  |  |         if game_state.selected_tower_type then | 
		
	
		
			
				|  |  |             if buildable then |  |  |             if buildable then | 
		
	
		
			
				|  |  |                 win.scene("cursor").hidden = false |  |  |                 win.scene("cursor").hidden = false | 
		
	
		
			
				|  |  | 
 |  |  | 
 | 
		
	
	
		
			
				|  | @ -358,10 +358,10 @@ local function game_action(scene) | 
		
	
		
			
				|  |  |         win.scene("cursor_translate").position2d = rounded_mouse |  |  |         win.scene("cursor_translate").position2d = rounded_mouse | 
		
	
		
			
				|  |  |     end |  |  |     end | 
		
	
		
			
				|  |  | 
 |  |  | 
 | 
		
	
		
			
				|  |  |     win.scene("score").text = string.format("SCORE: %.2f", state.score) |  |  |  | 
		
	
		
			
				|  |  |     win.scene("money").text = string.format("MONEY: $%d", state.money) |  |  |  | 
		
	
		
			
				|  |  |  |  |  |     win.scene("score").text = string.format("SCORE: %.2f", game_state.score) | 
		
	
		
			
				|  |  |  |  |  |     win.scene("money").text = string.format("MONEY: $%d", game_state.money) | 
		
	
		
			
				|  |  |     win.scene("wave_timer").text = get_wave_timer_text() |  |  |     win.scene("wave_timer").text = get_wave_timer_text() | 
		
	
		
			
				|  |  |     win.scene("top_right_display").text = get_top_right_display_text(hex, evenq, centered_evenq, state.selected_top_right_display_type) |  |  |  | 
		
	
		
			
				|  |  |  |  |  |     win.scene("top_right_display").text = get_top_right_display_text(hex, evenq, centered_evenq, game_state.selected_top_right_display_type) | 
		
	
		
			
				|  |  | end |  |  | end | 
		
	
		
			
				|  |  | 
 |  |  | 
 | 
		
	
		
			
				|  |  | local function make_game_toolbelt() |  |  | local function make_game_toolbelt() | 
		
	
	
		
			
				|  | @ -474,8 +474,8 @@ local function make_game_toolbelt() | 
		
	
		
			
				|  |  |                 end |  |  |                 end | 
		
	
		
			
				|  |  |             end |  |  |             end | 
		
	
		
			
				|  |  |         else |  |  |         else | 
		
	
		
			
				|  |  |             if state.selected_tower_type then |  |  |  | 
		
	
		
			
				|  |  |                 win.scene:replace("tower_tooltip_text", get_tower_tooltip_text_node(state.selected_tower_type)) |  |  |  | 
		
	
		
			
				|  |  |  |  |  |             if game_state.selected_tower_type then | 
		
	
		
			
				|  |  |  |  |  |                 win.scene:replace("tower_tooltip_text", get_tower_tooltip_text_node(game_state.selected_tower_type)) | 
		
	
		
			
				|  |  |             else |  |  |             else | 
		
	
		
			
				|  |  |                 win.scene:replace("tower_tooltip_text", am.group():tag"tower_tooltip_text") |  |  |                 win.scene:replace("tower_tooltip_text", am.group():tag"tower_tooltip_text") | 
		
	
		
			
				|  |  |             end |  |  |             end | 
		
	
	
		
			
				|  | @ -506,7 +506,7 @@ local function make_game_toolbelt() | 
		
	
		
			
				|  |  |     ) |  |  |     ) | 
		
	
		
			
				|  |  | 
 |  |  | 
 | 
		
	
		
			
				|  |  |     select_tower_type = function(tower_type) |  |  |     select_tower_type = function(tower_type) | 
		
	
		
			
				|  |  |         state.selected_tower_type = tower_type |  |  |  | 
		
	
		
			
				|  |  |  |  |  |         game_state.selected_tower_type = tower_type | 
		
	
		
			
				|  |  | 
 |  |  | 
 | 
		
	
		
			
				|  |  |         if get_tower_spec(tower_type) then |  |  |         if get_tower_spec(tower_type) then | 
		
	
		
			
				|  |  |             win.scene:replace( |  |  |             win.scene:replace( | 
		
	
	
		
			
				|  | @ -537,7 +537,7 @@ local function make_game_toolbelt() | 
		
	
		
			
				|  |  |     end |  |  |     end | 
		
	
		
			
				|  |  | 
 |  |  | 
 | 
		
	
		
			
				|  |  |     select_toolbelt_button = function(i) |  |  |     select_toolbelt_button = function(i) | 
		
	
		
			
				|  |  |         state.selected_toolbelt_button = i |  |  |  | 
		
	
		
			
				|  |  |  |  |  |         game_state.selected_toolbelt_button = i | 
		
	
		
			
				|  |  | 
 |  |  | 
 | 
		
	
		
			
				|  |  |         if get_tower_spec(i) then |  |  |         if get_tower_spec(i) then | 
		
	
		
			
				|  |  |             select_tower_type(i) |  |  |             select_tower_type(i) | 
		
	
	
		
			
				|  | @ -581,20 +581,20 @@ local function game_scene() | 
		
	
		
			
				|  |  |                 self.color = COLORS.SUNRAY |  |  |                 self.color = COLORS.SUNRAY | 
		
	
		
			
				|  |  | 
 |  |  | 
 | 
		
	
		
			
				|  |  |                 if win:mouse_pressed("left") then |  |  |                 if win:mouse_pressed("left") then | 
		
	
		
			
				|  |  |                     if state.spawning then |  |  |  | 
		
	
		
			
				|  |  |  |  |  |                     if game_state.spawning then | 
		
	
		
			
				|  |  |                         -- in this case, we don't exactly just send the next wave, we turn the current wave into the next |  |  |                         -- in this case, we don't exactly just send the next wave, we turn the current wave into the next | 
		
	
		
			
				|  |  |                         -- wave, and add the amount of time it would have lasted to the amount of remaining time in the |  |  |                         -- wave, and add the amount of time it would have lasted to the amount of remaining time in the | 
		
	
		
			
				|  |  |                         -- current wave |  |  |                         -- current wave | 
		
	
		
			
				|  |  |                         state.current_wave = state.current_wave + 1 |  |  |  | 
		
	
		
			
				|  |  |  |  |  |                         game_state.current_wave = game_state.current_wave + 1 | 
		
	
		
			
				|  |  | 
 |  |  | 
 | 
		
	
		
			
				|  |  |                         -- calculate spawn chance for next wave |  |  |                         -- calculate spawn chance for next wave | 
		
	
		
			
				|  |  |                         state.spawn_chance = math.log(state.current_wave)/100 + 0.002 |  |  |  | 
		
	
		
			
				|  |  |  |  |  |                         game_state.spawn_chance = math.log(game_state.current_wave)/100 + 0.002 | 
		
	
		
			
				|  |  | 
 |  |  | 
 | 
		
	
		
			
				|  |  |                         state.time_until_next_break = state.time_until_next_break + get_break_time(state.current_wave) |  |  |  | 
		
	
		
			
				|  |  |  |  |  |                         game_state.time_until_next_break = game_state.time_until_next_break + get_break_time(game_state.current_wave) | 
		
	
		
			
				|  |  | 
 |  |  | 
 | 
		
	
		
			
				|  |  |                         play_sfx(SOUNDS.EXPLOSION4) |  |  |                         play_sfx(SOUNDS.EXPLOSION4) | 
		
	
		
			
				|  |  |                     else |  |  |                     else | 
		
	
		
			
				|  |  |                         state.time_until_next_wave = 0 |  |  |  | 
		
	
		
			
				|  |  |  |  |  |                         game_state.time_until_next_wave = 0 | 
		
	
		
			
				|  |  | 
 |  |  | 
 | 
		
	
		
			
				|  |  |                         play_sfx(SOUNDS.EXPLOSION4) |  |  |                         play_sfx(SOUNDS.EXPLOSION4) | 
		
	
		
			
				|  |  |                     end |  |  |                     end | 
		
	
	
		
			
				|  | @ -620,7 +620,7 @@ local function game_scene() | 
		
	
		
			
				|  |  |     end)) |  |  |     end)) | 
		
	
		
			
				|  |  | 
 |  |  | 
 | 
		
	
		
			
				|  |  |     local scene = am.group( |  |  |     local scene = am.group( | 
		
	
		
			
				|  |  |         am.scale(1):tag"world_scale" ^ state.world, |  |  |  | 
		
	
		
			
				|  |  |  |  |  |         am.scale(1):tag"world_scale" ^ game_state.world, | 
		
	
		
			
				|  |  |         am.translate(HEX_GRID_CENTER):tag"cursor_translate" ^ make_hex_cursor(0, COLORS.TRANSPARENT):tag"cursor", |  |  |         am.translate(HEX_GRID_CENTER):tag"cursor_translate" ^ make_hex_cursor(0, COLORS.TRANSPARENT):tag"cursor", | 
		
	
		
			
				|  |  |         score, |  |  |         score, | 
		
	
		
			
				|  |  |         money, |  |  |         money, | 
		
	
	
		
			
				|  | @ -638,11 +638,11 @@ local function game_scene() | 
		
	
		
			
				|  |  |     return scene |  |  |     return scene | 
		
	
		
			
				|  |  | end |  |  | end | 
		
	
		
			
				|  |  | 
 |  |  | 
 | 
		
	
		
			
				|  |  | function update_score(diff) state.score = state.score + diff end |  |  |  | 
		
	
		
			
				|  |  | function update_money(diff) state.money = state.money + diff end |  |  |  | 
		
	
		
			
				|  |  |  |  |  | function update_score(diff) game_state.score = game_state.score + diff end | 
		
	
		
			
				|  |  |  |  |  | function update_money(diff) game_state.money = game_state.money + diff end | 
		
	
		
			
				|  |  | 
 |  |  | 
 | 
		
	
		
			
				|  |  | function game_end() |  |  | function game_end() | 
		
	
		
			
				|  |  |     state = {} |  |  |  | 
		
	
		
			
				|  |  |  |  |  |     game_state = {} | 
		
	
		
			
				|  |  |     game = false |  |  |     game = false | 
		
	
		
			
				|  |  | end |  |  | end | 
		
	
		
			
				|  |  | 
 |  |  | 
 | 
		
	
	
		
			
				|  | @ -653,7 +653,7 @@ end | 
		
	
		
			
				|  |  | 
 |  |  | 
 | 
		
	
		
			
				|  |  | function game_init(saved_state) |  |  | function game_init(saved_state) | 
		
	
		
			
				|  |  |     if saved_state then |  |  |     if saved_state then | 
		
	
		
			
				|  |  |         state = game_deserialize(saved_state) |  |  |  | 
		
	
		
			
				|  |  |  |  |  |         game_state = game_deserialize(saved_state) | 
		
	
		
			
				|  |  | 
 |  |  | 
 | 
		
	
		
			
				|  |  |         if not state then |  |  |         if not state then | 
		
	
		
			
				|  |  |             -- failed to load a save |  |  |             -- failed to load a save | 
		
	
	
		
			
				|  | @ -665,7 +665,7 @@ function game_init(saved_state) | 
		
	
		
			
				|  |  |         -- but you don't have a built tower cursor node, so hovering a buildable tile throws an error |  |  |         -- but you don't have a built tower cursor node, so hovering a buildable tile throws an error | 
		
	
		
			
				|  |  |         select_tower_type(nil) |  |  |         select_tower_type(nil) | 
		
	
		
			
				|  |  |     else |  |  |     else | 
		
	
		
			
				|  |  |         state = get_initial_game_state() |  |  |  | 
		
	
		
			
				|  |  |  |  |  |         game_state = get_initial_game_state() | 
		
	
		
			
				|  |  |     end |  |  |     end | 
		
	
		
			
				|  |  | 
 |  |  | 
 | 
		
	
		
			
				|  |  |     game = true |  |  |     game = true | 
		
	
	
		
			
				|  | 
 |