We are having a few issues that we couldn't solve properly for the past 6 months. Granted we have lack of experience and knowledge to solve these issues, and sorry to say we are at our limit. Therefore we love to hear from the community about the following issues and what would be the best way to go about it: (FYI, we are using EE 1.0)
1.
Object Avoidance. For some strange reason, we couldn't get the NPC to either:
- avoid each other. This mostly occur if the roaming NPC meet with a standing NPC (not moving) ones.
- avoid smaller or short props. This happen if there an object infront but are of shorter props (such as fences or boxes)
- avoid Wall in Dungeon/Caves. This is another strange occurrence. The NPC/Monster will continue to walk against the wall and continue walking while stuck at the front of the wall. We set the Dungeon/Caves as Terrain. Is there anyway we could resolve this?
2.
NPC Roaming.
- We tried various way to make them roam only to certain designated area by assigning a waypoint but that too didn't work. And the NPC keep roaming away from it. Is there better method to assign NPC that roams to only certain path?
3.
Monster/Enemies Roaming. This is another headache. The Monsters roam almost everywhere. We want to set the monsters only roam within the spawn area radius. Say 10-20 meter max from where they spawn. Is there better method we could do this?
4.
NPC/Main Char unable to go straight from Point A to B even in relatively short distance. The problem is when the characters are trying to perform or get from point A to B (which is a straight line), but they will get confused and unable to find the location (i.e. Point B) hence the character will start walking in circle around until it reach to point B. There is nothing wrong with the path, and the pathmesh is created nicely in and by EE.
The following is our code, and we couldn't find better solution. Is there something with our code or is our approach to the above issues wrong? We love to hear what you think and what's the best way to resolve these issues Any tips/advice would be highly appreciate and thank you in advance.
Code:
void DummyChr::findPath(){
//paths are set on stack basis. main destination being the last path node
//new positions are created in order to avoid the obstacle and added to the stack
//characters will access the path stack and move accordingly
//find the obstacles
//set elongated box in front of characters to detect the objects ahead
//press '.' to view the box
obstacleDetector.setBox(matrix());
//check for objects
UInt actor_groups=AG_CONTROLLER;
struct PathBlockCutsCallback : PhysCutsCallback{
Bool cuts;
DummyChr *caster;
Bool hit(ActorInfo &actor_info){
//if the obstacle object is not one of its target objects, avoid
if(actor_info.obj!=caster){
if(actor_info.obj!=&caster->targetNpc() &&
actor_info.obj!=&caster->targetParty() &&
actor_info.obj!=&caster->targetChest() &&
actor_info.obj!=&caster->targetEnemy())
{
//check if obstacle detection is necessary.
Vec start=caster->ctrlPos()+Vec(0,1,0), // starting position of ray
end=caster->targetPos.first()+Vec(0,1,0); // ending position of ray
PhysHit phys_hit; // phys-hit object for receiving hit parameters if any
UInt actor_groups=AG_CONTROLLER;
if(Physics.ray(start,end-start,&phys_hit,actor_groups))
{
//check if targetposition is closer than obstacle position
if(Dist(actor_info.obj->pos(),caster->pos())>Dist(caster->targetPos.first(),caster->pos())) return false;
//avoidance is based on rotation of the mover.
//a new point will be calculated based on the rotation amount and new point distance
Flt rotateAngle=Dist(actor_info.obj->pos(),caster->pos());
//nearer the obstacle rotation of the mover should be high while rotated distance should be less
Vec newTarget=RotatePoint(caster->matrix(),15-rotateAngle,rotateAngle+1);
//add the new target position to the stack
caster->targetPos.add(newTarget);
caster->actionMoveTo(caster->targetPos.last());
caster->blockingObj=CAST(DummyChr,actor_info.obj);
cuts=true;
caster->state=STATE_AVOIDING_OBSTACLE;
}
return false; // no need for further checking
}
}
return true; // check further
}
PathBlockCutsCallback(DummyChr *caster){
T.cuts =false;
T.caster=caster;
}
};
// check for collision
if(action){
PathBlockCutsCallback pcc(&T);
Physics.cuts(obstacleDetector.ob,pcc,actor_groups);
//if no longer obstacle in path move to initial target pos
if(!pcc.cuts){
Vec t=targetPos.first();
actionMoveTo(t);
}
}
//ray testing for walls
if(targetPos.elms()){
PhysHit phys_hit; // phys-hit object for receiving hit parameters if any
Vec start=ctrlPos()+Vec(0,1,0),
end=matrix().z*100;
UInt actor_groups=AG_TERRAIN;
if(Physics.ray(start,end-start,&phys_hit,actor_groups))if(phys_hit.group==AG_TERRAIN){
Flt dt=Dist(targetPos.first(),ctrlPos());
Flt dp=Dist(phys_hit.plane.pos,ctrlPos());
if(dt>dp){
//Vec newTarget=RotatePoint(matrix(),15,5);
//targetPos.add(newTarget);
//actionMoveTo(targetPos.last());
}
}
}
//if not moving and not reached destination while destination still valid, move to destination position
if(!action && targetPos.elms()){
Vec t=targetPos.first();
Flt d=Dist(t,pos());
if(Abs(d)>ctrl.radius()){
actionMoveTo(t);
}
else targetPos.clear();
}
//if moving, and reached destination, clear the path stack and stop
else if(targetPos.elms()){
Vec t=targetPos.first();
Flt d=Dist(t,pos());
if(Abs(d)<ctrl.radius()*1.1f) {actionBreak();targetPos.clear();}
}
}