diff --git a/src/components/gameMaster/GmTools.vue b/src/components/gameMaster/GmTools.vue
index 963037c..f746809 100644
--- a/src/components/gameMaster/GmTools.vue
+++ b/src/components/gameMaster/GmTools.vue
@@ -1,5 +1,5 @@
 <template>
-  <Modal :isModalOpen="true" :closable="false" :is-resizable="false" :modal-width="200" :modal-height="160">
+  <Modal :isModalOpen="true" :closable="false" :is-resizable="false" :modal-width="modalWidth" :modal-height="modalHeight" :modal-position-x="posXY.x" :modal-position-y="posXY.y">
     <template #modalHeader>
       <h3 class="m-0 font-medium shrink-0">GM tools</h3>
     </template>
@@ -15,7 +15,33 @@
 import Modal from '@/components/utilities/Modal.vue'
 import { useZoneEditorStore } from '@/stores/zoneEditor'
 import { useGameStore } from '@/stores/game'
+import { onMounted, ref } from 'vue'
 
 const zoneEditorStore = useZoneEditorStore()
 const gameStore = useGameStore()
+const modalWidth = ref(200);
+const modalHeight = ref(160);
+
+let posXY = ref({x: 0, y: 0});
+
+onMounted(() => {
+
+  window.addEventListener('resize', () => {
+    posXY.value = customPositionGmPanel(modalWidth.value);
+  })
+
+})
+
+const customPositionGmPanel = (modalWidth: number) => {
+  const padding = 25
+  const width = window.innerWidth
+
+  const x = width - (modalWidth+4) - 25
+  const y = padding
+
+  return { x, y }
+}
+
+posXY.value = customPositionGmPanel(modalWidth.value)
+
 </script>
diff --git a/src/components/sprites/Character.vue b/src/components/sprites/Character.vue
index 8ca1d7f..a1e9ea2 100644
--- a/src/components/sprites/Character.vue
+++ b/src/components/sprites/Character.vue
@@ -16,11 +16,12 @@
 </template>
 
 <script lang="ts" setup>
-import { Container, Image, RoundRectangle, Sprite, Text } from 'phavuer'
+import { Container, Image, RoundRectangle, Sprite, Text, useScene } from 'phavuer'
 import { type ExtendedCharacter as CharacterT } from '@/types'
 import { calculateIsometricDepth, tileToWorldX, tileToWorldY } from '@/composables/zoneComposable'
 import { watch, computed, ref, onMounted, onUnmounted } from 'vue'
 import config from '@/config'
