@@ -172,7 +172,7 @@ void AutoStrafeTool::ApplyStrafe(TasFramebulk &fb, const TasPlayerInfo &pInfo) {
172172 }
173173 }
174174
175- float angle = velAngle + RAD2DEG (this ->GetStrafeAngle (pInfo, params)) * params. turnRate ;
175+ float angle = velAngle + RAD2DEG (this ->GetStrafeAngle (pInfo, params));
176176
177177 FOR_TAS_SCRIPT_VERSIONS_SINCE (8 ) {
178178 // Deal with airlock: we're strafing, so always try to maximize how much
@@ -442,6 +442,22 @@ float AutoStrafeTool::GetTurningStrafeAngle(const TasPlayerInfo &player) {
442442 return acosf (cosAng);
443443}
444444
445+ // get horizontal angle of wishdir that would give the biggest turning angle while understrafing
446+ float AutoStrafeTool::GetMaxUnderstrafeAngle (const TasPlayerInfo &player) {
447+ Vector velocity = GetGroundFrictionVelocity (player);
448+
449+ if (velocity.Length2D () == 0 ) return 0 ;
450+
451+ Vector wishDir = Vector (0 , 1 ) * params.force ;
452+ float maxSpeed = GetMaxSpeed (player, wishDir);
453+
454+ // Solution is the angle where dot product of velocity and normalized wishdir is equal to max speed.
455+ float cosAng = maxSpeed / velocity.Length2D ();
456+ if (cosAng > 1 ) cosAng = 1 ;
457+
458+ return acosf (cosAng);
459+ }
460+
445461
446462// get horizontal angle of wishdir that does correct thing based on given parameters
447463// angle is relative to your current velocity direction.
@@ -496,6 +512,7 @@ float AutoStrafeTool::GetStrafeAngle(const TasPlayerInfo &player, AutoStrafePara
496512 ang = GetTargetStrafeAngle (player, params.strafeSpeed .speed , turningDir);
497513 }
498514
515+ ang += GetSteeringOffsetValue (player, params.steeringOffset ) * turningDir;
499516 return ang;
500517}
501518
@@ -630,6 +647,21 @@ void AutoStrafeTool::FollowLine(const TasPlayerInfo &pInfo) {
630647 this ->followLinePoint = pInfo.position ;
631648}
632649
650+ float AutoStrafeTool::GetSteeringOffsetValue (const TasPlayerInfo &pInfo, AutoStrafeSteeringOffset &offset) {
651+ if (offset.type == DEGREES) {
652+ return DEG2RAD (offset.value );
653+ }
654+
655+ bool understrafe = offset.value < 0 ;
656+ float absOffsetScalar = fabsf (offset.value );
657+
658+ float baseAngle = GetFastestStrafeAngle (pInfo);
659+ float unitAngle = understrafe ? GetMaxUnderstrafeAngle (pInfo) : GetTurningStrafeAngle (pInfo);
660+
661+ float unitDeltaAngle = unitAngle - baseAngle;
662+ return unitDeltaAngle * absOffsetScalar;
663+ }
664+
633665
634666std::shared_ptr<TasToolParams> AutoStrafeTool::ParseParams (std::vector<std::string> vp) {
635667 AutoStrafeType type = VECTORIAL;
@@ -638,7 +670,7 @@ std::shared_ptr<TasToolParams> AutoStrafeTool::ParseParams(std::vector<std::stri
638670 AutoStrafeSpeed speed = {SPECIFIED, maxSpeed};
639671 bool noPitchLock = false ;
640672 bool antiSpeedLock = true ;
641- float turnRate = 1 .0f ;
673+ AutoStrafeSteeringOffset steeringOffset = {DEGREES, 0 .0f } ;
642674 float force = 1 .0f ;
643675
644676 if (vp.size () == 0 ) {
@@ -657,15 +689,30 @@ std::shared_ptr<TasToolParams> AutoStrafeTool::ParseParams(std::vector<std::stri
657689 type = VECTORIAL_CAM;
658690 }
659691
692+ // steering offset
693+ else if (TasParser::hasSuffix (param, " os" )) {
694+ steeringOffset.type = SCALAR;
695+ steeringOffset.value = TasParser::toFloatAssumeSuffix (param, " os" );
696+ } else if (TasParser::hasSuffix (param, " osdeg" )) {
697+ steeringOffset.type = DEGREES;
698+ steeringOffset.value = TasParser::toFloatAssumeSuffix (param, " osdeg" );
699+ } else if (TasParser::hasSuffix (param, " us" )) {
700+ steeringOffset.type = SCALAR;
701+ steeringOffset.value = TasParser::toFloatAssumeSuffix (param, " us" ) * -1 .0f ;
702+ } else if (TasParser::hasSuffix (param, " usdeg" )) {
703+ steeringOffset.type = DEGREES;
704+ steeringOffset.value = TasParser::toFloatAssumeSuffix (param, " usdeg" ) * -1 .0f ;
705+ }
706+
660707 // speed
661708 else if (param == " max" ) {
662709 speed.type = SPECIFIED;
663710 speed.speed = maxSpeed; // as long as it's higher than max speed times square root of 2, we should be fine?
664711 } else if (param == " keep" ) {
665712 speed.type = CURRENT;
666- } else if (param. size () > 3 && param. substr (param. size () - 3 , 3 ) == " ups" ) {
713+ } else if (TasParser::hasSuffix ( param, " ups" ) ) {
667714 speed.type = SPECIFIED;
668- speed.speed = TasParser::toFloat (param. substr ( 0 , param. size () - 3 ) );
715+ speed.speed = TasParser::toFloatAssumeSuffix (param, " ups " );
669716 } else if (param == " min" ) {
670717 speed.type = SPECIFIED;
671718 speed.speed = 0 .0f ;
@@ -684,44 +731,29 @@ std::shared_ptr<TasToolParams> AutoStrafeTool::ParseParams(std::vector<std::stri
684731 } else if (param == " right" ) {
685732 dir.type = SPECIFIED;
686733 dir.angle = -10000 .0f ;
687- } else if (param. size () > 3 && param. substr (param. size () - 3 , 3 ) == " deg" ) {
734+ } else if (TasParser::hasSuffix ( param, " deg" ) ) {
688735 dir.type = SPECIFIED;
689- dir.angle = TasParser::toFloat (param. substr ( 0 , param. size () - 3 ) );
736+ dir.angle = TasParser::toFloatAssumeSuffix (param, " deg " );
690737 }
691738
739+ // flags
692740 else if (param == " nopitchlock" ) {
693741 noPitchLock = true ;
694742 }
695-
696743 else if (param == " letspeedlock" ) {
697744 antiSpeedLock = false ;
698745 }
699746
700- // named value parameters
701- else if (param.find (' =' ) != std::string::npos) {
702- size_t eqPos = param.find (' =' );
703- std::string key = param.substr (0 , eqPos);
704- std::string value = param.substr (eqPos + 1 );
705-
706- if (key == " turnrate" ) {
707- turnRate = TasParser::toFloat (value);
708- } else if (key == " force" ) {
709- force = TasParser::toFloat (value);
710- } else if (key == " velocity" || key == " vel" ) {
711- speed.type = SPECIFIED;
712- speed.speed = TasParser::toFloat (value);
713- } else if (key == " angle" || key == " ang" ) {
714- dir.angle = SPECIFIED;
715- dir.angle = TasParser::toFloat (value);
716- } else {
717- throw TasParserException (Utils::ssprintf (" Unknown named parameter for tool %s: %s" , this ->GetName (), key.c_str ()));
718- }
719- }
720-
721- // unknown parameter...
722- else
747+ // suffix-less number (force)
748+ else try {
749+ force = TasParser::toFloat (param);
750+ }
751+
752+ catch (...) {
753+ // unknown parameter...
723754 throw TasParserException (Utils::ssprintf (" Bad parameter for tool %s: %s" , this ->GetName (), param.c_str ()));
755+ }
724756 }
725757
726- return std::make_shared<AutoStrafeParams>(type, dir, speed, noPitchLock, antiSpeedLock, turnRate , force);
758+ return std::make_shared<AutoStrafeParams>(type, dir, speed, noPitchLock, antiSpeedLock, steeringOffset , force);
727759}
0 commit comments