/* jshint esversion: 6 */
/* jshint asi: true */
/* jshint expr: true */
/* jslint vars: true */
var MaiAi = pc.createScript('MaiAi');
var MaiAiTargetIsAudible = false;
MaiAi.attributes.add('MaiAiTarget', { type: 'entity', title: 'Target Entity' });
MaiAi.attributes.add('MaiAiHeight', { type: 'number', default: 1, title: 'MaiAi Height' });
MaiAi.attributes.add('MaiAiSpeed', { type: 'number', default: 1, title: 'MaiAi Speed' });
MaiAi.attributes.add('MaiAiRange', { type: 'number', default: 5, title: 'MaiAi Range' });
// initialize code called once per entity
MaiAi.prototype.initialize = function () {
this.MaiAiState = 'search';
this.MaiAiTargetDistance = 0;
this.MaiAiStateTimer = 0;
this.MaiAiCanSeeTarget = false;
this.MaiAiDestination = new pc.Vec3();
this.MaiAiOrigin = new pc.Vec3();
this.MaiAiOrigin.copy(this.entity.getPosition());
};
// update code called every frame
MaiAi.prototype.update = function (dt) {
this.detectroot(dt);
this.applyGravity(dt);
this.updateState(dt);
this.updateView(dt);
};
// this function controls the view of the MaiAi
MaiAi.prototype.updateView = function () {
this.MaiAiCanSeeTarget = false;
if (this.MaiAiTarget) {
// check distance to target
this.MaiAiTargetDistance = this.entity.getPosition().distance(this.MaiAiTarget.getPosition());
// check if target is in range
if (this.MaiAiTargetDistance < 50) {
var target = this.MaiAiTarget.getPosition();
target.sub(this.entity.getPosition()).normalize();
var dot = target.dot(this.entity.forward);
// check if target is in front
if (dot > 0.5 || this.MaiAiCanSeeTarget) {
var start = new pc.Vec3(this.entity.getPosition().x, this.entity.getPosition().y + this.MaiAiHeight / 2, this.entity.getPosition().z);
var end = new pc.Vec3(this.MaiAiTarget.getPosition().x, this.MaiAiTarget.getPosition().y + this.MaiAiHeight / 2, this.MaiAiTarget.getPosition().z);
var result = this.raycastRigidbody(start, end);
// check if target is in view
if (result && result.entity === this.MaiAiTarget) {
this.MaiAiCanSeeTarget = true;
//this.app.drawLine(start, end);
if (!this.MaiAiIsBlocked) {
this.MaiAiDestination.copy(new pc.Vec3(this.MaiAiTarget.getPosition().x, this.MaiAiHeight, this.MaiAiTarget.getPosition().z));
}
}
}
}
}
};
// this function controls the MaiAi state
MaiAi.prototype.updateState = function (dt) {
// update current state
if (this.MaiAiTarget && this.MaiAiCanSeeTarget) {
this.MaiAiStateTimer = 0;
if (this.MaiAiTargetDistance > 15) {
console.log("alert");
}
else if (this.MaiAiTargetDistance > 10) {
console.log("combat");
}
else if (this.MaiAiTargetDistance < 5) {
console.log("Following");
}
else if (this.MaiAiState != 'combat') {
console.log("combat");
}
}
else if (this.MaiAiTarget && MaiAiTargetIsAudible && this.MaiAiTargetDistance < 15) {
this.MaiAiStateTimer = 0;
this.MaiAiState = 'alert';
}
else if (this.MaiAiState != 'search') {
this.MaiAiStateTimer += dt;
if (this.MaiAiStateTimer > 2) {
this.MaiAiStateTimer = 0;
this.MaiAiState = 'search';
}
}
// exectue current state
this[this.MaiAiState](dt);
};
// alert state
MaiAi.prototype.alert = function (dt) {
this.MaiAiDestination.copy(new pc.Vec3(this.MaiAiTarget.getPosition().x, this.entity.getPosition().y, this.MaiAiTarget.getPosition().z));
this.entity.lookAt(new pc.Vec3(this.MaiAiDestination.x, this.entity.getPosition().y, this.MaiAiDestination.z), this.
this.entity.anim.baseLayer.play('Idle'))
}
// chase state
MaiAi.prototype.chase = function (dt) {
this.MaiAiDestination.copy(new pc.Vec3(this.MaiAiTarget.getPosition().x, this.entity.getPosition().y, this.MaiAiTarget.getPosition().z));
this.entity.lookAt(new pc.Vec3(this.MaiAiDestination.x, this.entity.getPosition().y, this.MaiAiDestination.z));
if (this.MaiAiTargetDistance > 3) {
this.entity.translateLocal(0, 0, -this.MaiAiSpeed * dt * 2);
this.entity.anim.baseLayer.play('Running')
}
}
// combat state
MaiAi.prototype.combat = function (dt) {
this.MaiAiDestination.copy(new pc.Vec3(this.MaiAiTarget.getPosition().x, this.entity.getPosition().y, this.MaiAiTarget.getPosition().z));
this.entity.lookAt(new pc.Vec3(this.MaiAiDestination.x, this.entity.getPosition().y, this.MaiAiDestination.z));
this.entity.anim.baseLayer.play('Jump')
}
// search state
MaiAi.prototype.search = function (dt) {
var distanceToDestination = this.entity.getPosition().distance(new pc.Vec3(this.MaiAiDestination.x, this.entity.getPosition().y, this.MaiAiDestination.z));
if (!this.MaiAiIsBlocked && distanceToDestination > 0.2) {
this.entity.lookAt(new pc.Vec3(this.MaiAiDestination.x, this.entity.getPosition().y, this.MaiAiDestination.z));
this.entity.translateLocal(0, 0, -this.MaiAiSpeed * dt);
}
else {
this.randomDestination();
}
this.entity.anim.baseLayer.play('Walk')
}
// get random point based on origin and range
MaiAi.prototype.randomDestination = function () {
const xPosition = pc.math.random(this.MaiAiOrigin.x - this.MaiAiRange, this.MaiAiOrigin.x + this.MaiAiRange);
const zPosition = pc.math.random(this.MaiAiOrigin.z - this.MaiAiRange, this.MaiAiOrigin.z + this.MaiAiRange);
this.MaiAiDestination.copy(new pc.Vec3(xPosition, this.entity.getPosition().y + this.MaiAiHeight, zPosition));
};
// prevent the MaiAi is moving inside an root
MaiAi.prototype.detectroot = function () {
var position = this.entity.getPosition();
var start = new pc.Vec3(position.x, position.y + (this.MaiAiHeight / 2), position.z);
var end = this.MaiAiDestination;
var result = this.app.systems.rigidbody.raycastFirst(start, end);
this.MaiAiIsBlocked = false;
if (result && (result.entity.tags.has("root"))) {
var distanceToroot = this.entity.getPosition().distance(result.point);
if (distanceToroot < 2) {
this.MaiAiIsBlocked = true;
this.randomDestination();
}
}
};
// apply fake gravity to MaiAi
MaiAi.prototype.applyGravity = function () {
var position = this.entity.getPosition();
var start = new pc.Vec3(position.x, position.y + (this.MaiAiHeight / 2), position.z);
var end = new pc.Vec3(position.x, position.y - this.MaiAiHeight, position.z);
var result = this.app.systems.rigidbody.raycastFirst(start, end);
if (result && result.entity != this.entity) {
if (Math.abs(result.point.y - this.entity.getPosition().y) - this.MaiAiHeight < -0.2) {
this.entity.translateLocal(0, 0.1, 0);
}
}
else {
this.entity.translateLocal(0, -0.1, 0);
}
this.entity.anim.baseLayer.play('Jump')
}
MaiAi.prototype.raycastRigidbody = function (start, end) {
var distanceVec3 = new pc.Vec3();
var closestDistanceSqr = Number.MAX_VALUE;
var closestResult = null;
var results = this.app.systems.rigidbody.raycastAll(start, end);
for (var i = 0; i < results.length; ++i) {
var result = results[i];
if (result.entity.rigidbody) {
distanceVec3.sub2(result.point, start);
var distanceSqr = distanceVec3.lengthSq();
if (distanceSqr < closestDistanceSqr) {
closestDistanceSqr = distanceSqr;
closestResult = result;
}
}
}
return closestResult;
};