Jump to content
Sign in to follow this  
The Real Bunc

Solved: Into/out of loop idle animation for combat

Recommended Posts

I'm working on a script that allows a unit to play a looped animation but brea out for combat

and then when combat is over return to the looped animation.

My aim is to have the script able to play say a couple of looped animations

which transition between them but stilll have the unit break into and out of the animations

for combat. But one thing at a time.

I am using a script I saw from Sagarahtyp which showed a way to loop the animation and I have discovered 

how to force the unit to break out of the "AWARE" state after combat by using setBehaviourStrong

to force the units Group back to "SAFE" mode from "AWARE".  ( doinhg this on the unit alone doesnt work).

 

So far so good. This script works.  Unit breaks out of animation for combat and once combat is over reverts quickly back to the looped idle animation.

The problem is that the unit is slow to break out of the looped animation. 

The unit starts in "SAFE" mode (necessary for the animation) and will only break out ( to the ELSE block) once the unit switches to 

"AWARE" or "COMBAT" modes.  But there is a delay in the Unit doing this.

Interestingly if I start a unit (with no script) standing next to the scripted unit

and set that to "SAFE" they break to "COMBAT" mode much quicker. So I suspect the issue is down to script and not a basic engine issue.

 

I thin the solution might be to test the scripted units knowsAbout side state and then force the Unit out of "SAFE" mode

before this first test>    if (toLower (behaviour _this) == "safe")  if the Units knowsAbout state passes a certain threshold

but I would appreciate other eyes and thoughts on this.

 

Easy test of the script >>>> place unit with this script in ini. And one friendly with no script beside him.

Place defeatable enemy units ( less well armed) some distance away with move waypoint

towards scripted unit. Observe unit break into and out of idle animation for combat. Observe unit delay to break into but not break out of combat/aware state.

Observe difference between scripted and non scripted units responses.

 

 

================================================================
this setBehaviour "SAFE";  
0 = this spawn  
  
{  
  
waitUntil {time > 0};  

_this switchMove "c4coming2cDf_genericstani1";  
  
while {alive _this} do  
  
{  
  
if (toLower (behaviour _this) == "safe") then  
  
{  
 waitUntil {animationState _this != "c4coming2cDf_genericstani1"};  
  
_this switchMove "c4coming2cDf_genericstani1";  
  
}  
  
else  
  
{  
  
_this switchMove "";  
  
waitUntil { sleep 1; toLower (behaviour _this) == "AWARE"};  
group _this setbehaviourStrong "SAFE";  
};  

};    
};

Share this post


Link to post
Share on other sites

Study this function, it uses the algorithm you need:

/*
    Author: Jiri Wainar

    Description:
    Play set of ambient animations on given unit AND allows the unit to leave the ambient state and engage enemy or move away.

    Remarks:
    * Function controls BIS_fnc_ambientAnim; check that function [Remarks] section for more info of how to use it.
    * Unit automatically leaves the animation loop if there is an enemy in 300m he knows about.

    Parameter(s):
    0: OBJECT - unit the anim & gear changes are going to be applied to
    1: STRING (optional, default "STAND") - animation set id, describing what the unit's action looks like.
       > "STAND"             - standing still, slightly turning to the sides. Needs a rifle!
       > "STAND_IA"            - default a3 animations for standing, rifle lowered
       > "SIT_LOW"            - sitting on the ground, with weapon.
       > "KNEEL"            - kneeling, with weapon.
       > "LEAN"            - standing while leaning (on wall)
       > "WATCH"/"WATCH1"/"WATCH2"    - standing and turning around

    2: STRING (optional, default "RANDOM") - equipment level id, describing how heavily is the unit equipped.
       > "NONE"          - no goggles, headgear, vest, weapon
       > "LIGHT"          - no goggles, headgear, vest
       > "MEDIUM"         - no goggles, headgear
       > "FULL"          - no goggles
       > "ASIS" (default)    - no touches to the gear
       > "RANDOM"         - gear is randomized according to the animation set

    3: CODE or STRING (optional, default {false}) - condition that if true frees the unit from the animation loop

    4: STRING (optional, default "COMBAT") - behaviour the unit should go to, when freed.

    Returns:
    -

    Example:
    [this,"STAND","FULL",{(player distance _this) < 5}] call BIS_fnc_ambientAnimCombat;
*/

//do the immediate operations ----------------------------------------------------------------------
private["_unit","_animset","_gear","_cond","_behaviour"];
private["_acceptableStates","_acceptableGear","_transAnim"];

_unit           = _this param [0, objNull, [objNull]];
_animset     = _this param [1, "STAND", [""]];
_gear           = _this param [2, "ASIS", [""]];
_cond         = _this param [3, {false}, ["",{}]];
_behaviour     = _this param [4, "COMBAT", [""]];

_acceptableStates =
[
    "STAND",
    "STAND_IA",
    "SIT_LOW",
    "KNEEL",
    "LEAN",
    "WATCH",
    "WATCH1",
    "WATCH2"
];

_acceptableGear =
[
    "NONE",
    "LIGHT",
    "MEDIUM",
    "FULL",
    "ASIS",
    "RANDOM"
];

if !(_animset in _acceptableStates) exitWith
{
    format["Definition of animset '%1' dosn't exist. Possible animsets are %2.",_animset,_acceptableStates] call BIS_fnc_error;
};

if !(_gear in _acceptableGear) exitWith
{
    format["Definition of gearset '%1' dosn't exist. Possible gearsets are %2.",_gear,_acceptableGear] call BIS_fnc_error;
};

if (typeName _cond == typeName "") then
{
    _cond = compile _cond;
};

//execute the ambient anim
[_unit,_animset,_gear,nil,nil,false] call BIS_fnc_ambientAnim;

//transition animation
_transAnim = "AmovPercMstpSrasWrflDnon";

[_unit,_cond,_transAnim,_behaviour] spawn
{
    private["_unit","_cond","_transAnim","_animHandle","_behaviour","_unitPos"];

    _unit         = _this select 0;
    _cond         = _this select 1;
    _transAnim     = _this select 2;
    _behaviour     = _this select 3;

    //wait for system to initialize on the unit
    waitUntil
    {
        sleep 0.1;

        _animHandle = _unit getVariable ["BIS_EhAnimDone", -1];

        (_animHandle > -1)
    };

    //wait for unlock condition evals to true
    waitUntil
    {
        sleep 0.1;

        (behaviour _unit == "COMBAT") || {(damage _unit > 0) || {(_unit call _cond) || {(_unit call BIS_fnc_enemyDetected)}}}
    };

    _unitPos = unitPos _unit;

    //remove the Ai handcuffs
    {_unit enableAI _x} forEach ["ANIM", "AUTOTARGET", "FSM", "MOVE", "TARGET"];
    _unit setBehaviour _behaviour;
    _unit setUnitPos "UP";
    detach _unit;

    //unlock the unit from it's ambient animation
    _unit removeEventHandler ["AnimDone",_animHandle];
    _unit playMoveNow _transAnim;

    sleep ((random 3) + 3);

    //return to the default or previously set unit pos
    _unit setUnitPos _unitPos;
};

 

Share this post


Link to post
Share on other sites

Thanks, that may be helpful. I'm actually using the more detailed loop animations found in the animation viewer rather than the more simplified options available using this function ( ie STAND, SIT etc) but there may be something here that I can use to manage transitions to and from the sorts of animations I'm using. 

Share this post


Link to post
Share on other sites

Actually I think  the clue is the function BIS_FNC_enemydetected. If I put that in as a test immediately after the main loop then I can trigger "AWARE" or "COMBAT" as soon as an enemy is detected and it should then jump to the ELSE  block and stop the animation.  The unit should then stay in combat until there are no enemies and then drop into aware at which point the script restarts the idle animation. Hopefully.

Share this post


Link to post
Share on other sites

Solved it. Using Bis_fnc_enemy detected to flip modes worked. I had to put the test for this at the start of the loop to get it to work.

Script now plays swinging rifle idle loop animation until enemy detected at whcih point unit engages in contact.

When no enemy detected switches back t idel animation. Both switching into and switching out of are now 

reasonably quick. Refinement will be including a transition animation.

=============================================================================

 

this setBehaviour "SAFE";   
   
0 = this spawn   
   
{   
 waitUntil {time > 0};   
 
_this switchMove "c4coming2cDf_genericstani1";   
   
while {alive _this} do   
   
{   
 
if (_this call BIS_fnc_enemyDetected) then {_this setbehaviour "AWARE"}; 
if not(_this call BIS_fnc_enemyDetected) then {_this setbehaviour "SAFE"}; 
detected = _this call BIS_fnc_enemydetected; 
behaviour1= behaviour _this; 
 
if (toLower (behaviour _this) == "safe") then   
   
{   
 waitUntil {animationState _this != "c4coming2cDf_genericstani1"};   
   
_this switchMove "c4coming2cDf_genericstani1";   
   
}   
   
else   
   
{   
 
_this switchMove "";   
waitUntil { sleep 1; toLower (behaviour _this) == "AWARE"};   
group _this setbehaviourStrong "SAFE";   
};   
 
};   
   
};

Share this post


Link to post
Share on other sites

Please sign in to comment

You will be able to leave a comment after signing in



Sign In Now
Sign in to follow this  

×