Skip to content

Instantly share code, notes, and snippets.

@snuffyDev
Created June 10, 2023 05:10
Show Gist options
  • Save snuffyDev/6b028815290cd5b336c4ae46f2d36068 to your computer and use it in GitHub Desktop.
Save snuffyDev/6b028815290cd5b336c4ae46f2d36068 to your computer and use it in GitHub Desktop.
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
};
}
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