Untitled

mail@pastecode.io avatar
unknown
php
25 days ago
44 kB
3
Indexable
Never
<?php
	$functions->init = function() {
		// here we're going to create the map
		if ($this->out_of_bounds_tile) {
			// $this->_out_of_bounds_tile = tile($this->out_of_bounds_tile);
			$this->_out_of_bounds_tile = data()->grab($this->out_of_bounds_tile)->from('tile')->get_one();
		} else {
			// $this->_out_of_bounds_tile = tile('nothingness');
			$this->_out_of_bounds_tile = data()->grab('nothingness')->from('tile')->get_one();
		}
		if ( ! isset($this->grid_data) || ! $this->grid_data) {
			$this->grid_data = [];
		}
		$this->_doors = [];
		$this->grid_data = json_decode(json_encode($this->grid_data), true);
		for ($y=0; $y<$this->height; $y++) {
			for ($x=0; $x<$this->width; $x++) {
				$tile = null;
				if (isset($this->grid_data[$x][$y]['tile'])) {
					// $tile = tile($this->grid_data[$x][$y]['tile']);
					$tile = data()->grab($this->grid_data[$x][$y]['tile'])->from('tile')->get_one();
				}
				if ( ! $tile) {
					// $tile = tile('blank');
					$tile = data()->grab('blank')->from('tile')->get_one();
				}
				$this->_grid[$x][$y]['tile']            = $tile;
				$this->_grid[$x][$y]['tile_rendered']   = $tile->render();
				$this->_grid[$x][$y]['exits']           = ($this->grid_data[$x][$y]['exits'] ?? []);
				$this->_grid[$x][$y]['short']           = ($this->grid_data[$x][$y]['short'] ?? null);
				$this->_grid[$x][$y]['long']            = ($this->grid_data[$x][$y]['long'] ?? null);
			}
		}
		$this->_characters = [];
		$this->_items = [];
		$this->_items_list = [];
		$this->place_doors();
		$this->spawn_regions();
	};
	$functions->place_doors = function() {
		for ($y=0; $y<$this->height; $y++) {
			for ($x=0; $x<$this->width; $x++) {
				// place doors
				if (isset($this->grid_data[$x][$y]['doors'])) {
					foreach ($this->grid_data[$x][$y]['doors'] as $door_data) {
						$x = $door_data['x'];
						$y = $door_data['y'];
						$door_id = $door_data['door_id'];
						$direction = $door_data['direction'];
						$reset_interval = $door_data['reset_interval'];
						$this->place_door_at($x, $y, $door_id, $direction, $reset_interval);

						// store it in _doors
						$this->_doors[$x.$y.$door_id.$direction] = $door_data;
					}
				}
			}
		}
	};
	$functions->has_wealth_at = function($x, $y, $amount, $type) {
		foreach ($this->items_at($x, $y) as $item) {
			if ($item->is_currency() && $item->currency_type == lower($type)) {
				if ($amount > 0 && $amount <= $item->amount) {
					return true;
				}
			}
		}
		return false;
	};
	$functions->spawns = function() {
		if ( ! isset($this->spawns)) {
			$this->spawns = [];
		}
		return $this->spawns;
	};
	$functions->add_spawn = function($x, $y, $collection, $id, $spawn) {
		if (isset($spawn['max'])) {
			$max = $spawn['max'];
		} else {
			$spawn['max'] = 1;
		}
		if (isset($spawn['interval'])) {
			$interval = $spawn['interval'];
		} else {
			$spawn['interval'] = 20;
		}
		if (isset($spawn['chance'])) {
			$chance = $spawn['chance'];
		} else {
			$spawn['chance'] = 100;
		}
		if ( ! isset($spawn['setters'])) {
			$spawn['setters'] = [];
		}
		$answer = [];
		$nearby_distance = null;
		if (isset($spawn['nearby_distance'])) {
			$nearby_distance = $spawn['nearby_distance'];
			$tile_count = pow((2 * $nearby_distance + 1), 2);
			if ($spawn['max'] > $tile_count) {
				$answer[] = "Tile count with a ($nearby_distance) nearby_distance is $tile_count tiles. You want to spawn " . $spawn['max'] . " $collection.$id. Not possible.";
			}
		}
		$spawn['x'] = $x;
		$spawn['y'] = $y;
		$spawn['collection'] = $collection;
		$spawn['id'] = $id;
		$spawn['spawn_id'] = uniqid();
		if ( ! database::id_exists_in_collection($collection, $id)) {
			$answer[] = "$collection.$id doesn't exist.";
		}
		if ( ! is_numeric($spawn['max']) || $spawn['max'] < 1) {
			$answer[] = "The max variable must be numeric and greater than 0.";
		}
		if ( ! is_numeric($spawn['interval']) || $spawn['interval'] < 1) {
			$answer[] = "The interval variable must be numeric and greater than 0.";
		}
		if ( ! is_numeric($spawn['chance']) || $spawn['chance'] < 1) {
			$answer[] = "The chance variable must be numeric and greater than 0.";
		}
		if ($nearby_distance) {
			if ( ! is_numeric($nearby_distance) || $nearby_distance < 1) {
				$answer[] = "The nearby_distance variable must be numeric and greater than 0.";
			}
			if ($nearby_distance > 10) {
				$answer[] = "Nearby distance should be 10 or less.";
			}
		}
		if (empty($answer)) {
			$answer['success'] = true;
			$answer[] = "{{069}}Item/NPC{{reset}}        : $collection.$id";
			$answer[] = "{{069}}X/Y{{reset}}             : $x.$y";
			$answer[] = "{{069}}Max{{reset}}             : " . $spawn['max'];
			$answer[] = "{{069}}Interval{{reset}}        : " . $spawn['interval'] . " minute(s)";
			$answer[] = "{{069}}Chance{{reset}}          : " . $spawn['chance'] . "%";
			if (isset($spawn['setters']) && ! empty($setters)) {
				$setters_array = [];
				foreach ($setters as $variable => $value) {
					$setters_array[] = "{{069}}$variable{{reset}} = $value";
				}
				$answer[] = "{{069}}Setters{{reset}}         : " . implode(", ", $setters_array);
			}
			if (isset($spawn['reset_function'])) {
				$answer[] = "{{069}}Reset function{{reset}}  : " . $spawn['reset_function'];
			}
			if ($nearby_distance) {
				$answer[] = "{{069}}Nearby distance{{reset}} : $nearby_distance";
			}
			$this->spawns[$x.$y.$collection.$id] = $spawn;
		} else {
			$answer['failed'] = true;
		}
		return $answer;
	};
	$functions->remove_spawn = function($x, $y, $collection, $id) {
		if (isset($this->spawns[$x.$y.$collection.$id])) {
			unset($this->spawns[$x.$y.$collection.$id]);
		}
	};
	$functions->spawns_at = function($x, $y) {
		$spawns = [];
		foreach ($this->spawns as $spawn) {
			if ($spawn['x'] == $x && $spawn['y'] == $y) {
				$spawns[] = $spawn;
			}
		}
		return $spawns;
	};
	$functions->has_spawn = function($x, $y, $collection, $id) {
		if (isset($this->spawns[$x.$y.$collection.$id])) {
			return true;
		}
		return false;
	};
	$functions->spawn = function() {
		$minutes = gametick::$minutes;
		if (isset($this->spawns) && is_array($this->spawns)) {
			foreach ($this->spawns as $key => $spawn) {
				$max = $spawn['max'];
				$interval = $spawn['interval'];
				$chance = $spawn['chance'];
				$setters = null;
				if (isset($spawn['setters'])) {
					$setters = $spawn['setters'];
				}
				$reset_function = null;
				if (isset($spawn['reset_function'])) {
					$reset_function = $spawn['reset_function'];
				}
				$nearby_distance = null;
				if (isset($spawn['nearby_distance'])) {
					$nearby_distance = $spawn['nearby_distance'];
				}
				$x          = $spawn['x'];
				$y          = $spawn['y'];
				$collection = $spawn['collection'];
				$id         = $spawn['id'];
				$spawn_id   = $spawn['spawn_id'];
				if (database::id_exists_in_collection($collection, $id)) {
					if ($minutes % $interval == 0) {
						$rand = rand(1, 100);
						if ($rand <= $chance) {
							if ($collection == 'item') {
								// adding nearby
								if ($nearby_distance) {
									$existing_items = [];
									$coordinates = $this->get_box_around_coordinates($x, $y, $nearby_distance);
									$items = $this->items_in_coordinates_list($coordinates);
									foreach ($items as $item) {
										if ($item->is_collection_id("$collection.$id")) {
											if (isset($item->spawn_id) && $item->spawn_id == $spawn_id) {
												$existing_items[] = $item;
											}
											// unset from the coordinates so we don't use it when placing
											$owner_x = $item->_owner['x'];
											$owner_y = $item->_owner['y'];
											unset($coordinates[$owner_x.$owner_y]);
											if ($reset_function && $item->has_function($reset_function)) {
												if (isset($item->spawn_id) && $item->spawn_id == $spawn_id) {
													$item->$reset_function();
												}
											}
										}
									}
									// remove solid/impassable tiles from the coordinates
									foreach ($coordinates as $xy => $coordinate) {
										if ( ! $this->character_can_enter($coordinate['x'], $coordinate['y'])) {
											unset($coordinates[$xy]);
										}
									}
									$count = $max - count($existing_items);
									if ($count > 0) {
										$place_at = (array)array_rand($coordinates, $count);
										foreach ($place_at as $xy_key) {
											$item = data()->grab($id)->from('item')->from_database()->get_one();
											if ( ! empty($setters)) {
												foreach ($setters as $variable => $value) {
													$item->$variable = $value;
												}
											}
											$item->spawn_id = $spawn_id;
											$this->add_item($item, $coordinates[$xy_key]['x'], $coordinates[$xy_key]['y']);
											if (isset($reset_function) && $item->has_function($reset_function)) {
												if (isset($item->spawn_id) && $item->spawn_id == $spawn_id) {
													$item->$reset_function();
												}
											}
										}
									}
								} else {
									$existing_items = [];
									foreach ($this->items_at($x, $y) as $item) {
										if ($item->is_collection_id("$collection.$id")) {
											if (isset($item->spawn_id) && $item->spawn_id == $spawn_id) {
												$existing_items[] = $item;
											}
											if ($reset_function && $item->has_function($reset_function)) {
												$item->$reset_function();
											}
										}
									}
									$count = $max - count($existing_items);
									for ($i=0; $i<$count; $i++) {
										$item = data()->grab($id)->from('item')->from_database()->get_one();
										$item->spawn_id = $spawn_id;
										$this->add_item($item, $x, $y);
										if ($reset_function && $item->has_function($reset_function)) {
											if (isset($item->spawn_id) && $item->spawn_id == $spawn_id) {
												$item->$reset_function();
											}
										}
									}
								}
							} else if ($collection == 'npc') {
								// adding nearby
								if ($nearby_distance) {
									$existing_npcs = [];
									$coordinates = $this->get_box_around_coordinates($x, $y, $nearby_distance);
									$npcs = $this->npcs_in_coordinates_list($coordinates);
									foreach ($npcs as $npc) {
										if ($npc->is_collection_id("$collection.$id")) {
											if (isset($npc->spawn_id) && $npc->spawn_id == $spawn_id) {
												$existing_npcs[] = $npc;
											}
											// unset from the coordinates so we don't use it when placing
											$location_x = $npc->x;
											$location_y = $npc->y;
											unset($coordinates[$location_x.$location_y]);
											if ($reset_function && $npc->has_function($reset_function)) {
												if (isset($npc->spawn_id) && $npc->spawn_id == $spawn_id) {
													$npc->$reset_function();
												}
											}
										}
									}
									// remove solid/impassable tiles from the coordinates
									foreach ($coordinates as $xy => $coordinate) {
										if ( ! $this->character_can_enter($coordinate['x'], $coordinate['y'])) {
											unset($coordinates[$xy]);
										}
									}
									$count = $max - count($existing_npcs);
									if ($count > 0) {
										$place_at = (array)array_rand($coordinates, $count);
										foreach ($place_at as $xy_key) {
											$npc = data()->grab($id)->from('npc')->from_database()->get_one();
											$npc->spawn($coordinates[$xy_key]['x'], $coordinates[$xy_key]['y'], $this->identifier);
											if ( ! empty($setters)) {
												foreach ($setters as $variable => $value) {
													$npc->$variable = $value;
												}
											}
											$npc->spawn_id = $spawn_id;
											//$this->add_item($npc, $coordinates[$xy_key]['x'], $coordinates[$xy_key]['y']);
											if (isset($reset_function) && $npc->has_function($reset_function)) {
												if (isset($npc->spawn_id) && $npc->spawn_id == $spawn_id) {
													$npc->$reset_function();
												}
											}
										}
									}
								} else {
									$existing_npcs = [];
									foreach ($this->npcs_at($x, $y) as $npc) {
										if ($npc->is_collection_id("$collection.$id")) {
											if (isset($npc->spawn_id) && $npc->spawn_id == $spawn_id) {
												$existing_npcs[] = $npc;
											}
											if ($reset_function && $npc->has_function($reset_function)) {
												$npc->$reset_function();
											}
										}
									}
									$count = $max - count($existing_npcs);
									for ($i=0; $i<$count; $i++) {
										$npc = data()->grab($id)->from('npc')->from_database()->get_one();
										$npc->spawn_id = $spawn_id;
										$npc->spawn($x, $y, $this->identifier);
										if ($reset_function && $npc->has_function($reset_function)) {
											if (isset($npc->spawn_id) && $npc->spawn_id == $spawn_id) {
												$npc->$reset_function();
											}
										}
									}
								}
//								$existing_npcs = [];
//								foreach ($this->npcs_at($x, $y) as $npc) {
//									if ($npc->is_collection_id("$collection.$id")) {
//										// recreate the npc so it resets
//										// $npc->reset();
//										$existing_npcs[] = $npc;
//									}
//								}
//								$count = $max - count($existing_npcs);
//								for ($i=0; $i<$count; $i++) {
//									$npc = data()->grab($id)->from('npc')->from_database()->get_one();
//									$npc->spawn($x, $y, $this->_id);
//								}
							}
						}
					}
				} else {
					unset($this->spawns[$key]);
				}
			}
		}
		// reset doors, but only if there's no other players nearby
		foreach ($this->doors() as $door) {
			if ($minutes % $door->reset_interval == 0) {
				if (isset($door->_owner) && is_array($door->_owner)) {
					$x = $door->_owner['x'];
					$y = $door->_owner['y'];
					if (empty($this->characters_near($x, $y, 25))) {
						if (isset($door->default_state)) {
							$door->set_state($door->default_state);
						}
					}
				}
			}
		}
		if ($this->has_function('on_spawn')) {
			$this->on_spawn();
		}
	};
	$functions->spawn_regions = function() {
		foreach ($this->regions() as $region) {
			if ($region->has_function('respawn')) {
				$region->respawn();
			}
		}
	};
	$functions->obstacles_along_path = function($path, $start_x, $start_y) {
		$current_x = $start_x;
		$current_y = $start_y;
		$doors = [];
		foreach ($path as $direction) {
			$door = $this->door_in_direction($current_x, $current_y, $direction);
			if ($door) {
				$state = $door->state();
				if ($state == 'closed' || $state == 'locked') {
					$doors[] = $door;
				}
			}
			$coordinates = $this->coordinates_from_cardinal_direction($current_x, $current_y, $direction);
			$current_x = $coordinates['x'];
			$current_y = $coordinates['y'];
		}
		return $doors;
	};
	$functions->coordinates_from_cardinal_direction = function($x, $y, $direction) {
		$direction = lower($direction);
		$direction = cardinal($direction);
		if ($direction) {
			if ($direction == 'north')     { $y--; }
			if ($direction == 'south')     { $y++; }
			if ($direction == 'east')      { $x++; }
			if ($direction == 'west')      { $x--; }
			if ($direction == 'northeast') { $y--; $x++; }
			if ($direction == 'northwest') { $y--; $x--; }
			if ($direction == 'southeast') { $y++; $x++; }
			if ($direction == 'southwest') { $y++; $x--; }
		}
		return ['x' => $x, 'y' => $y];
	};

	$functions->items = function() {
		return $this->_items_list;
	};
	/* doors */
	$functions->doors = function() {
		$doors = [];
		foreach ($this->items() as $item) {
			if ($item->is_door()) {
				$doors[] = $item;
			}
		}
		return $doors;
	};
	$functions->has_door_direction_at = function($x, $y, $direction) {
		foreach ($this->doors_at($x, $y) as $door) {
			if ($door->direction == $direction) {
				return true;
			}
		}
		return false;
	};
	$functions->doors_at = function($x, $y) {
		$doors = [];
		foreach ($this->items_at($x, $y) as $item) {
			if ($item->is_door()) {
				$doors[] = $item;
			}
		}
		return $doors;
	};
	$functions->door_in_direction = function($x, $y, $direction) {
		foreach ($this->doors_at($x, $y) as $door) {
			if ($door->direction == $direction) {
				return $door;
			}
		}
		return null;
	};
	$functions->has_stored_door_in_direction = function($x, $y, $direction) {
		if (isset($this->grid_data[$x][$y]['doors'])) {
			foreach ($this->grid_data[$x][$y]['doors'] as $door_data) {
				if ($door_data['direction'] == $direction) {
					return true;
				}
			}
		}
		return false;
	};
	// need to store the $x, $y, $door_id, $direction and some form of group_id
	$functions->store_door_at = function($x, $y, $door_id, $direction, $reset_interval=10) {
		if ($this->within_bounds($x, $y)) {
			$exists = false;
			if ( ! isset($this->grid_data[$x][$y]['doors'])) {
				$this->grid_data[$x][$y]['doors'] = [];
			}
			foreach ($this->grid_data[$x][$y]['doors'] as $key => $door_data) {
				if ($door_data['direction'] == $direction) {
					$exists = true;
				}
			}
			if ( ! $exists) {
				$door_data = ['x'              => $x,
				              'y'              => $y,
				              'door_id'        => $door_id,
				              'direction'      => $direction,
							  'reset_interval' => $reset_interval];
				$this->grid_data[$x][$y]['doors'][] = $door_data;
				$this->_doors[$x.$y.$door_id.$direction] = $door_data;
				return true;
			}
		}
		return false;
	};
	$functions->unstore_door_at = function($x, $y, $direction) {
		if (isset($this->grid_data[$x][$y]['doors'])) {
			foreach ($this->grid_data[$x][$y]['doors'] as $key => $door_data) {
				if ($door_data['direction'] == $direction) {
					unset($this->grid_data[$x][$y]['doors'][$key]);
					// remove it from _doors
					if (isset($this->_doors[$x.$y.$door_data['door_id'].$direction])) {
						unset($this->_doors[$x.$y.$door_data['door_id'].$direction]);
					}
					return true;
				}
			}
		}
		return false;
	};
	$functions->place_door_at = function($x, $y, $door_id, $direction, $reset_interval=10) {
		$direction = lower($direction);
		$direction = cardinal($direction);
		if ($direction) {
			$reverse_direction = reverse_cardinal($direction);
			if ($reverse_direction) {
				if ($this->within_bounds($x, $y)) {
					$adjacent_coordinates = $this->coordinates_from_cardinal_direction($x, $y, $direction);
					$adjacent_x = $adjacent_coordinates['x'];
					$adjacent_y = $adjacent_coordinates['y'];
					if ($this->within_bounds($adjacent_x, $adjacent_y)) {
						if (database::id_exists_in_collection('item', $door_id)) {
							if ( ! $this->has_door_direction_at($x, $y, $direction) &&
								 ! $this->has_door_direction_at($adjacent_x, $adjacent_y, $reverse_direction)) {
								$door                        = data()->grab($door_id)->from('item')->from_database()->get_one();
								$linked_door                 = data()->grab($door_id)->from('item')->from_database()->get_one();

								$door->linked_door           = $linked_door;
								$door->direction             = $direction;
								$door->reset_interval        = $reset_interval;

								$linked_door->linked_door    = $door;
								$linked_door->direction      = $reverse_direction;
								$linked_door->reset_interval = $reset_interval;

								$this->add_item($door, $x, $y);
								$this->add_item($linked_door, $adjacent_x, $adjacent_y);
							}
						}
					}
				}
			}
		}
	};
