Aller au contenu

Photo

CommandMoveToLocation freeze


  • Veuillez vous connecter pour répondre
8 réponses à ce sujet

#1
anakin5

anakin5
  • Members
  • 258 messages
Im am using the CommandMoveToLocation function to move a character to a defined position on the map.

Most of the time, all is working fine, but sometimes, the command never end. The Move icon stay near the character portrait despite the character has reach his position. The command is locked and never complete.

So I would like to know what is behind CommandMoveToLocation, what should I pay attention when calling it with a vector variable.
I check the vector variable before calling this function with IsLocationValid and IsLocationSafe but nothing changed, sometimes the command doesn't end after completion.

#2
Craig Graff

Craig Graff
  • Members
  • 608 messages
This can be many things. Without knowing more specifics or seeing the area in question it's difficult to know what the problem is.

Are you assigning the command as a static command? Are there a number of creatures or placeables near the location (especially ones that modify pathfinding like the portcullis or the cages)? Have you looked at the pathfinding data for the area (under View > Evironment > Pathfinding Data in the area editor)?

For some scenarios it is better to use CommandMoveToObject and set sufficiently generous values for fMinRange and fMaxRange.

#3
anakin5

anakin5
  • Members
  • 258 messages
I am not assigning it as static. I am using WR_AddCommand with default parameters.

However, yes, there is creatures moving randomly near the destination point, but there is no placeable or other object, it is a really plane area with creatures moving on it.



Sometimes, I can see that these creatures are blocking the character path. I though that was my problem, but when these creatures go away, to command doesn't end. In fact the character is freezed trying to execute a move command event when all creatures around are dead. The end of combat make the command disappear and make the character acting normally again.



Can the command get stuck when the character cannot reach his destination cause to an other creature blocking the path ? What is supposed to do the command in this case and in the case the blocking creature move away ?

#4
Craig Graff

Craig Graff
  • Members
  • 608 messages
Is the creature a party member? If not, it could be that the AI level is dipping too low, causing pathfinding to become very simplistic and prone to such errors. This will usually happen at larger distances from the player. Use GetAILevel to test and try SetAILevel(oCreature, CSERVERAIMASTER_AI_LEVEL_HIGH) if the current level is too low).

Modifié par Craig Graff, 10 février 2010 - 03:04 .


#5
anakin5

anakin5
  • Members
  • 258 messages
It is a party member :s

After more test, it seems to append when an enemy creature is near the destination point, causing the party member to infinitely try to reach the destination. What I don't understand is why, when this enemy go away or die, the problem is still present.

#6
Craig Graff

Craig Graff
  • Members
  • 608 messages
I assume this is for your tactics mod? Is the command queue building up (GetCommandQueueSize), or does each CommandMovetoLocation overwrite the last? I'm poking in the dark without seeing the code, but another thing you might try is adding a timeout to the command, cCommand = SetCommandFloat(cCommand, fTimeout, 5), though I'm not certain that will even work with followers.

#7
anakin5

anakin5
  • Members
  • 258 messages
Yes it is for my tactics mod, here is the function I use for tests :



