Okay, so I've scoped the vars properly with this. now, and that works fine for individually spawned NPC objects.
There is, however, still the same problem when instantiating instances of this code as a class - despite this.name attribute being unique for each instance. I believe that there may be an issue with the compiler/interpreter for the scripting language w/r/t classes: Perhaps only copying array header/reference when instantiating objects (thus leaving the reference to the start of the first array, rather than creating a new array for each object)?
Awesome if it could be fixed, anyway.
Cheers,
Cel
PHP Code:
// Created by Frans N Henskens (*Celarion)
// Last Modified 10/07/06 15:22
// Boid NPC
// Uses attraction, repulsion avoidance and
// guidance rules to simulate flocking
// and targetseeking/avoiding behaviour.
//
// Currently reduces a base desired movement vector to
// a desired movement angle, applies trigonometric
// functions to retrieve a unit vector,
// applies acceleration then adds this to current
// velocity vector.Celarion
// This is checked against and constrained by a
// maximum velocity vector.
//
// To Do:
// Implement boid rules of separation, alignment and cohesion
// Assign appropriate biases to each of the resultant vectors
// Replace target point with sum of weighted rule vectors to
// achieve desired movement angle.
// Possibly implement breaking, "perching"
//
// Long Term:
// Implement advanced rules: predators, pathways, prey/food.
//
// Algorithm Complexity (On^2)
//
// NOTE: In Graal, the y-axis is inverted (counting up in a
// downwards direction from the top-left of the screen)
// Thus, all calculations to do with the y-axis have to be
// negated.
function onCreated()
{
// DEPRECATED
targets = {23,17};
// Initialise variables
this.z = -1;
this.dist = {0,0};
this.uv = {0,0};
// viewRadius = 7;
// personalSpaceRadius = 3;
this.acceleration = 1;
this.maxVelocity = 3;
this.granularity = 0.05;
this.distanceThreshold = 3;
this.owner = "Celarion";
showcharacter();
this.headimg = "head3.png";
this.bodyimg = "body13.png";
setcharani("sit", " ");
// setimg("era_hachibluering.png");
setshape(1,0,0);
message(" ");
// Set timer to start behavioural thread
setTimer(this.granularity);
}
function getUnitVector(vec) {
temp.angle = getangle(vec[0], vec[1]);
temp.calcVec = {cos(temp.angle), -sin(temp.angle)};
return temp.calcVec;
}
function onPlayerEnters() {
onTimeout();
}
function onTimeOut() {
// DEPRECATED
// Calculate desired movement vector
// findplayer("Celarion").chat = "Owner: " @ this.target.name @ ", " @ "Targets: x=" @ this.targets[0] SPC "y=" @ this.targets[1] @ ", Distances: x=" @ this.dist[0] @ ", y=" @ this.dist[1];
this.target = findplayer(this.owner);
if (this.target != "")
{
this.targets = {this.target.x, this.target.y};
if (this.level.name != target.level.name) {
warpto(target.level.name, this.targets[0], this.targets[1]);
}
} else {
this.velocity = {0,0};
setTimer(0);
return;
}
this.dist = {this.targets[0] - this.x, this.targets[1] - this.y};
// Locate boids
// Calculate rule 1 :: Separation
// Calculate rule 2 :: Cohesion
// Calculate rule 3 :: Alignment
// Calculate resultant rule vector
// Calculate unit vector for resultant velocity
this.uv = getUnitVector(this.dist);
this.velocity[0] += this.acceleration * this.uv[0];
this.velocity[1] += this.acceleration * this.uv[1];
// Check resultant velocity vector amplitude against max velocity
if ((this.velocity[0]^2 + this.velocity[1]^2)^(1/2) > this.maxVelocity) {
this.uv = getUnitVector(this.velocity);
this.velocity = {this.maxVelocity * this.uv[0], this.maxVelocity * this.uv[1]};
}
// Apply resultant movement vector
this.x = this.x + this.velocity[0];
this.y = this.y + this.velocity[1];
// Set timer to start next behavioural thread
setTimer(this.granularity);
}
function onPlayerChats()
{
if (player.chat.starts("/"))
{
temp.toks = player.chat.tokenize();
if (temp.toks[0] == "/destroy")
{
if (this.owner == temp.toks[1])
{
destroy();
}
}
}
}
EDIT:: Thanks Skyld.