//	$functions->stamp = function($size, $num_points, $intensity, $center_x, $center_y, $tiles=[]) {
//		for ($i=0; $i<$intensity; $i++) {
//			$scatter_points = generate_scatter_points($center_x, $center_y, $size, $num_points);
//			foreach ($scatter_points as $point) {
//				$x = $point['x'];
//				$y = $point['y'];
//				if ($this->within_bounds($x, $y)) {
//					// $this->grid[$x][$y]['tile'] = tile($tiles[array_rand($tiles)]);
//					$this->grid[$x][$y]['tile'] = data()->grab($tiles[array_rand($tiles)])->from('tile')->get_one();
//				}
//			}
//		}
//	};

	// what happens when any character moves on the map
	$functions->character_moved = function($character) {
		$nearby_characters = $this->nearby_characters($character->x, $character->y, null, 18, 9, false);
		foreach ($nearby_characters as $nearby_character) {
			if ($nearby_character->is('npc')) {
				$nearby_character->nearby_notice_check();
			}
		}
	};
	$functions->character_can_go_cardinal = function($character, $direction) {
		$x = $character->x;
		$y = $character->y;
		if ($direction == 'north')     { $y--; }
		if ($direction == 'south')     { $y++; }
		if ($direction == 'east')      { $x++; }
		if ($direction == 'west')      { $x--; }
		if ($direction == 'northeast') { $y--; $x++; }
		if ($direction == 'northwest') { $y--; $x--; }
		if ($direction == 'southeast') { $y++; $x++; }
		if ($direction == 'southwest') { $y++; $x--; }
		if ($this->character_can_enter($x, $y, $character)) {
			return true;
		}
		return false;
	};
	$functions->distance_between = function($x1, $y1, $x2, $y2) {
	    $dx = abs($x2 - $x1);
	    $dy = abs($y2 - $y1);
		return max($dx, $dy);
	};
	$functions->regions = function() {
		return data()->from('region')->where('map', $this->_id)->get_many();
	};
	$functions->regions_from_coordinates = function($x, $y) {
		$regions = [];
		foreach ($this->regions() as $region) {
			$left = min($region->lower_left_x, $region->top_right_x);
			$right = max($region->lower_left_x, $region->top_right_x);
			$bottom = min($region->lower_left_y, $region->top_right_y);
			$top = max($region->lower_left_y, $region->top_right_y);
			if ($x >= $left && $x <= $right && $y >= $bottom && $y <= $top) {
				$regions[] = $region;
			}
		}
		return $regions;
	};
	$functions->set_tile = function($x, $y, $tile_id) {
		$tile = data()->grab($tile_id)->from('tile')->get_one();
		if ($tile) {
			$this->_grid[$x][$y]['tile_rendered'] = $tile->render();
			$this->_grid[$x][$y]['tile']          = $tile;
			$this->grid_data[$x][$y]['tile']     = $tile_id;
			return true;
		} else {
			return false;
		}
	};
	$functions->add_exit = function($x, $y, $direction, $target_map, $target_x, $target_y) {
		// $map = map($target_map);
		if (database::id_exists_in_collection('map', $target_map)) {
			$map = data()->grab($target_map)->from('map')->get_one();
			if ($map) {
				if ($map->within_bounds($target_x, $target_y)) {
					$exit = ['map_id' => $target_map, 'x' => $target_x, 'y' => $target_y];
					$this->grid_data[$x][$y]['exits'][$direction] = $exit;
					$this->_grid[$x][$y]['exits'][$direction] = $exit;
					return true;
				}
			}
		}
		return false;
	};
	$functions->set_long = function($x, $y, $long) {
		$this->_grid[$x][$y]['long'] = $long;
		$this->grid_data[$x][$y]['long'] = $long;
	};
	$functions->set_dark = function($x, $y) {
		$this->_grid[$x][$y]['dark'] = true;
		$this->grid_data[$x][$y]['dark'] = true;
	};
	$functions->set_light = function($x, $y) {
		if (isset($this->_grid[$x][$y]['dark'])) {
			unset($this->_grid[$x][$y]['dark']);
		}
		if (isset($this->grid_data[$x][$y]['dark'])) {
			unset($this->grid_data[$x][$y]['dark']);
		}
	};
	$functions->is_dark = function($x, $y, $looker=null) {
		if (isset($this->_grid[$x][$y]['dark']) && $this->_grid[$x][$y]['dark']) {
			// loop through characters
			foreach ($this->characters_at($x, $y) as $character) {
				if ($character->has_luminosity()) {
					return false;
				}
			}
			// loop through items
			foreach ($this->items_at($x, $y) as $item) {
				if ($item->has_luminosity()) {
					return false;
				}
			}
			return true;
		}
		return false;
	};
	$functions->editable = function() {
		if (isset($this->_instance) && $this->_instance) {
			return false;
		}
		return true;
	};
	$functions->long = function($x, $y) {
		if (isset($this->_grid[$x][$y]['long']) && $this->_grid[$x][$y]['long'] != "" && $this->_grid[$x][$y]['long'] != null) {
			return $this->_grid[$x][$y]['long'];
		}
		return null;
	};
	$functions->exit = function($x, $y, $direction) {
		if (isset($this->_grid[$x][$y]['exits'][$direction])) {
			return $this->_grid[$x][$y]['exits'][$direction];
		}
		return null;
	};
	$functions->has_exit = function($x, $y, $direction) {
		if (isset($this->_grid[$x][$y]['exits'][$direction])) {
			return true;
		}
		return false;
	};
	$functions->remove_exit = function($x, $y, $direction) {
		if (isset($this->grid_data[$x][$y]['exits'][$direction]) &&
			isset($this->_grid[$x][$y]['exits'][$direction]))
		{
			unset($this->grid_data[$x][$y]['exits'][$direction]);
			unset($this->_grid[$x][$y]['exits'][$direction]);
			return true;
		}
		return false;
	};
	$functions->within_bounds = function($x, $y) {
		if (isset($this->_grid[$x][$y])) return true;
		return false;
	};
	$functions->los = function($start_x, $start_y, $end_x, $end_y) {
		$cx = $end_x - $start_x;
		$cy = $end_y - $start_y;
		$direction = null;
		// Determine the cardinal direction
        if ($cx == 1 && $cy == 0) {
            $direction = "east"; // Moving right
        } elseif ($cx == -1 && $cy == 0) {
            $direction = "west"; // Moving left
        } elseif ($cx == 0 && $cy == 1) {
            $direction = "south"; // Moving down
        } elseif ($cx == 0 && $cy == -1) {
            $direction = "north"; // Moving up
        } elseif ($cx == 1 && $cy == 1) {
            $direction = "southeast"; // Moving down-right
        } elseif ($cx == 1 && $cy == -1) {
            $direction = "northeast"; // Moving up-right
        } elseif ($cx == -1 && $cy == 1) {
            $direction = "southwest"; // Moving down-left
        } elseif ($cx == -1 && $cy == -1) {
            $direction = "northwest"; // Moving up-left
        }
		// Check if the end coordinates are only 1 tile away
		if ($cx <= 1 && $cy <= 1) {
			$door = $this->door_in_direction($start_x, $start_y, $direction);
			if ($door) {
				if ($door->state() == "locked" || $door->state() == "closed") {
					return false;
				}
			}
		}
	    $dx = abs($end_x - $start_x);
	    $dy = abs($end_y - $start_y);
	    $sx = ($start_x < $end_x) ? 1 : -1;
	    $sy = ($start_y < $end_y) ? 1 : -1;
	    $err = $dx - $dy;
		$first_tile = true;
	    while ($start_x != $end_x || $start_y != $end_y) {
			if ( ! $first_tile) {
		        if (isset($this->_grid[$start_x][$start_y]['tile']) && $this->_grid[$start_x][$start_y]['tile']->blocks_los) {
		            return false;
		        }
				// add for items with blocking here
				foreach ($this->items_at($start_x, $start_y) as $item) {
					if (isset($item->blocks_los) && $item->blocks_los) {
						return false;
					}
				}
				foreach ($this->doors_at($start_x, $start_y) as $door) {
					if ($door->state() == "locked" || $door->state() == "closed") {
						return false;
					}
				}
			}
			$first_tile = false;
	        $e2 = 2 * $err;
	        if ($e2 > -$dy) {
	            $err -= $dy;
	            $start_x += $sx;
	        }
	        if ($e2 < $dx) {
	            $err += $dx;
	            $start_y += $sy;
	        }
	    }
	    return true;
	};

	$functions->characters_in_coordinates_list = function($list) {
		$characters = [];
		foreach ($this->_characters as $character) {
			if (isset($list[$character->x . $character->y])) {
				$characters[] = $character;
			}
		}
		return $characters;
	};
	$functions->npcs_in_coordinates_list = function($list) {
		$characters = [];
		foreach ($this->_characters as $character) {
			if (isset($list[$character->x . $character->y])) {
				if ($character->is('npc')) {
					$characters[] = $character;
				}
			}
		}
		return $characters;
	};
	$functions->items_in_coordinates_list = function($list) {
		$items = [];
		foreach ($this->items() as $item) {
			if (isset($item->_owner['x']) && isset($item->_owner['y'])) {
				$x = $item->_owner['x'];
				$y = $item->_owner['y'];
				if (isset($list[$x.$y])) {
					$items[] = $item;
				}
			}
		}
		return $items;
	};

	$functions->render = function($current_x, $current_y, $looker=null, $view_distance_x=14, $view_distance_y=7, $with_nearby=true, $highlight=[]) {
		// $use_los = true;
		if ($looker && $looker->is_administrator()) {
			$view_distance_x=60;
			$view_distance_y=18;
			// $use_los = true;
		}
		$lowest_x = $current_x - $view_distance_x;
		$highest_x = $current_x + $view_distance_x;
		$lowest_y = $current_y - $view_distance_y;
		$highest_y = $current_y + $view_distance_y;

		$x_center = ($lowest_x + $highest_x) / 2;
		$y_center = ($lowest_y + $highest_y) / 2;

		$map = [];
		if (isset($this->_grid[$current_x][$current_y]['short'])) {
			$short = $this->_grid[$current_x][$current_y]['short'];
			$map[] = $short;
		}

		// $marker_positions = $this->marker_positions($lowest_x, $lowest_y, $highest_x, $highest_y);
		$character_positions = $this->character_positions_within_bounds($lowest_x, $lowest_y, $highest_x, $highest_y);
		$item_positions = $this->item_positions_within_bounds($lowest_x, $lowest_y, $highest_x, $highest_y);
		$map_keys = [];
		$marker_counter = $view_distance_y;
		$rendered_out_of_bounds_tiles = [$this->_out_of_bounds_tile->render(),
										 $this->_out_of_bounds_tile->render(),
										 $this->_out_of_bounds_tile->render(),
			                             $this->_out_of_bounds_tile->render()];
		for ($y=$lowest_y; $y<=$highest_y; $y++) {
			$row = "";
			for ($x=$lowest_x; $x<=$highest_x; $x++) {
				if (isset($this->_grid[$x][$y])) {
					// $los = true;
					// if ($use_los) $los = $this->los($current_x, $current_y, $x, $y);
					// if ($los) {
						if ($x == $x_center && $y == $y_center) {
							$row .= "{{cyan3}}x{{reset}}";
						} else {
							if ($this->is_dark($x, $y)) {
								$row .= "{{bg234}} {{reset}}";
							} else if (isset($character_positions[$x][$y]) && $looker->los_to_xy($x, $y)) {
								$characters = $character_positions[$x][$y];
								foreach ($characters as $key => $character) {
									if ($character->invis()) {
										unset($characters[$key]);
									}
								}
								$characters = array_values($characters);
								if ( ! empty($characters)) {
									$character = $characters[0];
									$row .= $character->marker();
									// add map key if it exists
									if ($character->has_function('map_key')) {
										$map_key = $character->map_key();
										if (isset($map_key['key']) && isset($map_key['text'])) {
											$key = $map_key['key'];
											$text = $map_key['text'];
											$map_keys[] = "$key - $text";
										}
									}
								} else {
									// just render instead, if no characters found
									$row .= $this->_grid[$x][$y]['tile_rendered'];
								}
							} else if (isset($item_positions[$x][$y]) && $looker->los_to_xy($x, $y)) {
								$items = $item_positions[$x][$y];
								foreach ($items as $key => $item) {
									if (isset($item->shows_on_map) && ! $item->shows_on_map) {
										unset($items[$key]);
									}
								}
								$items = array_values($items);
								if ( ! empty($items)) {
									$item = $items[0];
									$row .= $item->marker();
									// add map key if it exists
									if ($item->has_function('map_key')) {
										$map_key = $item->map_key();
										if (isset($map_key['key']) && isset($map_key['text'])) {
											$key = $map_key['key'];
											$text = $map_key['text'];
											$map_keys[] = "$key - $text";
										}
									}
								} else {
									// just render instead, if no items found
									$row .= $this->_grid[$x][$y]['tile_rendered'];
								}
							} else if ( ! empty($highlight) && isset($highlight[$x.$y]['color']) && isset($highlight[$x.$y]['character'])) {
								$color = $highlight[$x.$y]['color'];
								$character = $highlight[$x.$y]['character'];
								$row .= "{{" . $color . "}}" . $character . "{{reset}}";
							} else {
								$row .= $this->_grid[$x][$y]['tile_rendered'];
							}
						}
					// } else {
						// $row .= "{{grey93}}#{{reset}}";
					// }
				} else {
					$row .= $rendered_out_of_bounds_tiles[array_rand($rendered_out_of_bounds_tiles)]; // blank space in the void, "out of bounds"
				}
			}
			$show_int = abs($marker_counter);
			if ($show_int < 10) $show_int = "0$show_int";
			$map[] = $row . " {{artifact}}[{{reset}}$show_int{{artifact}}]{{reset}}";
			$marker_counter--;
		}
		if (isset($this->_instance) && $this->_instance) {
			if ($looker->is_administrator()) {
				$map[] = "{{075}}(wiz_data) instance of $this->_id: $this->_instance_id{{reset}}";
			}
		}
		if ($this->show_coordinates) {
			$map[] = "{{artifact}}Coordinates: $current_x, $current_y{{reset}}";
		}
		if ($this->long($current_x, $current_y)) {
			$map[] = $this->long($current_x, $current_y);
		}
		$doors = [];
		$items_list = [];
		foreach ($this->items_at($current_x, $current_y) as $item) {
			if ($item->is_door()) {
				$doors[] = "The " . $item->short() . " leading " . $item->direction . " is " . $item->state() . ".";
			} else if ( ! $item->is_decoration()) {
				if ($item->is_chest()) {
					$items_list[] = "   " . $item->short() . " (" . $item->state() . ")";
				} else {
					$items_list[] = "   " . $item->short();
				}
			}
		}
		foreach ($doors as $door) {
			$map[] = $door;
		}
		$map[] = "";
		if ($with_nearby) {
			$nearby_characters = $this->nearby_characters($current_x, $current_y, $looker, $view_distance_x, $view_distance_y);
			if ( ! empty($nearby_characters)) {
				$names = [];
				foreach ($nearby_characters as $character) {
					if ($looker->los_to_character($character) && ! $character->invis()) {
						$names[] = $character->name;
					}
				}
				if (count($names) == 1) {
					$map[] = wrap("{{c}}You notice that {{reset}}[{{W}}" . dlist($names) . "{{reset}}]{{c}} is nearby.{{reset}}", 4);
				} else if (count($names) > 1) {
					$map[] = wrap("{{c}}You notice that {{reset}}[{{W}}" . dlist($names) . "{{reset}}]{{c}} are nearby.{{reset}}", 4);
				}
			} else {
				$map[] = "{{c}}There is {{reset}}[{{W}}no one{{reset}}]{{c}} discernable nearby.{{reset}}";
			}
		}
		if (isset($this->_grid[$current_x][$current_y]['exits'])) {
			$exits = [];
			foreach ($this->_grid[$current_x][$current_y]['exits'] as $direction => $exit_data) {
				$exits[] = $direction;
			}
			if (count($exits) == 1) {
				$map[] = "{{green3}}There is an additional exit here: {{reset}}[{{W}}" . dlist($exits) . "{{reset}}]";
			} else if (count($exits) > 1) {
				$map[] = "{{green3}}There are additional exits here: {{reset}}[{{W}}" . dlist($exits) . "{{reset}}]";
			}
		}
		$contents = [];
		foreach ($items_list as $item) {
			$contents[] = $item;
		}
		foreach ($this->characters_at($current_x, $current_y) as $character) {
			if ($character !== $looker) {
				$short = "";
				if ($character->is('character')) {
					$short = $character->short();
				}
				if ($character->is('npc')) {
					$short = $character->short();
				}
				if ($character->in_combat()) {
					$short = $short . " [in combat]";
				}
				$contents[] = "   $short";
			}
		}
		if ( ! empty($contents)) {
			$map[] = "";
			$map[] = lined($contents);
		}
		$map[] = "";
		if ( ! empty($map_keys)) {
			$map[0] .= "    {{artifact}}Map Key{{reset}}";
			$map[1] .= "    {{015}}~~~~~~~{{reset}}";
			$start_key = 2;
			foreach ($map_keys as $map_key) {
				$map[$start_key] .= "    $map_key";
				$start_key++;
			}
		}
		return lined($map);
	};

	$functions->solid_tiles_around_box = function($center_x, $center_y, $distance) {
		$coordinates = $this->get_box_around_coordinates($center_x, $center_y, $distance);
		$solid_tiles = [];
		foreach ($coordinates as $coordinate) {
			$x = $coordinate['x'];
			$y = $coordinate['y'];
			// tile cannot be passed
			if ( ! isset($this->_grid[$x][$y]['tile']->passable) ||
				(isset($this->_grid[$x][$y]['tile']->passable) && ! $this->_grid[$x][$y]['tile']->passable)) {
				$solid_tiles[$x.$y] = ['x' => $x, 'y' => $y];
			}
		}
		return $solid_tiles;
	};
	$functions->character_can_enter = function($x, $y, $character=null) {
		if ( ! $this->within_bounds($x, $y)) return false;
		if ($character && $character->is_administrator()) return true;
		if ( ! isset($this->_grid[$x][$y])) {
			return false;
		}
		if (isset($this->_grid[$x][$y]['tile']->passable) && $this->_grid[$x][$y]['tile']->passable) {
			return true;
		}
		return false;
	};

	$functions->add_character = function($character) {
		if ($character->is('npc')) {
			// store for later usage (tick, etc)
			data()->store_in('npcs', $character);
		}
		$this->_characters[] = $character;
	};
	$functions->remove_character = function($search) {
		foreach ($this->_characters as $key => $character) {
			if ($character === $search) {
				// remove from npcs:: if it's an npc
				if ($character->is('npc')) {
					data()->unstore_from('npcs', $character);
				}
				unset($this->_characters[$key]);
			}
		}
	};
	$functions->characters_at = function($x, $y) {
		$characters = [];
		foreach ($this->_characters as $character) {
			if ($character->x == $x && $character->y == $y) {
				$characters[] = $character;
			}
		}
		return $characters;
	};
	$functions->npcs_at = function($x, $y) {
		$npcs = [];
		foreach ($this->characters_at($x, $y) as $character) {
			if ($character->is('npc')) {
				$npcs[] = $character;
			}
		}
		return $npcs;
	};
	$functions->add_item = function($item, $x, $y) {
		// set the owner to this location
		$item->_owner = ["map" => $this,
						 "x"   => $x,
						 "y"   => $y];
		$this->_items[$x][$y][$item->uniqueid] = $item;
		$this->_items_list[$item->uniqueid] = $item;
		if ($item->has_function('picked_up')) {
			$item->picked_up();
		}
	};
	$functions->get_coordinates_in_sphere = function($centerX, $centerY, $radius) {
	    $coordinates = [];
	    // Iterate through the range of x and y values
	    for ($x = $centerX - $radius; $x <= $centerX + $radius; $x++) {
	        for ($y = $centerY - $radius; $y <= $centerY + $radius; $y++) {
	            // Calculate the distance from the center
	            $distance = sqrt(pow($x - $centerX, 2) + pow($y - $centerY, 2));
	            // If the distance is within the radius, add the coordinate to the list
	            if ($distance <= $radius) {
	                $coordinates[$x.$y] = ['x' => $x, 'y' => $y];
	            }
	        }
	    }
	    return $coordinates;
	};
	$functions->get_box_around_coordinates = function($center_x, $center_y, $distance) {
		if ($this->within_bounds($center_x, $center_y)) {
		    $coordinates = [];
		    for ($i = -$distance; $i <= $distance; $i++) {
		        for ($j = -$distance; $j <= $distance; $j++) {
		            $x = $center_x + $i;
		            $y = $center_y + $j;
		            // Exclude the center point if needed
//		            if ( ! ($i == 0 && $j == 0)) {
			        $coordinates[$x.$y] = ['x' => $x, 'y' => $y];
//		            }
		        }
		    }
		    return $coordinates;
		}
		return [];
	};
	$functions->get_coordinates_in_box = function($x1, $y1, $x2, $y2) {
		if ($this->within_bounds($x1, $y1) && $this->within_bounds($x2, $y2)) {
		    $coordinates = [];
		    $min_x = min($x1, $x2);
		    $max_x = max($x1, $x2);
		    $min_y = min($y1, $y2);
		    $max_y = max($y1, $y2);
		    for ($x=$min_x; $x<=$max_x; $x++) {
		        for ($y=$min_y; $y<=$max_y; $y++) {
		            $coordinates[$x.$y] = ['x' => $x, 'y' => $y];
		        }
		    }
		    return $coordinates;
		}
		return [];
	};
	$functions->remove_item = function($item, $x, $y) {
		if (isset($this->_items[$x][$y][$item->uniqueid])) {
			unset($this->_items[$x][$y][$item->uniqueid]);
			if (isset($this->_items_list[$item->uniqueid])) {
				unset($this->_items_list[$item->uniqueid]);
			}
			return true;
		}
		return false;
	};
	$functions->items_at = function($x, $y) {
		if (isset($this->_items[$x][$y])) {
			return $this->_items[$x][$y];
		}
		return [];
	};

	// $functions->marker_positions = function($lowest_x, $lowest_y, $highest_x, $highest_y) { };
	$functions->character_positions_within_bounds = function($lowest_x, $lowest_y, $highest_x, $highest_y) {
		$positions = [];
		foreach ($this->_characters as $character) {
			if ($character->x >= $lowest_x &&
				$character->y >= $lowest_y &&
				$character->x <= $highest_x &&
				$character->y <= $highest_y) {
				$positions[$character->x][$character->y][] = $character;
			}
		}
		return $positions;
	};
	$functions->item_positions_within_bounds = function($lowest_x, $lowest_y, $highest_x, $highest_y) {
		$x_range = range($lowest_x, $highest_x);
		$y_range = range($lowest_y, $highest_y);
		$positions = [];
		foreach ($x_range as $x) {
			foreach ($y_range as $y) {
				if (isset($this->_items[$x][$y]) && ! empty($this->_items[$x][$y])) {
					$keys = array_keys($this->_items[$x][$y]);
					$items = [];
					foreach ($keys as $uniqueid) {
						$items[] = $this->_items[$x][$y][$uniqueid];
					}
					$positions[$x][$y] = $items;
				}
			}
		}
		return $positions;
	};
	$functions->message_xy = function($message, $x, $y, $objects=[], $omit=[]) {
		foreach ($this->_characters as $character) {
			if ( ! in_array($character, $omit)) {
				if ($character->x == $x && $character->y == $y) {
					$character->message($message, $objects);
				}
			}
		}
	};
	$functions->message_sphere_near_xy = function($radius, $message, $x, $y, $objects=[], $omit=[]) {
		$coordinates = $this->get_coordinates_in_sphere($x, $y, $radius);
		$characters = $this->characters_in_coordinates_list($coordinates);
		foreach ($characters as $character) {
			if ( ! in_array($character, $omit)) {
				if ($character->x != $x && $character->y != $y) {
					$character->message($message, $objects);
				}
			}
		}
	};
	$functions->message_box_near_xy = function($radius, $message, $x, $y, $objects=[], $omit=[]) {
		$coordinates = $this->get_box_around_coordinates($x, $y, $radius);
		$characters = $this->characters_in_coordinates_list($coordinates);
		foreach ($characters as $character) {
			if ( ! in_array($character, $omit)) {
				if ($character->x != $x && $character->y != $y) {
					$character->message($message, $objects);
				}
			}
		}
	};
	$functions->message = function($message, $omit=[]) {
		foreach ($this->_characters as $character) {
			if ( ! in_array($character, $omit)) {
				$character->message($message);
			}
		}
	};
	$functions->characters_near = function($x, $y, $distance) {
		$lowest_x   = $x - $distance;
		$highest_x  = $x + $distance;
		$lowest_y   = $y - $distance;
		$highest_y  = $y + $distance;
		$characters = [];
		foreach ($this->_characters as $character) {
			if ($character->x >= $lowest_x &&
				$character->x < $highest_x &&
				$character->y >= $lowest_y &&
				$character->y < $highest_y) {
					$characters[] = $character;
			}
		}
		return $characters;
	};
	$functions->nearby_characters = function($current_x, $current_y, $looker=null, $view_distance_x=14, $view_distance_y=7, $ignore_center=true) {
		$lowest_x = $current_x - $view_distance_x;
		$highest_x = $current_x + $view_distance_x;
		$lowest_y = $current_y - $view_distance_y;
		$highest_y = $current_y + $view_distance_y;
		$characters = [];
		foreach ($this->_characters as $character) {
			if ($ignore_center && $character->x == $current_x && $character->y == $current_y || $character === $looker) {
				continue;
			}
			if ($character->x >= $lowest_x &&
				$character->x < $highest_x &&
				$character->y >= $lowest_y &&
				$character->y < $highest_y) {
				if ($this->los($current_x, $current_y, $character->x, $character->y)) {
					$characters[] = $character;
				}
			}
		}
		return $characters;
	};
	return $functions;
Leave a Comment