+import { useGameStore } from '@/stores/game'
 
 enum Direction {
   POSITIVE,
@@ -40,9 +41,11 @@ const props = withDefaults(defineProps<Props>(), {
 const isometricDepth = ref(calculateIsometricDepth(props.character.positionX, props.character.positionY, 28, 94, true))
 const currentX = ref(0)
 const currentY = ref(0)
+const gameStore = useGameStore();
 const tween = ref<Phaser.Tweens.Tween | null>(null)
 const isInitialPosition = ref(true)
 
+
 const calculateLocalDepth = (x: number, y: number, width: number, height: number, isCharacter: boolean) => {
   isometricDepth.value = calculateIsometricDepth(x, y, width, height, isCharacter)
 }
@@ -51,6 +54,11 @@ const updatePosition = (x: number, y: number, direction: Direction) => {
   const targetX = tileToWorldX(props.layer, x, y)
   const targetY = tileToWorldY(props.layer, x, y)
 
+  // Used for camera resize calculation to center on Character.
+  if(gameStore.character) {
+    gameStore.character.relativePosition = { x: targetX, y: targetY };
+  }
+
   if (isInitialPosition.value) {
     currentX.value = targetX
     currentY.value = targetY
diff --git a/src/components/utilities/Modal.vue b/src/components/utilities/Modal.vue
index 2246e4a..ce46bee 100644
--- a/src/components/utilities/Modal.vue
+++ b/src/components/utilities/Modal.vue
@@ -43,6 +43,14 @@ const props = defineProps({
     type: Boolean,
     default: false
   },
+  modalPositionX: {
+    type: Number,
+    default: 0
+  },
+  modalPositionY: {
+    type: Number,
+    default: 0
+  },
   modalWidth: {
     type: Number,
     default: 500
@@ -149,8 +157,15 @@ function handleResize() {
 function initializePosition() {
   width.value = Math.min(props.modalWidth, window.innerWidth)
   height.value = Math.min(props.modalHeight, window.innerHeight)
-  x.value = (window.innerWidth - width.value) / 2
-  y.value = (window.innerHeight - height.value) / 2
+  if(props.modalPositionX !== 0 && props.modalPositionY !== 0) {
+    console.log(props.modalPositionX)
+    console.log(props.modalPositionY)
+    x.value = props.modalPositionX
+    y.value = props.modalPositionY
+  } else {
+    x.value = (window.innerWidth - width.value) / 2
+    y.value = (window.innerHeight - height.value) / 2
+  }
 }
 
 function toggleFullScreen() {
@@ -192,12 +207,28 @@ watch(
   }
 )
 
+watch(
+  () => props.modalPositionX,
+  (value) => {
+    x.value = value
+  }
+)
+
+watch(
+  () => props.modalPositionY,
+  (value) => {
+    y.value = value
+  }
+)
+
 onMounted(() => {
   window.addEventListener('mousemove', drag)
   window.addEventListener('mouseup', stopDrag)
   window.addEventListener('mousemove', resizeModal)
   window.addEventListener('mouseup', stopResize)
-  window.addEventListener('resize', handleResize)
+  if(props.modalPositionX !== 0 && props.modalPositionY !== 0) {
+    window.addEventListener('resize', handleResize)
+  }
   initializePosition()
 })
 
@@ -206,6 +237,8 @@ onUnmounted(() => {
   window.removeEventListener('mouseup', stopDrag)
   window.removeEventListener('mousemove', resizeModal)
   window.removeEventListener('mouseup', stopResize)
-  window.removeEventListener('resize', handleResize)
+  if(props.modalPositionX !== 0 && props.modalPositionY !== 0) {
+    window.removeEventListener('resize', handleResize)
+  }
 })
 </script>
diff --git a/src/components/zone/Zone.vue b/src/components/zone/Zone.vue
index eb4006f..2de107a 100644
--- a/src/components/zone/Zone.vue
+++ b/src/components/zone/Zone.vue
@@ -13,7 +13,7 @@ import type { Character as CharacterT, Zone as ZoneT, ExtendedCharacter as Exten
 import Tiles from '@/components/zone/Tiles.vue'
 import Objects from '@/components/zone/Objects.vue'
 import Characters from '@/components/zone/Characters.vue'
-import { loadAssets } from '@/composables/zoneComposable'
+import { loadAssets, tileToWorldX, tileToWorldY } from '@/composables/zoneComposable'
 
 const gameStore = useGameStore()
 const zoneStore = useZoneStore()
@@ -26,19 +26,23 @@ type zoneLoadData = {
   characters: CharacterT[]
 }
 
+
 gameStore.connection!.emit('zone:character:join', { zoneId: gameStore.character!.zoneId }, async (response: zoneLoadData) => {
   // Fetch assets for new zone
   await gameStore.fetchZoneAssets(response.zone.id)
   await loadAssets(scene)
 
+
+
   // Set zone and characters
   zoneStore.setZone(response.zone)
   zoneStore.setCharacters(response.characters)
+  scene.cameras.main.setScroll(-(scene.cameras.main.worldView.width/2) - gameStore.character.relativePosition.x, -(scene.cameras.main.worldView.height/2) + gameStore.character.relativePosition.y)
+  console.log('--- CHARACTER JOIN')
 })
 
 // Event listeners
 gameStore.connection!.on('zone:character:teleport', async (data: zoneLoadData) => {
-  console.log('eeee');
   /**
    * This is the cause of the bug
    */
@@ -56,6 +60,12 @@ gameStore.connection!.on('zone:character:teleport', async (data: zoneLoadData) =
 
   zoneStore.setZone(data.zone)
   zoneStore.setCharacters(data.characters)
+
+  const character = gameStore.character;
+  // Position character centered on zone change or teleport
+  const posX = tileToWorldX(tileMap.value, character.positionX, character.positionY)
+  const posY = tileToWorldY(tileMap.value, character.positionX, character.positionY)
+  scene.cameras.main.setScroll(-(scene.cameras.main.worldView.width/2) + posX, -(scene.cameras.main.worldView.height/2) + posY)
 })
 
 gameStore.connection!.on('zone:character:join', async (data: ExtendedCharacterT) => {
diff --git a/src/composables/useCameraControls.ts b/src/composables/useCameraControls.ts
index 56b6617..8f908a5 100644
--- a/src/composables/useCameraControls.ts
+++ b/src/composables/useCameraControls.ts
@@ -6,6 +6,15 @@ export function useCameraControls(scene: Phaser.Scene): any {
   const camera = ref(scene.cameras.main)
   const isDragging = ref(false)
 
+  // Resize center camera on character.
+  window.addEventListener('resize', () => {
+    console.log('woep')
+    // Need to change camera position next frame
+    setTimeout(() => {
+      scene.cameras.main.setScroll(-(scene.cameras.main.worldView.width/2) + gameStore.character.relativePosition.x, -(scene.cameras.main.worldView.height/2) + gameStore.character.relativePosition.y)
+    }, 0)
+  })
+
   function onPointerDown(pointer: Phaser.Input.Pointer) {
     if (pointer.event instanceof MouseEvent || pointer.event.shiftKey) {
       isDragging.value = true
diff --git a/src/types.ts b/src/types.ts
index 55fafe7..763553c 100644
--- a/src/types.ts
+++ b/src/types.ts
@@ -142,6 +142,7 @@ export type Character = {
   role: string
   positionX: number
   positionY: number
+  relativePosition: {x: number, y: number}
   rotation: number
   zoneId: number
   zone: Zone