fix castingVision giving vision to neutrals
This commit is contained in:
Binary file not shown.
|
Before Width: | Height: | Size: 95 B After Width: | Height: | Size: 95 B |
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Binary file not shown.
|
After Width: | Height: | Size: 543 B |
Binary file not shown.
|
After Width: | Height: | Size: 95 B |
Binary file not shown.
|
After Width: | Height: | Size: 95 B |
+51
-42
@@ -36,6 +36,8 @@ const teamMaterials = {
|
||||
redTransparent: new THREE.MeshToonMaterial({ color: 0xff4444, transparent: true, opacity }),
|
||||
projectile: new THREE.MeshToonMaterial({ color: 0xff00ff, transparent: true, opacity }),
|
||||
range: new THREE.MeshToonMaterial({ color: 0x00ffff, transparent: true, opacity: opacity / 2 }),
|
||||
visionRange: new THREE.MeshToonMaterial({ color: 0x226022 }),
|
||||
// visionRange: new THREE.MeshToonMaterial({ color: 0x00ffff, transparent: true, opacity: opacity / 6 }),
|
||||
}
|
||||
|
||||
// TODO: draw lines of path for minimap camera
|
||||
@@ -70,9 +72,9 @@ const preloadGLTF = function loadTemplate(path) {
|
||||
gltfLoader.load(path, (loadedGLTF) => gltf[path] = loadedGLTF)
|
||||
}
|
||||
|
||||
const addGLTF = function addGLTF(scene, path, id) {
|
||||
const addGLTF = function addGLTF(scene, path, id, additionalSteps = function noAdditionalSteps() {}) {
|
||||
if (gltf[path] == null) {
|
||||
setTimeout(() => addGLTF(scene, path, id), 200)
|
||||
setTimeout(() => addGLTF(scene, path, id, additionalSteps), 200)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -89,6 +91,7 @@ const addGLTF = function addGLTF(scene, path, id) {
|
||||
})
|
||||
|
||||
model.scale.set(scale, scale, scale)
|
||||
additionalSteps(model)
|
||||
scene.add(model)
|
||||
}
|
||||
|
||||
@@ -208,6 +211,7 @@ var websocket = null
|
||||
global.websocket = null
|
||||
var timerId = null
|
||||
var playerId = null
|
||||
var playerTeam = null
|
||||
|
||||
function connectWebSocket() {
|
||||
websocket = new WebSocket(`ws://${window.location.hostname}:1280/ws`)
|
||||
@@ -236,6 +240,11 @@ function connectWebSocket() {
|
||||
tweenDuration = 1000 / stateUpdates.tickRate
|
||||
}
|
||||
|
||||
if (stateUpdates.width != null && stateUpdates.height != null && stateUpdates.width != (state.width ?? -1) && stateUpdates.height != (state.height ?? -1) ) {
|
||||
ground.geometry = new THREE.PlaneGeometry(stateUpdates.width / 100, stateUpdates.height / 100)
|
||||
ground.position.set(stateUpdates.width / 200, stateUpdates.height / 200, 0)
|
||||
}
|
||||
|
||||
if (stateUpdates.width != null && stateUpdates.height != null) {
|
||||
state.width = stateUpdates.width
|
||||
state.height = stateUpdates.height
|
||||
@@ -317,17 +326,18 @@ function connectWebSocket() {
|
||||
}
|
||||
}
|
||||
|
||||
if (state.width != null && state.height != null && (ground.geometry.attributes.width != state.width || ground.geometry.attributes.height != state.height)) {
|
||||
ground.geometry = new THREE.PlaneGeometry(state.width / 100, state.height / 100)
|
||||
ground.position.set(state.width / 200, state.height / 200, 0)
|
||||
}
|
||||
|
||||
for (const e of Object.values(entities)) {
|
||||
e.userData.flaggedForRemoval = true
|
||||
}
|
||||
|
||||
for (const e of state.entities ?? []) {
|
||||
let entity
|
||||
let created = false
|
||||
|
||||
if (e.id == playerId && playerTeam != e.team) {
|
||||
playerTeam = e.team
|
||||
}
|
||||
|
||||
if (e.id in entities) {
|
||||
entity = entities[e.id]
|
||||
}
|
||||
@@ -335,17 +345,19 @@ function connectWebSocket() {
|
||||
// const entityMaterial = teamMaterials[e.team]
|
||||
// entity = new THREE.Mesh(new THREE.CylinderGeometry(e.visualRadius / 100, e.visualRadius / 100, e.height / 50), entityMaterial)
|
||||
// TODO: change entity material
|
||||
created = true
|
||||
|
||||
entity = new THREE.Group()
|
||||
entity.rotation.x = Math.PI / 2
|
||||
entity.scale.set(e.visualRadius / 100, e.height / 100, e.visualRadius / 100)
|
||||
entity.scale.set(e.visualRadius / 100, e.visualRadius / 100, e.visualRadius / 100)
|
||||
entity.userData.type = 'entity'
|
||||
entity.userData.id = e.id
|
||||
entity.position.set(e.position.x / 100, e.position.y / 100, 0)
|
||||
scene.add(entity)
|
||||
|
||||
const hpMargin = 4.8
|
||||
const hpMargin = 0.5
|
||||
const maxHp = new THREE.Sprite(new THREE.SpriteMaterial({ color: 0xd03333 }))
|
||||
maxHp.position.set(0, hpMargin, 0)
|
||||
maxHp.position.set(0, 0, 0)
|
||||
maxHp.scale.set(1.5, 0.2, 1)
|
||||
maxHp.layers.set(1)
|
||||
entity.add(maxHp)
|
||||
@@ -358,36 +370,20 @@ function connectWebSocket() {
|
||||
|
||||
const teamMaterial = teamMaterials[`${e.team}Transparent`]
|
||||
const teamMarker = new THREE.Mesh(new THREE.CylinderGeometry(1, 0.00001, 1), teamMaterial)
|
||||
teamMarker.position.y = -0.496
|
||||
teamMarker.position.y = -0.493
|
||||
entity.add(teamMarker)
|
||||
|
||||
const buffMaterial = new THREE.MeshToonMaterial({ color: 0xffff00, transparent: true, opacity: 0.4 })
|
||||
const buffMarkerRadius = 0.6
|
||||
const buffMarker = new THREE.Mesh(new THREE.CylinderGeometry(buffMarkerRadius, buffMarkerRadius, 0.3), buffMaterial)
|
||||
buffMarker.position.y = 2
|
||||
const buffMarker = new THREE.Mesh(new THREE.TorusGeometry(0.95, 0.15), buffMaterial)
|
||||
buffMarker.rotation.x = Math.PI / 2
|
||||
buffMarker.layers.set(1)
|
||||
buffMarker.visible = false
|
||||
entity.add(buffMarker)
|
||||
|
||||
const castingMarkerrotationBase = new THREE.Group()
|
||||
entity.add(castingMarkerrotationBase)
|
||||
|
||||
const castingMaterial = new THREE.MeshToonMaterial({ color: 0x10dde0, transparent: true, opacity: 0.4 })
|
||||
const castingMarker = new THREE.Mesh(new THREE.CylinderGeometry((e.height * 0.9) / 100, (e.height * 0.9) / 100, 1), castingMaterial)
|
||||
const castingMarkerSize = 800
|
||||
castingMarker.rotation.z = Math.PI / 2
|
||||
castingMarker.position.x = 1
|
||||
castingMarker.position.y = 1
|
||||
castingMarker.scale.y = e.height / castingMarkerSize
|
||||
castingMarker.layers.set(1)
|
||||
castingMarker.visible = false
|
||||
castingMarkerrotationBase.add(castingMarker)
|
||||
|
||||
const rangeMaterial = teamMaterials['range']
|
||||
// const rangeSize = e.visionRange ?? 0
|
||||
const rangeSize = (state.abilities.find((it) => it.id == e.abilities?.a)?.range ?? 0) + e.radius
|
||||
const rangeMarker = new THREE.Mesh(new THREE.CylinderGeometry(rangeSize / e.visualRadius, rangeSize / e.visualRadius, 0.001), rangeMaterial)
|
||||
rangeMarker.position.y = 0.002
|
||||
rangeMarker.position.y = 0.004
|
||||
rangeMarker.layers.set(1)
|
||||
rangeMarker.visible = false
|
||||
entity.add(rangeMarker)
|
||||
@@ -397,10 +393,22 @@ function connectWebSocket() {
|
||||
modelRotationBase.layers.set(1)
|
||||
entity.add(modelRotationBase)
|
||||
|
||||
addGLTF(modelRotationBase, 'models/generic-player-placeholder.gltf', e.id)
|
||||
const animations = animationActions[e.id] ?? {}
|
||||
if (e.dead) {
|
||||
animations.dead?.reset().play()
|
||||
const visionRangeMaterial = teamMaterials['visionRange']
|
||||
const visionRangeSize = e.visionRange ?? 0
|
||||
const visionRangeMarker = new THREE.Mesh(new THREE.CylinderGeometry(visionRangeSize / e.visualRadius, visionRangeSize / e.visualRadius, 0.001), visionRangeMaterial)
|
||||
visionRangeMarker.position.y = 0.002
|
||||
visionRangeMarker.layers.set(1)
|
||||
visionRangeMarker.visible = false
|
||||
entity.add(visionRangeMarker)
|
||||
|
||||
if (e.model != null) {
|
||||
addGLTF(modelRotationBase, e.model, e.id, function(model) {
|
||||
const box = new THREE.Box3().setFromObject(model)
|
||||
const size = box.getSize(new THREE.Vector3())
|
||||
maxHp.position.set(0, size.y + hpMargin, 0)
|
||||
buffMarker.position.y = size.y / 2
|
||||
buffMarker.scale.z = size.y / 10
|
||||
})
|
||||
}
|
||||
|
||||
entities[e.id] = entity
|
||||
@@ -411,7 +419,7 @@ function connectWebSocket() {
|
||||
entity.children.at(2).visible = e.buffs.some((it) => it.id == 'exposed') // TODO: only works for Exposed now
|
||||
|
||||
const animations = animationActions[e.id] ?? {}
|
||||
const fadeIn = 0.15
|
||||
const fadeIn = created ? 0 : 0.15
|
||||
|
||||
if (e.dead) {
|
||||
if (!animations.dead?.isRunning()) {
|
||||
@@ -433,26 +441,25 @@ function connectWebSocket() {
|
||||
}
|
||||
|
||||
entity.userData.flaggedForRemoval = false
|
||||
entity.children.at(3).rotation.y = e.rotation
|
||||
const oldRotationY = entity.children.at(5).rotation.y
|
||||
const oldRotationY = entity.children.at(4).rotation.y
|
||||
const newRotationY = e.rotation - (Math.PI / 2)
|
||||
if (Math.abs((oldRotationY - (2 * Math.PI)) - newRotationY) < Math.abs(oldRotationY - newRotationY)) {
|
||||
entity.children.at(5).rotation.y = oldRotationY - (2 * Math.PI)
|
||||
entity.children.at(4).rotation.y = oldRotationY - (2 * Math.PI)
|
||||
}
|
||||
if (Math.abs((oldRotationY + (2 * Math.PI)) - newRotationY) < Math.abs(oldRotationY - newRotationY)) {
|
||||
entity.children.at(5).rotation.y = oldRotationY + (2 * Math.PI)
|
||||
entity.children.at(4).rotation.y = oldRotationY + (2 * Math.PI)
|
||||
}
|
||||
|
||||
positionTweens[entity.id] = new Tween(entity.position).to({ x: e.position.x / 100, y: e.position.y / 100, z: 0 }, tweenDuration).start()
|
||||
rotationTweens[entity.id] = new Tween(entity.children.at(5).rotation).to({ x: 0, y: newRotationY, z: 0 }, tweenDuration).start()
|
||||
rotationTweens[entity.id] = new Tween(entity.children.at(4).rotation).to({ x: 0, y: newRotationY, z: 0 }, tweenDuration).start()
|
||||
|
||||
const hp = entity.children.at(0).children.at(0)
|
||||
const percentageHp = e.health / e.maxHealth
|
||||
hp.scale.x = percentageHp
|
||||
hp.position.x = -(1 - percentageHp) / 2
|
||||
|
||||
entity.children.at(4).visible = e.id == playerId
|
||||
// entity.children.at(3).children.at(0).visible = e.casting != null
|
||||
entity.children.at(3).visible = e.id == playerId
|
||||
// entity.children.at(5).visible = !e.dead && e.team == playerTeam
|
||||
}
|
||||
|
||||
for (const e of Object.values(entities)) {
|
||||
@@ -613,7 +620,9 @@ function connectWebSocket() {
|
||||
}
|
||||
|
||||
window.addEventListener('load', () => {
|
||||
preloadGLTF('models/generic-bam-placeholder.gltf')
|
||||
preloadGLTF('models/generic-player-placeholder.gltf')
|
||||
preloadGLTF('models/generic-player-placeholder-red.gltf')
|
||||
|
||||
const params = Object.fromEntries(new URLSearchParams(window.location.search).entries())
|
||||
playerId = params.id
|
||||
|
||||
@@ -20,6 +20,7 @@ export default class Entity {
|
||||
health = null
|
||||
height = null
|
||||
maxHealth = 1
|
||||
model = null
|
||||
position = null
|
||||
radius = 0
|
||||
rotation = 0
|
||||
@@ -681,6 +682,7 @@ export default class Entity {
|
||||
owner: this.id,
|
||||
position: this.position.clone(),
|
||||
visionRange: radius,
|
||||
team: enemyTeam,
|
||||
})
|
||||
|
||||
this.game?.spawnProjectile(projectile)
|
||||
|
||||
+15
-12
@@ -7,9 +7,10 @@ export default class Template {
|
||||
return {
|
||||
abilities: {},
|
||||
logic: this.#basiliskLogic(),
|
||||
maxHealth: 3000,
|
||||
model: 'models/generic-bam-placeholder.gltf',
|
||||
radius: 180,
|
||||
speed: 230,
|
||||
maxHealth: 3000,
|
||||
...overrides,
|
||||
}
|
||||
}
|
||||
@@ -19,6 +20,7 @@ export default class Template {
|
||||
abilities: { a: options.ranged ? Ability.rangedAttack.id : Ability.meleeAttack.id },
|
||||
logic: this.#minionLogic(options.route, (team != Team.blue)),
|
||||
maxHealth: options.ranged ? 300 : 450,
|
||||
model: Team.blue == (team ?? Team.blue) ? 'models/generic-player-placeholder.gltf' : 'models/generic-player-placeholder-red.gltf',
|
||||
pathfindingCooldown: 0.2,
|
||||
pathfindingObstacleLimit: 0,
|
||||
position: options.route?.at(0) ?? options.position ?? new Vector2(0, 0),
|
||||
@@ -42,6 +44,7 @@ export default class Template {
|
||||
},
|
||||
logic: this.#playerLogic,
|
||||
maxHealth: 600,
|
||||
model: Team.blue == (overrides.team ?? Team.blue) ? 'models/generic-player-placeholder.gltf' : 'models/generic-player-placeholder-red.gltf',
|
||||
pathfindingObstacleLimit: 3,
|
||||
radius: 65,
|
||||
spawnPosition: new Vector2(500, 150),
|
||||
@@ -60,17 +63,17 @@ export default class Template {
|
||||
const despawnDelay = entity.game?.secToTick(despawnDelaySec) ?? 1
|
||||
const timestamp = entity.game?.currentTick ?? 0
|
||||
|
||||
if (entity.dead) {
|
||||
if (diedOnTick == null) {
|
||||
diedOnTick = timestamp
|
||||
}
|
||||
else if (diedOnTick + despawnDelay < timestamp) {
|
||||
entity.despawn()
|
||||
}
|
||||
}
|
||||
else if (diedOnTick != null) {
|
||||
diedOnTick = null
|
||||
}
|
||||
if (entity.dead && diedOnTick == null) { diedOnTick = timestamp }
|
||||
if (entity.dead && diedOnTick != null && diedOnTick + despawnDelay < timestamp) { entity.despawn() }
|
||||
if (!entity.dead) { diedOnTick = null }
|
||||
if (entity.dead) { return }
|
||||
|
||||
const target = entity.closestTargetTo(entity.position, 500)
|
||||
if (target == null) { return }
|
||||
|
||||
const directionToTarget = target.position.clone().sub(entity.position).normalize()
|
||||
const entityRotationVector = new Vector2(1, 0).rotateAround(new Vector2(), entity.rotation)
|
||||
entity.rotation = directionToTarget.clone().add(entityRotationVector).add(entityRotationVector).add(entityRotationVector).angle()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user