[color="#99ccff"]command[/color] AT_CommandFlankingAttack([color="#99ccff"]object[/color] oTarget)
{
  [color="#99ccff"]command[/color] cRet = CommandAttack(oTarget);

  [color="#99ccff"]if[/color] ((GetCreatureCoreclass([color="#99ccff"]OBJECT_SELF[/color]) == class_ROGUE)
  && (IsUsingMeleeWeapon([color="#99ccff"]OBJECT_SELF[/color]) == [color="#99ccff"]TRUE[/color]))
  {
    [color="#99ccff"]int[/color] nTargetApp = GetAppearanceType(oTarget);
    [color="#99ccff"]float[/color] fTargetPerSpace = GetM2DAFloat(TABLE_APPEARANCE, [color="#3366ff"]"PERSPACE"[/color], nTargetApp);
    [color="#99ccff"]float[/color] fDistance = fTargetPerSpace + [color="#cc99ff"]1.5f[/color];

    [color="#99ccff"]float[/color] fDistanceToTarget = GetDistanceBetween([color="#99ccff"]OBJECT_SELF[/color], oTarget);

    [color="#99ccff"]if[/color] (fDistanceToTarget <= fDistance + [color="#cc99ff"]1.5f[/color])
    {
      [color="#99cc00"]/* Advanced Tactics */[/color]
      [color="#99cc00"]/* Do not attack behind the enemy in the following situation :
        - The enemy is not in melee range
        - The enemy is attacking you
        - You are already at flank
        - You can one shot the enemy
        - The enemy has special abilities for flankers :)
      */[/color]
      [color="#99ccff"]if[/color] ((GetAttackTarget(oTarget) != [color="#99ccff"]OBJECT_SELF[/color])
      && (AT_IsAtFlank(oTarget) != [color="#99ccff"]TRUE[/color])
      && (IsOneShotKillCreature(oTarget) != [color="#99ccff"]TRUE[/color])
      && (HasAbility(oTarget, MONSTER_DRAGON_TAIL_SLAP) == [color="#99ccff"]FALSE[/color])
      && (HasAbility(oTarget, MONSTER_HIGH_DRAGON_TAIL_FLAP) == [color="#99ccff"]FALSE[/color]))
      {
        [color="#99ccff"]location[/color] lTargetLoc = GetLocation(oTarget);

        [color="#99ccff"]if[/color] (IsLocationValid(lTargetLoc) == [color="#99ccff"]TRUE[/color])
        {
          [color="#99ccff"]vector[/color] vTargetPos = GetPositionFromLocation(lTargetLoc);
          [color="#99ccff"]vector[/color] vTargetOri = GetOrientationFromLocation(lTargetLoc);
          [color="#99ccff"]float[/color] fTargetAngle = VectorToAngle(vTargetOri);
          [color="#99ccff"]object[/color] oTargetArea = GetAreaFromLocation(lTargetLoc);

          [color="#99ccff"]location[/color] lLoc = GetLocation([color="#99ccff"]OBJECT_SELF[/color]);
          [color="#99ccff"]float[/color] fFlankingAngle = GetCreatureProperty([color="#99ccff"]OBJECT_SELF[/color], PROPERTY_ATTRIBUTE_FLANKING_ANGLE);

          [color="#99cc00"]/* Standardize */[/color]
          vTargetPos = AT_PositionToStd(vTargetPos);
          fTargetAngle = AT_AngleToStd(fTargetAngle);
          fFlankingAngle = AT_AngleToStd(fFlankingAngle);

          [color="#99ccff"]float[/color] fAngle1 = fTargetAngle;
          [color="#99ccff"]float[/color] fAngle2 = fTargetAngle + (fFlankingAngle * [color="#cc99ff"]0.25f[/color]);
          [color="#99ccff"]float[/color] fAngle3 = fTargetAngle - (fFlankingAngle * [color="#cc99ff"]0.25f[/color]);

          [color="#99ccff"]vector[/color] delta1 = Vector(fDistance * cos(fAngle1), fDistance * sin(fAngle1), [color="#cc99ff"]0.0f[/color]);
          [color="#99ccff"]vector[/color] delta2 = Vector(fDistance * cos(fAngle2), fDistance * sin(fAngle2), [color="#cc99ff"]0.0f[/color]);
          [color="#99ccff"]vector[/color] delta3 = Vector(fDistance * cos(fAngle3), fDistance * sin(fAngle3), [color="#cc99ff"]0.0f[/color]);

          [color="#99ccff"]vector[/color] vNewPos1 = vTargetPos - delta1;
          [color="#99ccff"]vector[/color] vNewPos2 = vTargetPos - delta2;
          [color="#99ccff"]vector[/color] vNewPos3 = vTargetPos - delta3;

          [color="#99cc00"]/* DAOize */[/color]
          vNewPos1 = AT_StdToPosition(vNewPos1);
          vNewPos2 = AT_StdToPosition(vNewPos2);
          vNewPos3 = AT_StdToPosition(vNewPos3);

          [color="#99ccff"]location[/color] lNewLoc1 = Location(oTargetArea, vNewPos1, [color="#cc99ff"]0.0f[/color]);
          [color="#99ccff"]location[/color] lNewLoc2 = Location(oTargetArea, vNewPos2, [color="#cc99ff"]0.0f[/color]);
          [color="#99ccff"]location[/color] lNewLoc3 = Location(oTargetArea, vNewPos3, [color="#cc99ff"]0.0f[/color]);

          lNewLoc1 = SetLocationOrientation(lNewLoc1, vTargetOri);
          lNewLoc2 = SetLocationOrientation(lNewLoc2, vTargetOri);
          lNewLoc3 = SetLocationOrientation(lNewLoc3, vTargetOri);

          [color="#99ccff"]float[/color] fDistance1 = GetDistanceBetweenLocations(lLoc, lNewLoc1);
          [color="#99ccff"]float[/color] fDistance2 = GetDistanceBetweenLocations(lLoc, lNewLoc2);
          [color="#99ccff"]float[/color] fDistance3 = GetDistanceBetweenLocations(lLoc, lNewLoc3);

          [color="#99ccff"]location[/color] lFinalLoc;

          [color="#99ccff"]if[/color] ((fDistance2 <= fDistance1)
          && (fDistance2 <= fDistance3)
          && (IsLocationValid(lNewLoc2) == [color="#99ccff"]TRUE[/color])
          && (IsLocationSafe(lNewLoc2) == [color="#99ccff"]TRUE[/color]))
            lFinalLoc = lNewLoc2;
          [color="#99ccff"]else[/color] [color="#99ccff"]if[/color] ((fDistance3 <= fDistance1)
          && (IsLocationValid(lNewLoc3) == [color="#99ccff"]TRUE[/color])
          && (IsLocationSafe(lNewLoc3) == [color="#99ccff"]TRUE[/color]))
            lFinalLoc = lNewLoc3;
          [color="#99ccff"]else[/color] [color="#99ccff"]if[/color] ((IsLocationValid(lNewLoc1) == [color="#99ccff"]TRUE[/color])
          && (IsLocationSafe(lNewLoc1) == [color="#99ccff"]TRUE[/color]))
            lFinalLoc = lNewLoc1;

          [color="#99ccff"]if[/color] ((IsLocationValid(lFinalLoc) == [color="#99ccff"]TRUE[/color])
          && (IsLocationSafe(lFinalLoc) == [color="#99ccff"]TRUE[/color]))
          {
            cRet = CommandMoveToLocation(lFinalLoc);
            [color="#99cc00"]//cRet = SetCommandFloat(cRet, 2.0f, 5);[/color]
          }
        }
      }
    }
  }

  [color="#99ccff"]return[/color] cRet;
}

