Created
June 10, 2023 05:10
-
-
Save snuffyDev/6b028815290cd5b336c4ae46f2d36068 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function _levelStore() { | |
let TILES: WorldState["data"] = []; | |
const { subscribe, set, update } = writable<WorldState["data"]>([]); | |
const checkCollisionWithWorld = ( | |
position: Position | Position2D, | |
isBot: boolean | null = false | |
) => { | |
const { component, attributes, blocking } = TILES[position!.z][position!.x]; | |
if (attributes?.collectable && !blocking) { | |
if (isBot === null || isBot === true) return false; | |
handleNoClipObject(TILES[position.z][position.x], position); | |
return false; | |
} | |
if (attributes?.state === "open") return false; | |
return component === "Wall" || attributes?.state === "closed" || blocking === true; | |
}; | |
const handleNoClipObject = (model: NonNullable<ExtendedEntityV2>, position: Position2D) => { | |
if (!ArrayUtils.includesUnknown(ItemPickupIds as never, model.texture)) return; | |
if (model.texture === ItemPickups.Smg) { | |
PlayerState.giveWeapon("smg"); | |
} | |
if (model.texture === ItemPickups.Ammo) { | |
PlayerState.giveAmmo("pistol", 4); | |
} | |
if (model.texture! in TreasurePickupPointMap) { | |
PlayerState.givePoints( | |
TreasurePickupPointMap[model.texture! as keyof typeof TreasurePickupPointMap] | |
); | |
PlayerState.setPickupState(); | |
} | |
if (model.texture === ItemPickups.DogFood) { | |
PlayerState.giveHealth(4); | |
} | |
if (model.texture === ItemPickups.Food) { | |
PlayerState.giveHealth(10); | |
} | |
if (model.texture === ItemPickups.Medkit) { | |
PlayerState.giveHealth(25); | |
} | |
model.texture = null; | |
updateTileAt(position.z, position.x, { rotation: undefined, surfaces: null }); | |
}; | |
const updateTileAt = (row: number, column: number, data: ExtendedEntityV2) => { | |
update((u) => { | |
u = [...u.slice(0, row), splice(u[row], column, 1, data), ...u.slice(row + 1)]; | |
return u; | |
}); | |
TILES[row][column] = data; | |
}; | |
return { | |
subscribe, | |
get() { | |
return TILES; | |
}, | |
set() { | |
const baseTile = (model: Partial<EntityV2>) => | |
({ | |
rotation: null, | |
texture: null, | |
pushwall: false, | |
secret: false, | |
attributes: null, | |
...model | |
} as EntityV2); | |
const BASE_TILE_MAP: EntityV2[][] = [...Array(64).keys()].map(() => | |
[...Array(64).keys()].map(() => baseTile({})) | |
); | |
for (let z = 0; z < 64; z++) { | |
for (let x = 0; x < 64; x++) { | |
let m0 = gameData.getMap0(x, z)!; | |
if (m0 <= 63) { | |
// wall | |
BASE_TILE_MAP[z][x] = baseTile({ | |
blocking: true, | |
texture: m0 * 2 - 1, | |
component: "Wall" | |
}); | |
} else if (89 <= m0 && m0 <= 103) { | |
// door | |
BASE_TILE_MAP[z][x] = baseTile({ | |
component: "Door", | |
texture: m0 + 9, | |
attributes: { state: "closed" }, | |
blocking: true | |
}); | |
} | |
let m1 = gameData.getMap1(x, z); | |
if (19 <= m1 && m1 <= 22) { | |
// player starting position | |
PlayerState.modify((player) => { | |
player.position.x = x - 0.5; | |
player.position.z = z - 0.5; | |
console.log(player.position); | |
player.position = { ...getRealPositionFromLocalPosition(player.position), y: 0 }; | |
return player; | |
}); | |
} else if (23 <= m1 && m1 <= 70) { | |
// TODO: Props | |
} else if (m1 === 98) { | |
// TODO: pushwall | |
} else if (m1 === 124) { | |
// dead guard | |
BASE_TILE_MAP[z][x] = { ...BASE_TILE_MAP[z][x], texture: 95 }; | |
} else if (m1 >= 108) { | |
// TODO: Enemies | |
// const guardEnemyRange = (108 <= m1 && m1 < 116) || (144 <= m1 && m1 < 152); | |
// const ssEnemyRange = (126 <= m1 && m1 < 134) || (162 <= m1 && m1 < 170); | |
// const dogEnemyRange = (134 <= m1 && m1 < 142) || (170 <= m1 && m1 < 178); | |
// if (guardEnemyRange) { | |
// const baseNumber = guardEnemyRange ? 108 : 144; | |
// TEMP[z][x] = { ...TEMP[z][x], component: "Guard" }; | |
// // (m1 - baseNumber) % 4); | |
// } else if (ssEnemyRange) { | |
// const baseNumber = ssEnemyRange ? 126 : 162; | |
// TEMP[z][x] = { ...TEMP[z][x], component: "SS" }; | |
// // things.push(new SSEnemy(x, y, (m1 - baseNumber) % 4)); | |
// } else if (dogEnemyRange) { | |
// const baseNumber = dogEnemyRange ? 134 : 170; | |
// TEMP[z][x] = { ...TEMP[z][x], component: "Dog" }; | |
// // things.push(new DogEnemy(x, y, (m1 - baseNumber) % 4)); | |
// } | |
} | |
} | |
} | |
const extendedMap = createExtendedWorld(BASE_TILE_MAP); | |
removeConnectedSurfaces(extendedMap); | |
TILES = [...extendedMap]; | |
set(TILES); | |
}, | |
updateTileAt, | |
update: (updateFn: Updater<typeof TILES>) => { | |
update((v) => { | |
v = updateFn(TILES); | |
TILES = v; | |
return v; | |
}); | |
}, | |
checkCollisionWithWorld | |
}; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function _levelStore() { | |
let TILES: WorldState["data"] = []; | |
const { subscribe, set, update } = writable<WorldState["data"]>([]); | |
const checkCollisionWithWorld = ( | |
position: Position | Position2D, | |
isBot: boolean | null = false, | |
skipWalls = false | |
) => { | |
const { | |
pushwall = false, | |
secret = false, | |
model, | |
position: wallPosition, | |
surfaces, | |
rotation | |
} = TILES[position!.z][position!.x]; | |
if (model?.texture && noClipObjectIds.includes(model?.texture)) { | |
if (isBot === null || isBot === true) return false; | |
handleNoClipObject(model, position); | |
return false; | |
} else if (model?.texture && model.component === "Object") return true; | |
const doorCheck = isDoor( | |
{ pushwall, secret, model, position: wallPosition, rotation, surfaces }, | |
position | |
); | |
if (doorCheck) return doorCheck; | |
if ( | |
!skipWalls && | |
isWall( | |
{ position: wallPosition, secret, rotation, pushwall, model, surfaces }, | |
wallPosition | |
) | |
) | |
return true; | |
if (isBot && isEnemy(model)) return true; | |
else if (isEnemy(model)) return false; | |
return ( | |
surfaces && | |
(pushwall | |
? secret && position.x === wallPosition?.x && position.z === wallPosition?.z | |
: surfaces && Object.values(surfaces).some(hasValidTexture)) | |
); | |
}; | |
const isDoor = ( | |
entity: { [K in keyof ExtendedEntity]: ExtendedEntity[K] }, | |
position: Position2D | |
) => { | |
return ( | |
(entity.pushwall === true && entity.secret === true) || | |
("model" in entity && | |
typeof entity.model === "object" && | |
"component" in entity.model && | |
entity.model.component === "Door" && | |
entity.position?.x === position.x && | |
entity.position?.z === position.z) | |
); | |
}; | |
const handleNoClipObject = ( | |
model: NonNullable<ExtendedEntity["model"]>, | |
position: Position2D | |
) => { | |
if (!ArrayUtils.includesUnknown(ItemPickupIds as never, model.texture)) return; | |
if (model.texture === ItemPickups.Smg) { | |
PlayerState.giveWeapon("smg"); | |
} | |
if (model.texture === ItemPickups.Ammo) { | |
PlayerState.giveAmmo("pistol", 4); | |
} | |
if (model.texture! in TreasurePickupPointMap) { | |
PlayerState.givePoints( | |
TreasurePickupPointMap[model.texture! as keyof typeof TreasurePickupPointMap] | |
); | |
} | |
if (model.texture === ItemPickups.DogFood) { | |
PlayerState.giveHealth(4); | |
} | |
if (model.texture === ItemPickups.Food) { | |
PlayerState.giveHealth(10); | |
} | |
if (model.texture === ItemPickups.Medkit) { | |
PlayerState.giveHealth(25); | |
} | |
model.texture = undefined; | |
updateTileAt(position.z, position.x, { rotation: undefined, surfaces: null }); | |
}; | |
const isWall = ( | |
{ | |
secret, | |
position: wallPosition, | |
pushwall, | |
surfaces, | |
model | |
}: { [K in keyof ExtendedEntity]: ExtendedEntity[K] }, | |
position: ExtendedEntity["position"] | |
) => { | |
return ( | |
position && | |
!model && | |
wallPosition && | |
wallPosition.x === position.x && | |
wallPosition.z === position.z && | |
surfaces && | |
!secret | |
); | |
}; | |
const isEnemy = (model: ExtendedEntity["model"]) => { | |
return model?.component === "Guard" || model?.component === "Dog"; | |
}; | |
const hasValidTexture = (surfaces: Surface) => { | |
return compare(surfaces, (t) => isValidTexture(t) !== false); | |
}; | |
const updateTileAt = (row: number, column: number, data: ExtendedEntity) => { | |
update((u) => { | |
u = [...u.slice(0, row), splice(u[row], column, 1, data), ...u.slice(row + 1)]; | |
return u; | |
}); | |
TILES[row][column] = data; | |
}; | |
return { | |
subscribe, | |
get() { | |
return TILES; | |
}, | |
set(level: typeof TILES) { | |
TILES = [...level]; | |
set(TILES); | |
}, | |
updateTileAt, | |
update: (updateFn: Updater<typeof TILES>) => { | |
update((v) => { | |
v = updateFn(TILES); | |
TILES = v; | |
return v; | |
}); | |
}, | |
checkCollisionWithWorld | |
}; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment