levels
This commit is contained in:
parent
923106effb
commit
d2bae46701
|
@ -14,10 +14,16 @@ class Bullet extends Item
|
|||
constructor: () ->
|
||||
@size = 0.2
|
||||
@src_object = null
|
||||
|
||||
super
|
||||
@addAction new Action @, Action.FLY, "fly", 40
|
||||
@addAction new Action @, Action.EXPLODE, "explode", 200
|
||||
|
||||
del: ->
|
||||
if @mesh?
|
||||
world.scene.remove @mesh
|
||||
_.pull world.objects, @
|
||||
Timer.removeActionsOfObject @
|
||||
@mesh = null
|
||||
|
||||
createMesh: ->
|
||||
geom = new THREE.SphereGeometry 1, 16, 16
|
||||
|
@ -28,12 +34,12 @@ class Bullet extends Item
|
|||
bullet = new Bullet()
|
||||
world.addObject bullet
|
||||
bullet.direction = bot.getCurrentDir()
|
||||
bullet.setPosition bot.position.plus bullet.direction #.mul 1/2.0
|
||||
bullet.setPosition bot.position.plus bullet.direction.mul 0.8
|
||||
bullet.src_object = bot
|
||||
bullet.mesh.material.color.set bot.mesh.material.color
|
||||
world.playSound 'BULLET_SHOT', bot.getPos()
|
||||
|
||||
return if bullet.hitObjectAtPos bullet.position.plus bullet.direction.mul 1/2.0
|
||||
return if bullet.hitObjectAtPos bot.position.plus bullet.direction
|
||||
|
||||
Timer.addAction bullet.getActionWithId Action.FLY
|
||||
|
||||
|
@ -66,10 +72,10 @@ class Bullet extends Item
|
|||
|
||||
actionFinished: (action) ->
|
||||
if action.id == Action.FLY
|
||||
if @hitObjectAtPos @position.plus @direction.mul 1/2.0
|
||||
if @hitObjectAtPos @position.plus @direction.mul 0.5
|
||||
return
|
||||
Timer.addAction @getActionWithId Action.FLY
|
||||
else if action.id == Action.EXPLODE
|
||||
world.deleteObject @
|
||||
@del()
|
||||
|
||||
module.exports = Bullet
|
||||
|
|
|
@ -21,11 +21,11 @@ class Cell
|
|||
getOccupant: -> _.find @objects, (o) -> o.isSpaceEgoistic()
|
||||
|
||||
removeObject: (object) ->
|
||||
# log 'cell.removeObject', @objects.length
|
||||
# log "cell.removeObject #{object.name}", @objects.length
|
||||
for o in @objects
|
||||
o.cellMateLeft object if o != object
|
||||
_.remove @objects, (o) -> o == object or o.object == object
|
||||
# log 'cell.removedObject ', (o.name for o in @objects)
|
||||
# log "cell.removeObject #{object.name}", @objects.length
|
||||
|
||||
addObject: (object) ->
|
||||
# log "cell.addObject #{object.name}"
|
||||
|
|
|
@ -4,8 +4,6 @@
|
|||
# 000 000 000 000 000 000
|
||||
# 0000000 000 000 000 00000000
|
||||
|
||||
log = require "/Users/kodi/s/ko/js/tools/log"
|
||||
|
||||
Vector = require './lib/vector'
|
||||
Switch = require './switch'
|
||||
Light = require './light'
|
||||
|
@ -19,27 +17,29 @@ class Gate extends Switch
|
|||
super active
|
||||
@ENTER_EVENT = @addEventWithName "enter"
|
||||
@value = 0.0
|
||||
@getActionWithId(Action.ROTATE).duration = 3000
|
||||
@getActionWithId(Action.ROTATE).duration = 50000
|
||||
@sound_on = 'GATE_OPEN'
|
||||
@sound_off = 'GATE_CLOSE'
|
||||
|
||||
createLight: ->
|
||||
@light = new Light
|
||||
pos: @position
|
||||
radius: 12.0
|
||||
radius: 10.0
|
||||
shadow: true
|
||||
|
||||
createMesh: () ->
|
||||
torusRadius = 0.05
|
||||
t1 = new THREE.TorusGeometry 0.5-torusRadius, torusRadius, 16, 32
|
||||
@mat = new THREE.MeshPhongMaterial
|
||||
color: 0xff0000
|
||||
side: THREE.FrontSide
|
||||
shading: THREE.SmoothShading
|
||||
shininess: 5
|
||||
t1 = new THREE.TorusBufferGeometry 0.5-torusRadius, torusRadius, 16, 32
|
||||
@mat = new THREE.MeshPhongMaterial
|
||||
color: 0xff0000
|
||||
side: THREE.FrontSide
|
||||
shading: THREE.SmoothShading
|
||||
shininess: 5
|
||||
|
||||
@mesh = new THREE.Mesh t1, @mat
|
||||
|
||||
@mesh.castShadow = true
|
||||
@mesh.receiveShadow = true
|
||||
|
||||
t2 = new THREE.TorusGeometry 0.5-torusRadius, torusRadius, 16, 32
|
||||
t3 = new THREE.TorusGeometry 0.5-torusRadius, torusRadius, 16, 32
|
||||
t2.rotateY Vector.DEG2RAD 90
|
||||
|
@ -47,114 +47,17 @@ class Gate extends Switch
|
|||
t2.merge t3
|
||||
@tors = new THREE.Mesh t2, @mat
|
||||
@tors.castShadow = true
|
||||
@tors.receiveShadow = true
|
||||
@mesh.add @tors
|
||||
@mesh.castShadow = true
|
||||
@mesh.receiveShadow = true
|
||||
@mesh
|
||||
|
||||
bulletImpact: ->
|
||||
|
||||
newCellMate: (object) ->
|
||||
# log "gate.newCellMate --------------------------- #{object.name} #{@active}"
|
||||
if object.name == 'player' and @active
|
||||
world.playSound 'GATE_WARP'
|
||||
# log "gate.newCellMate --------------------------- trigger enter event actions"
|
||||
@events[@ENTER_EVENT].triggerActions()
|
||||
|
||||
renderBar: (r,b,h) ->
|
||||
# glBegin(GL_QUAD_STRIP);
|
||||
# glNormal3f(0,1,0);
|
||||
# glVertex3f(-r, h, -r); glVertex3f(-b, h, -b);
|
||||
# glVertex3f( r, h, -r); glVertex3f( b, h, -b);
|
||||
# glVertex3f( r, h, r); glVertex3f( b, h, b);
|
||||
# glVertex3f(-r, h, r); glVertex3f(-b, h, b);
|
||||
# glVertex3f(-r, h, -r); glVertex3f(-b, h, -b);
|
||||
# glEnd();
|
||||
# glBegin(GL_QUAD_STRIP);
|
||||
# glNormal3f(0,-1,0);
|
||||
# glVertex3f(-b, -h, -b); glVertex3f(-r, -h, -r);
|
||||
# glVertex3f( b, -h, -b); glVertex3f( r, -h, -r);
|
||||
# glVertex3f( b, -h, b); glVertex3f( r, -h, r);
|
||||
# glVertex3f(-b, -h, b); glVertex3f(-r, -h, r);
|
||||
# glVertex3f(-b, -h, -b); glVertex3f(-r, -h, -r);
|
||||
# glEnd();
|
||||
# glBegin(GL_QUADS);
|
||||
# glNormal3f(0,0,-1);
|
||||
# glVertex3f(-r, -h, -r); glVertex3f(-r, h, -r);
|
||||
# glVertex3f( r, h, -r); glVertex3f( r, -h, -r);
|
||||
# glNormal3f(1,0,0);
|
||||
# glVertex3f( r, -h, -r); glVertex3f( r, h, -r);
|
||||
# glVertex3f( r, h, r); glVertex3f( r, -h, r);
|
||||
# glNormal3f(0,0,1);
|
||||
# glVertex3f( r, -h, r); glVertex3f( r, h, r);
|
||||
# glVertex3f(-r, h, r); glVertex3f(-r, -h, r);
|
||||
# glNormal3f(-1,0,0);
|
||||
# glVertex3f(-r, -h, r); glVertex3f(-r, h, r);
|
||||
# glVertex3f(-r, h, -r); glVertex3f(-r, -h, -r);
|
||||
# glNormal3f(0,0,1);
|
||||
# glVertex3f(-b, h, -b); glVertex3f(-b, -h, -b);
|
||||
# glVertex3f( b, -h, -b); glVertex3f( b, h, -b);
|
||||
# glNormal3f(-1,0,0);
|
||||
# glVertex3f( b, h, -b); glVertex3f( b, -h, -b);
|
||||
# glVertex3f( b, -h, b); glVertex3f( b, h, b);
|
||||
# glNormal3f(0,0,-1);
|
||||
# glVertex3f( b, h, b); glVertex3f( b, -h, b);
|
||||
# glVertex3f(-b, -h, b); glVertex3f(-b, h, b);
|
||||
# glNormal3f(1,0,0);
|
||||
# glVertex3f(-b, h, b); glVertex3f(-b, -h, b);
|
||||
# glVertex3f(-b, -h, -b); glVertex3f(-b, h, -b);
|
||||
# glEnd();
|
||||
|
||||
render: () ->
|
||||
# KColor gate_color = colors[KikiGate_base_color];
|
||||
# if (active == false)
|
||||
# gate_color.setAlpha (gate_color.getAlpha()/4.0);
|
||||
#
|
||||
# gate_color.glColor();
|
||||
#
|
||||
# float v = sin(DEG2RAD(angle));
|
||||
# float av = kAbs(v);
|
||||
# float b = 0.29 + av * 0.1;
|
||||
# float h = 0.1 - av * 0.05;
|
||||
# float r = 0.49;
|
||||
# float t = v * (0.49 - h);
|
||||
# float s = 1.0 - av * 0.5;
|
||||
#
|
||||
# glEnable(GL_POLYGON_OFFSET_FILL);
|
||||
# glPushMatrix();
|
||||
# glScalef(s, 1.0, s);
|
||||
# glTranslatef (0, t, 0);
|
||||
# glPolygonOffset(0.1, 0.1);
|
||||
# renderBar (r, b, h);
|
||||
# glTranslatef (0, -2*t, 0);
|
||||
# glPolygonOffset(0.2, 0.2);
|
||||
# renderBar (r, b, h);
|
||||
# glPopMatrix();
|
||||
#
|
||||
# glPushMatrix();
|
||||
# glRotatef (90, 1.0, 0.0, 0.0);
|
||||
# glScalef(s, 1.0, s);
|
||||
# glTranslatef (0, t, 0);
|
||||
# glPolygonOffset(0.3, 0.3);
|
||||
# renderBar (r, b, h);
|
||||
# glTranslatef (0, -2*t, 0);
|
||||
# glPolygonOffset(0.4, 0.4);
|
||||
# renderBar (r, b, h);
|
||||
# glPopMatrix();
|
||||
#
|
||||
# glPushMatrix();
|
||||
# glRotatef (-90, 0.0, 0.0, 1.0);
|
||||
# glScalef(s, 1.0, s);
|
||||
# glTranslatef (0, t, 0);
|
||||
# glPolygonOffset(0.5, 0.5);
|
||||
# renderBar (r, b, h);
|
||||
# glTranslatef (0, -2*t, 0);
|
||||
# glPolygonOffset(0.6, 0.6);
|
||||
# renderBar (r, b, h);
|
||||
# glPopMatrix();
|
||||
# glDisable(GL_POLYGON_OFFSET_FILL);
|
||||
#
|
||||
# if (active)
|
||||
# colors[KikiGate_sphere_color].glColor();
|
||||
# kDisplaySolidSphere(0.20);
|
||||
|
||||
|
||||
module.exports = Gate
|
||||
|
|
|
@ -21,8 +21,12 @@ class Gear extends Valve
|
|||
|
||||
createMesh: ->
|
||||
@mesh = new THREE.Mesh Geom.gear(), Material.gear
|
||||
@mesh.add new THREE.Mesh Geom.valve(), Material.plate
|
||||
valve = new THREE.Mesh Geom.valve(), Material.plate
|
||||
valve.receiveShadow = true
|
||||
valve.castShadow = true
|
||||
@mesh.add valve
|
||||
@mesh.receiveShadow = true
|
||||
@mesh.castShadow = true
|
||||
|
||||
neighborGears: ->
|
||||
dirs = Gear.neighbors[@face % 3]
|
||||
|
|
|
@ -24,8 +24,10 @@ class Item extends Actor
|
|||
@move_action = null
|
||||
|
||||
del: ->
|
||||
return if @name == 'del'
|
||||
super
|
||||
# log "item del !!!!!!!!!!!!!!!!!!!!!! #{@name}"
|
||||
@name = 'del'
|
||||
world.scene.remove @mesh if @mesh?
|
||||
world.removeObject @
|
||||
@emit 'deleted'
|
||||
|
|
|
@ -16,4 +16,5 @@ module.exports =
|
|||
MotorCylinder: require './motorcylinder'
|
||||
Generator: require './generator'
|
||||
Face: require './face'
|
||||
Switch: require './switch'
|
||||
|
|
@ -10,67 +10,68 @@ class Levels
|
|||
@dict = {}
|
||||
@list = [
|
||||
# "test",
|
||||
"mini",
|
||||
# --- introduction
|
||||
# "steps",
|
||||
# "start",
|
||||
# "move",
|
||||
# "electro",
|
||||
# "elevate",
|
||||
# "throw",
|
||||
"steps",
|
||||
"start",
|
||||
"blocks",
|
||||
"move",
|
||||
"electro",
|
||||
"elevate",
|
||||
"throw",
|
||||
# --- easy
|
||||
# "gold",
|
||||
# "jump",
|
||||
# "escape",
|
||||
# "gears",
|
||||
# "gamma",
|
||||
# "cube",
|
||||
# "switch",
|
||||
# "borg",
|
||||
# "mini",
|
||||
# "blocks",
|
||||
# "bombs",
|
||||
# "sandbox",
|
||||
# "energy",
|
||||
# "maze",
|
||||
"gold",
|
||||
"jump",
|
||||
"escape",
|
||||
"gears",
|
||||
"gamma",
|
||||
"cube",
|
||||
"switch",
|
||||
"borg",
|
||||
"mini",
|
||||
"bombs",
|
||||
"sandbox",
|
||||
"energy",
|
||||
"maze",
|
||||
"love",
|
||||
# --- medium
|
||||
# "towers",
|
||||
# "edge",
|
||||
# "random",
|
||||
# "plate",
|
||||
# "nice",
|
||||
# "entropy",
|
||||
# --- owen hay's levels (TODO: sort in)
|
||||
# "grasp",
|
||||
# "fallen",
|
||||
# "cheese",
|
||||
# "invisimaze",
|
||||
# "spiral",
|
||||
"towers",
|
||||
"edge",
|
||||
"random",
|
||||
"plate",
|
||||
"nice",
|
||||
"entropy",
|
||||
"neutron",
|
||||
"strange",
|
||||
"core",
|
||||
# --- difficult
|
||||
# "slick",
|
||||
# "bridge",
|
||||
# "flower",
|
||||
# "stones",
|
||||
# "walls",
|
||||
# "grid",
|
||||
# "rings",
|
||||
# "core",
|
||||
# "bronze",
|
||||
# "pool",
|
||||
"slick",
|
||||
"bridge",
|
||||
"flower",
|
||||
"stones",
|
||||
"walls",
|
||||
"grid",
|
||||
"rings",
|
||||
"bronze",
|
||||
"pool",
|
||||
# --- owen hay's levels (TODO: sort in)
|
||||
"grasp",
|
||||
"fallen",
|
||||
"cheese",
|
||||
"invisimaze",
|
||||
"spiral",
|
||||
# --- tough
|
||||
# "hidden",
|
||||
# "church",
|
||||
# "strange",
|
||||
# "mesh",
|
||||
# "columns",
|
||||
# "machine",
|
||||
"hidden",
|
||||
"church",
|
||||
"mesh",
|
||||
"columns",
|
||||
"machine",
|
||||
# --- very hard
|
||||
# "neutron",
|
||||
# "captured",
|
||||
# "circuit",
|
||||
# "regal",
|
||||
# "conductor",
|
||||
# "evil",
|
||||
"captured",
|
||||
"circuit",
|
||||
"regal",
|
||||
"conductor",
|
||||
"evil",
|
||||
# outro
|
||||
"mutants"]
|
||||
|
||||
|
|
39
coffee/levels/blocks.coffee
Normal file
39
coffee/levels/blocks.coffee
Normal file
|
@ -0,0 +1,39 @@
|
|||
|
||||
module.exports =
|
||||
name: "blocks"
|
||||
design: 'Michael Abel'
|
||||
scheme: "default_scheme"
|
||||
size: [18,12,5]
|
||||
intro: "blocks"
|
||||
help: """
|
||||
you can grab
|
||||
most stones by pressing forward
|
||||
while jumping or falling down
|
||||
next to them.
|
||||
the slitted stones are slippery,
|
||||
you can't grab them while jumping
|
||||
or falling.
|
||||
the color of a stone has no meaning.
|
||||
"""
|
||||
player:
|
||||
coordinates: [1,6,2]
|
||||
exits: [
|
||||
name: "exit"
|
||||
active: 1
|
||||
coordinates: [7,9,2]
|
||||
]
|
||||
create: ->
|
||||
{Stone} = require '../items'
|
||||
world.addObjectAtPos 'Wall', 1,1,2
|
||||
world.addObjectAtPos 'Wall', 4,2,2
|
||||
world.addObjectAtPos 'Wall', 7,2,2
|
||||
world.addObjectAtPos 'Stone', 10,2,2
|
||||
world.addObjectAtPos new Stone(slippery:true), 13,2,2
|
||||
world.addObjectAtPos new Stone(slippery:true), 15,4,2
|
||||
|
||||
world.addObjectAtPos new Stone(color: [0,1,0], opacity: 0.8, slippery: true), 13,7,2
|
||||
world.addObjectAtPos new Stone(color: [1,0,0], opacity: 0.8, slippery: true), 10,7,2
|
||||
world.addObjectAtPos new Stone(color: [0,0,1], opacity: 0.8, slippery: true), 7,7,2
|
||||
world.addObjectAtPos new Stone(color: [0.5,0.5,0], opacity:0.8), 4,7,2
|
||||
|
||||
world.addObjectLine 'Wall', 0,0,2, 7,0,2
|
|
@ -33,7 +33,7 @@ module.exports =
|
|||
for z in [-3, -1, 1, 3 ]
|
||||
world.addObjectAtPos 'Stone', world.decenter x, y, z
|
||||
|
||||
world.deleteObject world.getOccupantAtPos world.decenter -1, 0, 1
|
||||
world.deleteObject world.getOccupantAtPos world.decenter 1, 0,-1
|
||||
world.deleteObject world.getOccupantAtPos world.decenter 1, 0, 1
|
||||
world.deleteObject world.getOccupantAtPos world.decenter -1, 0,-1
|
||||
world.getOccupantAtPos(world.decenter -1, 0, 1).del()
|
||||
world.getOccupantAtPos(world.decenter 1, 0,-1).del()
|
||||
world.getOccupantAtPos(world.decenter 1, 0, 1).del()
|
||||
world.getOccupantAtPos(world.decenter -1, 0,-1).del()
|
||||
|
|
49
coffee/levels/core.coffee
Normal file
49
coffee/levels/core.coffee
Normal file
|
@ -0,0 +1,49 @@
|
|||
|
||||
# 0000000 0000000 00000000 00000000
|
||||
# 000 000 000 000 000 000
|
||||
# 000 000 000 0000000 0000000
|
||||
# 000 000 000 000 000 000
|
||||
# 0000000 0000000 000 000 00000000
|
||||
|
||||
module.exports =
|
||||
name: "core"
|
||||
design: "Michael Abel"
|
||||
scheme: "yellow_scheme"
|
||||
size: [9,9,9]
|
||||
help: """
|
||||
reach the exit.
|
||||
to reach the exit, move the stones.
|
||||
"""
|
||||
player:
|
||||
position: [1,1,1]
|
||||
orientation: rotz90
|
||||
exits: [
|
||||
name: "exit"
|
||||
active: 1
|
||||
position: [0,0,0]
|
||||
]
|
||||
create: ->
|
||||
|
||||
s = world.size
|
||||
|
||||
for y in [-3, -1, 1, 3]
|
||||
for x in [-3...5]
|
||||
for z in [-3...5]
|
||||
world.addObjectAtPos 'Stone', world.decenter x, y, z
|
||||
|
||||
for y in [-1, 1]
|
||||
for x in [-1, 0, 1]
|
||||
for z in [-1, 0, 1]
|
||||
world.getOccupantAtPos(world.decenter x, y, z).del()
|
||||
for z in [-2, 2]
|
||||
world.getOccupantAtPos(world.decenter 0, y, z).del()
|
||||
|
||||
for x in [-2, 2]
|
||||
world.getOccupantAtPos(world.decenter x, y, 0).del()
|
||||
|
||||
for y in [-3, 3]
|
||||
world.getOccupantAtPos(world.decenter 0, y, 0).del()
|
||||
|
||||
for y in [-4, 4]
|
||||
world.addObjectAtPos 'Stone', world.decenter 0, y, 0
|
||||
|
|
@ -32,7 +32,7 @@ module.exports =
|
|||
create: ->
|
||||
s = world.size
|
||||
d = 2
|
||||
{Gear, Generator, MotorCylinder, MotorGear, Wire} = require '../items'
|
||||
{Gear, Generator, MotorCylinder, MotorGear, Wire, Face} = require '../items'
|
||||
world.addObjectLine('WireStone', world.decenter(-d, s.y/2, 0), world.decenter(-d, 0, 0))
|
||||
world.addObjectLine('WireStone', world.decenter( d, s.y/2, 0), world.decenter( d, 0, 0))
|
||||
world.addObjectLine('WireStone', world.decenter( d, 0, 0), world.decenter( 0, 0, 0))
|
||||
|
@ -45,22 +45,22 @@ module.exports =
|
|||
world.addObjectAtPos(new MotorGear(Face.Y), s.x/2, 0, s.z/2)
|
||||
|
||||
# floor wire square
|
||||
world.addObjectLine(new Wire(Face.Y, 10), s.x/2-d+1, 0, s.z/2-d, s.x/2+d, 0, s.z/2-d)
|
||||
world.addObjectLine(new Wire(Face.Y, 10), s.x/2-d+1, 0, s.z/2+d, s.x/2+d, 0, s.z/2+d)
|
||||
world.addObjectLine(new Wire(Face.Y, 5), s.x/2-d, 0, s.z/2-d+1, s.x/2-d, 0, s.z/2+d)
|
||||
world.addObjectLine(new Wire(Face.Y, 5), s.x/2+d, 0, s.z/2-d+1, s.x/2+d, 0, s.z/2+d)
|
||||
world.addObjectLine('new Wire(Face.Y, 10)', s.x/2-d+1, 0, s.z/2-d, s.x/2+d, 0, s.z/2-d)
|
||||
world.addObjectLine('new Wire(Face.Y, 10)', s.x/2-d+1, 0, s.z/2+d, s.x/2+d, 0, s.z/2+d)
|
||||
world.addObjectLine('new Wire(Face.Y, 5)', s.x/2-d, 0, s.z/2-d+1, s.x/2-d, 0, s.z/2+d)
|
||||
world.addObjectLine('new Wire(Face.Y, 5)', s.x/2+d, 0, s.z/2-d+1, s.x/2+d, 0, s.z/2+d)
|
||||
# corners of wire square
|
||||
world.addObjectAtPos(new Wire(Face.Y, 6), s.x/2-d, 0, s.z/2-d)
|
||||
world.addObjectAtPos(new Wire(Face.Y, 3), s.x/2-d, 0, s.z/2+d)
|
||||
world.addObjectAtPos(new Wire(Face.Y, 9), s.x/2+d, 0, s.z/2+d)
|
||||
world.addObjectAtPos(new Wire(Face.Y, 12), s.x/2+d, 0, s.z/2-d)
|
||||
|
||||
world.addObjectLine(new Wire(Face.X, 5), 0, 0, s.z/2, 0, s.y, s.z/2)
|
||||
world.addObjectLine(new Wire(Face.NX, 5), s.x-1, 0, s.z/2, s.x-1, s.y, s.z/2)
|
||||
world.addObjectLine(new Wire(Face.NY, 10), 0, s.y-1, s.z/2, s.x/2-d, s.y-1, s.z/2)
|
||||
world.addObjectLine(new Wire(Face.NY, 10), s.x-d, s.y-1, s.z/2, s.x, s.y-1, s.z/2)
|
||||
world.addObjectLine(new Wire(Face.Y, 10), 0, 0, s.z/2, s.x/2-d, 0, s.z/2)
|
||||
world.addObjectLine(new Wire(Face.Y, 10), s.x-d, 0, s.z/2, s.x, 0, s.z/2)
|
||||
world.addObjectLine('new Wire(Face.X, 5)', 0, 0, s.z/2, 0, s.y, s.z/2)
|
||||
world.addObjectLine('new Wire(Face.NX, 5)', s.x-1, 0, s.z/2, s.x-1, s.y, s.z/2)
|
||||
world.addObjectLine('new Wire(Face.NY, 10)', 0, s.y-1, s.z/2, s.x/2-d, s.y-1, s.z/2)
|
||||
world.addObjectLine('new Wire(Face.NY, 10)', s.x-d, s.y-1, s.z/2, s.x, s.y-1, s.z/2)
|
||||
world.addObjectLine('new Wire(Face.Y, 10)', 0, 0, s.z/2, s.x/2-d, 0, s.z/2)
|
||||
world.addObjectLine('new Wire(Face.Y, 10)', s.x-d, 0, s.z/2, s.x, 0, s.z/2)
|
||||
world.addObjectAtPos(new Wire(Face.Y, 13), s.x/2-d, 0, s.z/2)
|
||||
world.addObjectAtPos(new Wire(Face.Y, 7), s.x/2+d, 0, s.z/2)
|
||||
|
|
@ -29,24 +29,24 @@ module.exports =
|
|||
exits: [
|
||||
name: "exit"
|
||||
active: 0
|
||||
position: 2,-2,0
|
||||
position: [2,-2,0]
|
||||
]
|
||||
create: ->
|
||||
|
||||
s = world.size
|
||||
{MotorCylinder, MotorGear, Gear, Wire} = require '../items'
|
||||
{MotorCylinder, MotorGear, Generator, Gear, Wire, Face} = require '../items'
|
||||
world.addObjectAtPos(new MotorGear(Face.NY), s.x/2-3, s.y-1, s.z/2)
|
||||
world.addObjectAtPos(new MotorCylinder(Face.NY), s.x/2-3, s.y-2, s.z/2)
|
||||
world.addObjectAtPos(new Generator (Face.NY), s.x/2+2, 1, s.z/2-1)
|
||||
world.addObjectAtPos(new Generator(Face.NY), s.x/2+2, 1, s.z/2-1)
|
||||
world.addObjectAtPos(new Gear(Face.NY), s.x/2+1, 1, s.z/2+1)
|
||||
world.addObjectAtPos(new Gear(Face.NY), s.x/2, 1, s.z/2-1)
|
||||
world.addObjectAtPos(new Gear(Face.NY), s.x/2-1, 1, s.z/2+1)
|
||||
world.addObjectAtPos(new Gear(Face.NY), s.x/2-2, 1, s.z/2-1)
|
||||
|
||||
world.addObjectLine(new Wire(Face.NY, Wire.VERTICAL), s.x/2+2, s.y-1, 0, s.x/2+2, s.y-1, s.z)
|
||||
world.addObjectLine(new Wire(Face.Y, Wire.VERTICAL), s.x/2+2, 0, 0, s.x/2+2, 0, s.z)
|
||||
world.addObjectLine(new Wire(Face.Z, Wire.VERTICAL), s.x/2+2, 0, 0, s.x/2+2, s.y, 0)
|
||||
world.addObjectLine(new Wire(Face.NZ, Wire.VERTICAL), s.x/2+2, 0, s.z-1, s.x/2+2, s.y, s.z-1)
|
||||
world.addObjectLine('new Wire(Face.NY, Wire.VERTICAL)', s.x/2+2, s.y-1, 0, s.x/2+2, s.y-1, s.z)
|
||||
world.addObjectLine('new Wire(Face.Y, Wire.VERTICAL)', s.x/2+2, 0, 0, s.x/2+2, 0, s.z)
|
||||
world.addObjectLine('new Wire(Face.Z, Wire.VERTICAL)', s.x/2+2, 0, 0, s.x/2+2, s.y, 0)
|
||||
world.addObjectLine('new Wire(Face.NZ, Wire.VERTICAL)', s.x/2+2, 0, s.z-1, s.x/2+2, s.y, s.z-1)
|
||||
|
||||
world.addObjectAtPos('Bomb', s.x/2+2, 0, s.z/2-1)
|
||||
world.addObjectAtPos('Bomb', s.x/2+1, 0, s.z/2+1)
|
||||
|
|
|
@ -24,7 +24,7 @@ module.exports =
|
|||
|
||||
world.addObjectLine 'Wall', [0, s.y/2, s.z/2], [s.x, s.y/2, s.z/2]
|
||||
world.addObjectLine 'Wall', [s.x/2, s.y/2, 0], [s.x/2, s.y/2, s.z]
|
||||
world.deleteObject world.getOccupantAtPos world.decenter 0,0,0
|
||||
world.getOccupantAtPos(world.decenter 0,0,0).del()
|
||||
|
||||
world.addObjectAtPos 'Wall', world.decenter 0, 3, 0
|
||||
world.addObjectAtPos 'Wall', world.decenter 0, 6, 0
|
||||
|
|
|
@ -32,13 +32,13 @@ module.exports =
|
|||
s = world.size
|
||||
world.switch_countera = 0
|
||||
world.switch_counter = 0
|
||||
|
||||
{Switch} = require '../items'
|
||||
aswitched = () ->
|
||||
# applyColorScheme(schemes[world.switch_countera])
|
||||
if world.switch_countera==schemes.length-1
|
||||
world.switch_countera=0
|
||||
else
|
||||
world.switch_countera+=1
|
||||
# if world.switch_countera==schemes.length-1
|
||||
# world.switch_countera=0
|
||||
# else
|
||||
# world.switch_countera+=1
|
||||
switched = (swtch) ->
|
||||
world.switch_counter += swtch.active and 1 or -1
|
||||
exit = world.getObjectWithName "exit"
|
||||
|
|
37
coffee/levels/neutron.coffee
Normal file
37
coffee/levels/neutron.coffee
Normal file
|
@ -0,0 +1,37 @@
|
|||
|
||||
# 000 000 00000000 000 000 000000000 00000000 0000000 000 000
|
||||
# 0000 000 000 000 000 000 000 000 000 000 0000 000
|
||||
# 000 0 000 0000000 000 000 000 0000000 000 000 000 0 000
|
||||
# 000 0000 000 000 000 000 000 000 000 000 000 0000
|
||||
# 000 000 00000000 0000000 000 000 000 0000000 000 000
|
||||
|
||||
module.exports =
|
||||
name: "neutron"
|
||||
design: 'Michael Abel'
|
||||
scheme: "neutron_scheme"
|
||||
size: [11,11,11]
|
||||
help: """
|
||||
$scale(1.5)mission:
|
||||
get to the exit!
|
||||
|
||||
it looks simpler than it is.
|
||||
"""
|
||||
player:
|
||||
"position": [0,-1,0]
|
||||
"nostatus": 0
|
||||
exits: [
|
||||
"name": "exit"
|
||||
"active": 1
|
||||
"position": [0,0,0]
|
||||
]
|
||||
"create": ->
|
||||
|
||||
# neutron_scheme["KikiStone"] = "base": [0.0, 0.5, 0.5, 0.5]
|
||||
|
||||
world.addObjectAtPos 'Stone', world.decenter 0,0,-5
|
||||
world.addObjectAtPos 'Stone', world.decenter 0,0,+5
|
||||
world.addObjectAtPos 'Stone', world.decenter +5,0,0
|
||||
world.addObjectAtPos 'Stone', world.decenter -5,0,0
|
||||
world.addObjectAtPos 'Stone', world.decenter 0,+5,0
|
||||
world.addObjectAtPos 'Stone', world.decenter 0,-5,0
|
||||
|
|
@ -11,7 +11,6 @@ module.exports =
|
|||
design: 'Michael Abel'
|
||||
scheme: "tron_scheme"
|
||||
size: [11,11,11]
|
||||
intro: "nice"
|
||||
help: "$scale(1.5)mission:\nget to the exit!"
|
||||
player: position: [2,-1,0]
|
||||
exits: [
|
||||
|
@ -24,25 +23,16 @@ module.exports =
|
|||
supercube = (point=[5,5,5],size=2,obj='Wall') ->
|
||||
p=point
|
||||
s=size
|
||||
world.addObjectPoly(obj,[[p[0]+s,p[1]+s,p[2]],
|
||||
[p[0]+s,p[1]-s,p[2]],
|
||||
[p[0]-s,p[1]-s,p[2]],
|
||||
[p[0]-s,p[1]+s,p[2]] ])
|
||||
world.addObjectPoly(obj,[[p[0]+s,p[1],p[2]+s],
|
||||
[p[0]+s,p[1],p[2]-s],
|
||||
[p[0]-s,p[1],p[2]-s],
|
||||
[p[0]-s,p[1],p[2]+s] ])
|
||||
world.addObjectPoly(obj,[[p[0],p[1]+s,p[2]+s],
|
||||
[p[0],p[1]+s,p[2]-s],
|
||||
[p[0],p[1]-s,p[2]-s],
|
||||
[p[0],p[1]-s,p[2]+s] ])
|
||||
world.addObjectPoly obj,[[p[0]+s,p[1]+s,p[2]], [p[0]+s,p[1]-s,p[2]], [p[0]-s,p[1]-s,p[2]], [p[0]-s,p[1]+s,p[2]]]
|
||||
world.addObjectPoly obj,[[p[0]+s,p[1],p[2]+s], [p[0]+s,p[1],p[2]-s], [p[0]-s,p[1],p[2]-s], [p[0]-s,p[1],p[2]+s]]
|
||||
world.addObjectPoly obj,[[p[0],p[1]+s,p[2]+s], [p[0],p[1]+s,p[2]-s], [p[0],p[1]-s,p[2]-s], [p[0],p[1]-s,p[2]+s]]
|
||||
|
||||
s = world.size
|
||||
world.addObjectLine('Wall', 1,1,1, 9,9,9)
|
||||
world.addObjectLine('Wall', 1,1,9, 9,9,1)
|
||||
world.addObjectLine('Wall', 1,9,1, 9,1,9)
|
||||
world.addObjectLine('Wall', 9,1,1, 1,9,9)
|
||||
world.deleteObject(world.getOccupantAtPos(world.decenter(0,0,0)))
|
||||
supercube(point=[5,5,5],size=5,obj='Wall')
|
||||
supercube(point=[5,5,5],size=3,obj='Stone')
|
||||
world.addObjectLine 'Wall', 1,1,1, 9,9,9
|
||||
world.addObjectLine 'Wall', 1,1,9, 9,9,1
|
||||
world.addObjectLine 'Wall', 1,9,1, 9,1,9
|
||||
world.addObjectLine 'Wall', 9,1,1, 1,9,9
|
||||
world.getOccupantAtPos(world.decenter(0,0,0)).del()
|
||||
supercube point=[5,5,5],size=5,obj='Wall'
|
||||
supercube point=[5,5,5],size=3,obj='Stone'
|
||||
|
84
coffee/levels/strange.coffee
Normal file
84
coffee/levels/strange.coffee
Normal file
|
@ -0,0 +1,84 @@
|
|||
|
||||
# 0000000 000000000 00000000 0000000 000 000 0000000 00000000
|
||||
# 000 000 000 000 000 000 0000 000 000 000
|
||||
# 0000000 000 0000000 000000000 000 0 000 000 0000 0000000
|
||||
# 000 000 000 000 000 000 000 0000 000 000 000
|
||||
# 0000000 000 000 000 000 000 000 000 0000000 00000000
|
||||
|
||||
module.exports =
|
||||
name: "strange"
|
||||
deisgn: 'Michael Abel'
|
||||
scheme: "default_scheme"
|
||||
size: [9,9,9]
|
||||
help: """
|
||||
$scale(1.5)mission:
|
||||
activate the exit!
|
||||
|
||||
to activate the exit,
|
||||
feed it with electricity:
|
||||
|
||||
connect the generator
|
||||
with the motor
|
||||
|
||||
place a wire stone
|
||||
next to the exit
|
||||
"""
|
||||
player:
|
||||
position: [1,2,0]
|
||||
exits: [
|
||||
name: "exit"
|
||||
active: 0
|
||||
position: [0,0,-2]
|
||||
]
|
||||
create: ->
|
||||
s = world.size
|
||||
d = 2
|
||||
{MotorGear, MotorCylinder, Generator, Face} = require '../items'
|
||||
world.addObjectAtPos 'Bomb', world.decenter 0, 0, 0
|
||||
|
||||
world.addObjectAtPos 'WireStone', world.decenter 1, 0, 0
|
||||
world.addObjectAtPos 'WireStone', world.decenter 0, 1, 0
|
||||
world.addObjectAtPos 'WireStone', world.decenter -1, 0, 0
|
||||
world.addObjectAtPos 'WireStone', world.decenter 0, -1, 0
|
||||
|
||||
world.addObjectAtPos 'Bomb', 1, 1, d
|
||||
world.addObjectAtPos 'Bomb', s.x-2, s.y-2, d
|
||||
world.addObjectAtPos 'Bomb', s.x-2, 1, d
|
||||
world.addObjectAtPos 'Bomb', 1, s.y-2, d
|
||||
|
||||
d = s.z-2
|
||||
|
||||
world.addObjectAtPos 'Bomb', 1, 1, d
|
||||
world.addObjectAtPos 'Bomb', s.x-2, s.y-2, d
|
||||
world.addObjectAtPos 'Bomb', s.x-2, 1, d
|
||||
world.addObjectAtPos 'Bomb', 1, s.y-2, d
|
||||
|
||||
world.addObjectAtPos 'Bomb', s.x/2, s.y/2, d
|
||||
world.addObjectAtPos 'Bomb', s.x/2, 1, d
|
||||
world.addObjectAtPos 'Bomb', 1, s.y/2, d
|
||||
world.addObjectAtPos 'Bomb', s.x/2, s.y-2, d
|
||||
world.addObjectAtPos 'Bomb', s.x-2, s.y/2, d
|
||||
|
||||
d = 2
|
||||
|
||||
world.addObjectAtPos 'Stone', s.x/2-1, 1, d
|
||||
world.addObjectAtPos 'Stone', s.x/2+1, 1, d
|
||||
|
||||
world.addObjectAtPos 'Stone', s.x/2-1, s.y-2, d
|
||||
world.addObjectAtPos 'Stone', s.x/2+1, s.y-2, d
|
||||
|
||||
world.addObjectAtPos 'Stone', 1, s.y/2-1, d
|
||||
world.addObjectAtPos 'Stone', 1, s.y/2+1, d
|
||||
|
||||
world.addObjectAtPos 'Stone', s.x-2, s.y/2-1, d
|
||||
world.addObjectAtPos 'Stone', s.x-2, s.y/2+1, d
|
||||
|
||||
world.addObjectAtPos new MotorGear(Face.NZ), s.x/2+1, s.y/2, s.z-1
|
||||
world.addObjectAtPos new MotorCylinder(Face.NZ), s.x/2+1, s.y/2, s.z-2
|
||||
world.addObjectAtPos new Generator(Face.NZ), s.x/2, s.y/2, s.z/2+1
|
||||
world.addObjectLine "new Wire(Face.NY, Wire.VERTICAL)", s.x/2, s.y-1, 0, s.x/2, s.y-1, s.z
|
||||
world.addObjectLine "new Wire(Face.Y, Wire.VERTICAL)", s.x/2, 0, 0, s.x/2, 0, s.z
|
||||
world.addObjectLine "new Wire(Face.Z, Wire.VERTICAL)", s.x/2, 0, 0, s.x/2, s.y, 0
|
||||
world.addObjectLine "new Wire(Face.NZ, Wire.VERTICAL)", s.x/2, 0, s.z-1, s.x/2, s.y, s.z-1
|
||||
|
||||
|
|
@ -29,6 +29,11 @@ class Light extends Item
|
|||
opacity: 0.7
|
||||
emissive: 0xffff00
|
||||
emissiveIntensity: 0.9
|
||||
|
||||
# world.scene.add new THREE.CameraHelper @point.shadow.camera if @shadow
|
||||
|
||||
@point.shadow.camera.near = 0.1
|
||||
@point.shadow.camera.far = @radius*2
|
||||
|
||||
@mesh = new THREE.Mesh geom, mat
|
||||
world.scene.add @point
|
||||
|
|
|
@ -92,4 +92,9 @@ module.exports =
|
|||
emissive: 0x880000
|
||||
emissiveIntensity: 0.02
|
||||
|
||||
stone: new THREE.MeshPhongMaterial
|
||||
side: THREE.DoubleSide
|
||||
shading: THREE.SmoothShading
|
||||
transparent: true
|
||||
shininess: 20
|
||||
|
|
@ -32,6 +32,7 @@ class MotorCylinder extends Pushable #Item
|
|||
@kolben = new THREE.Mesh Geom.kolben(), Material.gear
|
||||
@mesh.add @kolben
|
||||
@mesh.receiveShadow = true
|
||||
@mesh.castShadow = true
|
||||
|
||||
updateMesh: ->
|
||||
@kolben.position.set 0, 0, -0.5 * Math.sin @value
|
||||
|
|
|
@ -25,8 +25,11 @@ class MotorGear extends Gear
|
|||
createMesh: ->
|
||||
@mesh = new THREE.Mesh Geom.motor(), Material.plate
|
||||
@gear = new THREE.Mesh Geom.gear(), Material.gear
|
||||
@gear.receiveShadow = true
|
||||
@gear.castShadow = true
|
||||
@mesh.add @gear
|
||||
@mesh.receiveShadow = true
|
||||
@mesh.castShadow = true
|
||||
|
||||
initAction: (action) ->
|
||||
# log "MotorGear.initAction action #{action.name}"
|
||||
|
|
|
@ -284,19 +284,7 @@ class Player extends Bot
|
|||
# Controller.displayText "game over"
|
||||
world.playSound 'BOT_DEATH'
|
||||
world.setCameraMode world.CAMERA_FOLLOW
|
||||
|
||||
reborn: () ->
|
||||
@died = false
|
||||
|
||||
# reset: () ->
|
||||
# super
|
||||
# Timer.removeActionsOfObject @
|
||||
#
|
||||
# @look_action = null
|
||||
# @look_angle = 0.0
|
||||
# @new_dir_sgn = 1.0
|
||||
# @rotate = 0
|
||||
|
||||
|
||||
# 000 000 00000000 000 000
|
||||
# 000 000 000 000 000
|
||||
# 0000000 0000000 00000
|
||||
|
|
|
@ -5,32 +5,42 @@
|
|||
# 0000000 000 0000000 000 000 00000000
|
||||
|
||||
Pushable = require './pushable'
|
||||
Material = require './material'
|
||||
|
||||
class Stone extends Pushable
|
||||
|
||||
constructor: (opt) ->
|
||||
@slippery = opt?.slippery or false
|
||||
@opacity = opt?.opacity ? 0.7
|
||||
@color = 0xff8800
|
||||
if opt?.color
|
||||
if Array.isArray opt.color
|
||||
@color = new THREE.Color opt.color[0], opt.color[1], opt.color[2]
|
||||
else
|
||||
@color = opt.color
|
||||
@geom = new THREE.BoxGeometry 0.98,0.98,0.98
|
||||
|
||||
@mat = new THREE.MeshPhongMaterial
|
||||
color: @color
|
||||
side: THREE.DoubleSide
|
||||
shading: THREE.SmoothShading
|
||||
transparent: true
|
||||
opacity: opt?.opacity ? 0.7
|
||||
shininess: 20
|
||||
|
||||
@mesh = new THREE.Mesh @geom, @mat
|
||||
@mesh.receiveShadow = true
|
||||
@mesh.castShadow = true
|
||||
@color = opt.color
|
||||
log 'color: ', @color
|
||||
super
|
||||
|
||||
isSlippery: -> return @slippery
|
||||
|
||||
createMesh: ->
|
||||
if @slippery
|
||||
for x in [-1,1]
|
||||
for y in [-1,1]
|
||||
for z in [-1,1]
|
||||
cube = new THREE.BoxGeometry 0.48, 0.48, 0.48
|
||||
cube.translate x * 0.25, y * 0.25, z * 0.25
|
||||
if not @geom
|
||||
@geom = cube
|
||||
else
|
||||
@geom.merge cube
|
||||
else
|
||||
@geom = new THREE.BoxBufferGeometry 0.98,0.98,0.98
|
||||
@mat = Material.stone.clone()
|
||||
@mat.opacity = @opacity
|
||||
@mat.color.set @color
|
||||
@mesh = new THREE.Mesh @geom, @mat
|
||||
@mesh.receiveShadow = true
|
||||
@mesh.castShadow = true
|
||||
|
||||
module.exports = Stone
|
||||
|
|
|
@ -40,7 +40,7 @@ class Switch extends Item
|
|||
|
||||
createMesh: () ->
|
||||
torusRadius = 0.05
|
||||
t1 = new THREE.TorusGeometry 0.5-torusRadius, torusRadius, 16, 32
|
||||
t1 = new THREE.TorusBufferGeometry 0.5-torusRadius, torusRadius, 16, 32
|
||||
@mat = new THREE.MeshPhongMaterial
|
||||
color: 0x0000ff
|
||||
side: THREE.FrontSide
|
||||
|
@ -48,14 +48,16 @@ class Switch extends Item
|
|||
shininess: 5
|
||||
@mesh = new THREE.Mesh t1, @mat
|
||||
@mesh.castShadow = true
|
||||
@mesh.receiveShadow = true
|
||||
|
||||
t2 = new THREE.TorusGeometry 0.5-torusRadius, torusRadius, 16, 32
|
||||
t3 = new THREE.TorusGeometry 0.5-torusRadius, torusRadius, 16, 32
|
||||
t2 = new THREE.TorusBufferGeometry 0.5-torusRadius, torusRadius, 16, 32
|
||||
# t3 = new THREE.TorusGeometry 0.5-torusRadius, torusRadius, 16, 32
|
||||
t2.rotateY Vector.DEG2RAD 90
|
||||
t3.rotateX Vector.DEG2RAD 90
|
||||
t2.merge t3
|
||||
# t3.rotateX Vector.DEG2RAD 90
|
||||
# t2.merge t3
|
||||
@tors = new THREE.Mesh t2, @mat
|
||||
@tors.castShadow = true
|
||||
@tors.receiveShadow = true
|
||||
@mesh.add @tors
|
||||
@mesh
|
||||
|
||||
|
|
|
@ -253,14 +253,9 @@ class World extends Actor
|
|||
# ............................................................ init
|
||||
# @init() # tell the world that we are finished
|
||||
|
||||
restart: () ->
|
||||
# restores the player status and restarts the current level
|
||||
@player.status.setMoves 0
|
||||
@player.reborn()
|
||||
@create()
|
||||
restart: () -> @create @dict
|
||||
|
||||
finish: () ->
|
||||
log 'world.levelFinished'
|
||||
finish: () -> # log 'world.levelFinished'
|
||||
# saves the current level status in highscore file
|
||||
# highscore.levelFinished world.level_name, Controller.player.getStatus().getMoves()
|
||||
|
||||
|
@ -397,12 +392,13 @@ class World extends Actor
|
|||
|
||||
setObjectRandom: (object) ->
|
||||
# adds number objects of type at random positions to the world
|
||||
object_set = 0
|
||||
while not object_set # hack alert!
|
||||
random_pos = new Pos randInt(@size.x), randInt(@size.y), randInt(@size.z)
|
||||
if not object.isSpaceEgoistic() or @isUnoccupiedPos(random_pos)
|
||||
@addObjectAtPos object, random_pos
|
||||
object_set = 1
|
||||
objectSet = false
|
||||
object = @newObject object
|
||||
while not objectSet # hack alert!
|
||||
randomPos = new Pos randInt(@size.x), randInt(@size.y), randInt(@size.z)
|
||||
if not object.isSpaceEgoistic() or @isUnoccupiedPos randomPos
|
||||
@addObjectAtPos object, randomPos
|
||||
objectSet = true
|
||||
|
||||
# 0000000 0000000 000 00000000 0000000 000000000 0000000
|
||||
# 000 000 000 000 000 000 000 000 000
|
||||
|
@ -494,14 +490,7 @@ class World extends Actor
|
|||
# 000 000 0000000 000 0000000 000 0000000
|
||||
# 000 000 000 000 000 000 000
|
||||
# 0000000 00000000 0000000 00000000 000 00000000
|
||||
|
||||
deleteObject: (object) ->
|
||||
if not object?
|
||||
log "world.deleteObject [WARNING] no object?"
|
||||
return
|
||||
@removeObject object
|
||||
object.del()
|
||||
|
||||
|
||||
deleteAllObjects: () ->
|
||||
Timer.removeAllActions()
|
||||
|
||||
|
@ -899,6 +888,8 @@ class World extends Actor
|
|||
switch combo
|
||||
when '=' then @speed = Math.min 10, @speed+1
|
||||
when '-' then @speed = Math.max 1, @speed-1
|
||||
when 'r' then @restart()
|
||||
when 'n' then @exitLevel()
|
||||
|
||||
modKeyComboEventUp: (mod, key, combo, event) ->
|
||||
return if @player?.modKeyComboEventUp mod, key, combo, event
|
||||
|
|
Loading…
Reference in New Issue
Block a user