Rotating Placeables - 1 Degree Off

void main()
{
    object oObject = OBJECT_SELF;
    float fFacing = GetFacing(oObject);
    float fNewFacing = fFacing - 20.0f;
    if (fNewFacing < 0.0f)
    {
        fNewFacing = 0.0f;
    }
    else if (fNewFacing >= 360.0f)
    {
        fNewFacing = 360.0f - fNewFacing;
    }
    AssignCommand(oObject, SetFacing(fNewFacing));
}

So this script is rotating a placeable in a specific zone. In short it’s for furniture in player housing. My issue is that it’s not lining up. It seems to be one degree off and it doesn’t matter the placeable. I swear I had a post about this years ago but I can’t seem to find it as I think I did correct it but I have a good 100+ saved iterations of my module that I don’t feel like jumping through to find where I once had it corrected, if I ever really did. Anyone know off the top of their head how to fix this?

I ran it through some AI and the above code was spit out. This is the original:

void main()
{
    object oObject = OBJECT_SELF;
    float fFacing = GetFacing(oObject);
    float fNewFacing = fFacing - 20.0f;
    if (fNewFacing < 0.0f)
    {
        fNewFacing = 360.0f - (fNewFacing * 0.0f) ;
    }
    AssignCommand(oObject, SetFacing(fNewFacing));
}


Uploaded a screenshot of the example. Top down view of a placed chest. It’s like one degree off and the rotation scripts for clockwise and counter seem to hold onto that 1 degree off.

When the placeable is created it’s facing is set to 0.0f if that helps.

AssignCommand(oPlaceable, SetFacing(0.0f));

The following line is problematic for 2 reasons -

fNewFacing = 360.0f - (fNewFacing * 0.0f) ;

Multiplying anything by zero will give you zero and even with that corrected there is another problem. Because you test for fNewFacing being less than zero it means that you will effectively be doing -

fNewFacing = 360.0f - (-A) ;

Anyone that can remember maths will tell you that X - (-A) = X + A where A is the current value of fNewFacing.

TR

Does this make more sense?

void main()
{
    object oObject = OBJECT_SELF;
    float fFacing = GetFacing(oObject);
    float fNewFacing = fFacing - 20.0f;
    if (fNewFacing >= 360.0f)
    {
        fNewFacing = fNewFacing - 360.0f;
    }
    AssignCommand(oObject, SetFacing(fNewFacing));
}

I may have copied in one of the non original scripts that I altered. It still worked as far as rotating the object, it just wouldn’t rotate clockwise past 360.

Either way, I changed the value 20 to 21 and it’s correctly aligning the object now. I just don’t understand why exactly since unless all objects are modeled 1 degree off?

Coding wise that is better. A more robust version would be

void main()
{
    object oObject = OBJECT_SELF;
    float fFacing = GetFacing(oObject);
    float fNewFacing = fFacing - 20.0f;
    
    while(fNewFacing >= 360.0f)
        fNewFacing -= 360.0f;

    if(fNewFacing < 0.0f)
        fNewFacing = 0.0f;

    AssignCommand(oObject, SetFacing(fNewFacing));
}

Using while instead of if just makes sure that you’ll get < 360.0f. Followed by a check to make sure that it is at least 0.0f. Using the compound operator -= is the same as what you have written but fewer keystrokes. Probably some redundant code there but you get the idea.

Can’t make any guarantees that it will fix your off by 1 degree problem though.

TR

Given that GetFacing() should never return anything > 360.0 any of the code above that subtracts 20 from the facing is guaranteed to never be >= 360.0.

Is there any reason to set the new facing to 0.0f if it’s initially lower than 20.0f?
I find it odd that if the placing is placed at 350°, it will be rotated to 330° but it the value is entered at -10° (same orientation as 350°), instead of -30° it will be rotated to 0° (i.e. instead of 20° clockwise it will rotate 10° anti-clockwise).

I understand the placeable is created facing East (0°), then rotated -20°. Why not create it facing -20° (or 340°) then? Unless the idea is to click on the placeable and rotate it 20° clockwise each time?