And here functions used in this code.

[color="#99ccff"]vector[/color] AT_PositionToStd([color="#99ccff"]vector[/color] vPos)
{
  [color="#99ccff"]return[/color] Vector(-vPos.y, vPos.x, vPos.z);
}

[color="#99ccff"]vector[/color] AT_StdToPosition([color="#99ccff"]vector[/color] vPos)
{
  [color="#99ccff"]return[/color] Vector(vPos.y, -vPos.x, vPos.z);
}

[color="#99ccff"]float[/color] AT_AngleToStd([color="#99ccff"]float[/color] fAngle)
{
  [color="#99ccff"]return[/color] ToRadians((fAngle + [color="#cc99ff"]180.0f[/color]));
}

The trigonometry part is not really interesting, I know the calculation done here is fine.
This code is part of the standard
ExecuteAttack
function and so is called after :

[color="#99ccff"]command[/color] cCurrent = GetCurrentCommand([color="#99ccff"]OBJECT_SELF[/color]);
[color="#99ccff"]int[/color] nCurrentType = GetCommandType(cCurrent);
[color="#99ccff"]int[/color] nQueueSize = GetCommandQueueSize([color="#99ccff"]OBJECT_SELF[/color]);
[color="#99ccff"]if[/color] ((nCurrentType != [color="#99ccff"]COMMAND_TYPE_INVALID[/color]) || (nQueueSize > 0))
  [color="#99ccff"]return[/color];

Modifié par anakin5, 11 février 2010 - 04:12 .


#8
anakin5

anakin5
  • Members
  • 258 messages
hum, it may be caused by dead enemies body bag. If an enemy die on the target location between the movement duration, his body take the place.



I tested the timeout things and it seems to not been take in account.

#9
anakin5

anakin5
  • Members
  • 258 messages
Well, news, I had the bug several times on really plane area without anything on the ground.

My locations coords are good as well. I also put a mark on the ground to know were the character has to go but sometimes that failed even if the character is on the mark.

The last idea that come in my mind is that the destination is not reachable because the character cannot come as close as he has to be.

Do you know Craig when the engine consider the character has reach the destination ? I mean when the "delta" between his current position and the destination is enough small.
I ask you this because I wonder if I should round coords like "984.4654987654".

I took a screenshot if it can help

EDIT : on the screenshot, the character is "flying", something like 0.1 m over the ground, while the mark is on the ground. That may be a z-coord problem.

Modifié par anakin5, 11 février 2010 - 10:54 .