Complete disaster-recovery snapshot: engine/game source, game data assets, VC6 toolchain + DX SDKs, build outputs, deployed game, and _UNUSED archive. Large binaries in Git LFS; text preserved byte-for-byte (core.autocrlf=false, no eol attributes). See RECOVERY.md for the one-clone rebuild procedure.
553 lines
13 KiB
C++
553 lines
13 KiB
C++
|
|
#include "MW4Headers.hpp"
|
|
|
|
#include "AI_Condition.hpp"
|
|
#include "AI_Weapons.hpp"
|
|
#include "MWPlayer.hpp"
|
|
#include "VehicleInterface.hpp"
|
|
#include "Torso.hpp"
|
|
#include "MWMission.hpp"
|
|
#include "JumpJet.hpp"
|
|
|
|
|
|
|
|
using namespace MW4AI;
|
|
using namespace MW4AI::Conditions;
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
|
|
Fuzzy Conditions::HittingSomethingElse(TacticInterface& i)
|
|
{
|
|
AILOGFUNC("Conditions::HittingSomethingElse");
|
|
|
|
if (i.GetUnableToFireDuration(4.0f) == true)
|
|
{
|
|
LOG_AND_RETURN(1);
|
|
}
|
|
LOG_AND_RETURN(0);
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// AnyWeaponReady
|
|
//
|
|
|
|
Fuzzy Conditions::AnyWeaponReady(TacticInterface& i)
|
|
{
|
|
AILOGFUNC("Conditions::AnyWeaponReady");
|
|
|
|
if (MW4AI::AnyWeaponReady(i.GetSelf()) == true)
|
|
{
|
|
LOG_AND_RETURN(1);
|
|
}
|
|
|
|
LOG_AND_RETURN(0);
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
|
|
Fuzzy Conditions::ProjectileApproaching(TacticInterface& i, Stuff::Scalar min_distance)
|
|
{
|
|
AILOGFUNC("Conditions::ProjectileApproaching");
|
|
AILOG1(min_distance);
|
|
|
|
if (i.ProjectileApproaching() == true)
|
|
{
|
|
Stuff::Point3D delta;
|
|
delta.Subtract(i.GetProjectileOrigin(),(Stuff::Point3D)i.GetSelf().GetLocalToWorld());
|
|
if (delta.GetLengthSquared() < min_distance * min_distance)
|
|
{
|
|
LOG_AND_RETURN(0);
|
|
}
|
|
|
|
LOG_AND_RETURN(1);
|
|
}
|
|
|
|
LOG_AND_RETURN(0);
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
|
|
Fuzzy Conditions::Fired(TacticInterface& i, Stuff::Scalar within_when)
|
|
{
|
|
AILOGFUNC("Conditions::Fired");
|
|
AILOG1(within_when);
|
|
|
|
if (i.FiredWithin(within_when) == true)
|
|
{
|
|
LOG_AND_RETURN(1);
|
|
}
|
|
|
|
LOG_AND_RETURN(0);
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
|
|
Fuzzy Conditions::TargetedByEnemy(TacticInterface& i, Stuff::Scalar duration)
|
|
{
|
|
AILOGFUNC("Conditions::TargetedByEnemy");
|
|
AILOG1(duration);
|
|
|
|
if (i.GetTimeTargetedByEnemy() >= duration)
|
|
{
|
|
LOG_AND_RETURN(1);
|
|
}
|
|
|
|
LOG_AND_RETURN(0);
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
|
|
Fuzzy Conditions::Rammed(TacticInterface& i, Stuff::Scalar duration)
|
|
{
|
|
AILOGFUNC("Conditions::Rammed");
|
|
AILOG1(duration);
|
|
|
|
if (i.GetLastTimeRammedTarget() + duration > gos_GetElapsedTime())
|
|
{
|
|
LOG_AND_RETURN(1);
|
|
}
|
|
|
|
LOG_AND_RETURN(0);
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
|
|
Fuzzy Conditions::InsideRadiusOfTarget(TacticInterface& i, Stuff::Scalar radius)
|
|
{
|
|
AILOGFUNC("Conditions::InsideRadiusOfTarget");
|
|
AILOG1(radius);
|
|
|
|
if (i.GetDistanceFromTargetSquared() <= radius * radius)
|
|
{
|
|
LOG_AND_RETURN(1);
|
|
}
|
|
|
|
LOG_AND_RETURN(0);
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
Fuzzy Conditions::InsideRadiusOfTarget(TacticInterface&i, Stuff::Scalar radius, Stuff::Scalar when)
|
|
{
|
|
AILOGFUNC("Conditions::InsideRadiusOfTarget");
|
|
AILOG2(radius,when);
|
|
|
|
Stuff::Point3D my_pos(i.GetSelf().GetLocalToWorld());
|
|
Stuff::Point3D target_pos;
|
|
i.GetTarget().EstimateFuturePosition(&target_pos,(Scalar)when,true);
|
|
my_pos.y = 0;
|
|
target_pos.y = 0;
|
|
|
|
if (GetLengthSquared(my_pos,target_pos) <= radius * radius)
|
|
{
|
|
LOG_AND_RETURN(1);
|
|
}
|
|
|
|
LOG_AND_RETURN(0);
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
Fuzzy Conditions::InsideRadiusOfRamTarget(TacticInterface& i, Stuff::Scalar radius)
|
|
{
|
|
AILOGFUNC("Conditions::InsideRadiusOfRamTarget");
|
|
AILOG(radius);
|
|
|
|
Verify(i.GetSelf_AsVehicle() != 0);
|
|
|
|
Stuff::Scalar time_to_reach = GetApproximateLength((Stuff::Point3D)i.GetSelf().GetLocalToWorld(),
|
|
(Stuff::Point3D)i.GetTarget().GetLocalToWorld()) / i.GetSelf_AsVehicle()->GetGameModel()->maxSpeed;
|
|
|
|
Stuff::Point3D target_pos;
|
|
i.GetTarget().EstimateFuturePosition(&target_pos,time_to_reach,false);
|
|
|
|
Stuff::Point3D my_pos((Stuff::Point3D)i.GetSelf().GetLocalToWorld());
|
|
my_pos.y = 0;
|
|
target_pos.y = 0;
|
|
|
|
if (GetLengthSquared(my_pos,target_pos) <= radius * radius)
|
|
{
|
|
LOG_AND_RETURN(1);
|
|
}
|
|
|
|
LOG_AND_RETURN(0);
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
|
|
Fuzzy MW4AI::Conditions::InsideWeaponsRadiusOfTarget(TacticInterface& i,
|
|
TacticInterface::WR_WHO who,
|
|
TacticInterface::WR_QUALIFIER type,
|
|
Stuff::Scalar multiplier)
|
|
{
|
|
AILOGFUNC("Conditions::InsideWeaponsRadiusOfTarget");
|
|
AILOG3(who,type,multiplier);
|
|
|
|
Stuff::Scalar radius = i.WeaponRange(who,type) * multiplier;
|
|
|
|
if (i.GetDistanceFromTargetSquared() <= radius * radius)
|
|
{
|
|
LOG_AND_RETURN(1);
|
|
}
|
|
|
|
LOG_AND_RETURN(0);
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
|
|
Fuzzy MW4AI::Conditions::InsidePercentileRangeOf(TacticInterface& i, Stuff::Scalar percentile_range, bool nearest_enemy)
|
|
{
|
|
AILOGFUNC("Conditions::InsidePercentileRangeOfTarget");
|
|
AILOG2(percentile_range,nearest_enemy);
|
|
|
|
Stuff::Scalar radius = i.GetCombatRadiusForRange(percentile_range);
|
|
|
|
if (nearest_enemy == true)
|
|
{
|
|
Adept::Entity* nearest = i.GetNearest(true);
|
|
|
|
if (nearest == 0)
|
|
{
|
|
nearest = &i.GetTarget();
|
|
}
|
|
|
|
if (GetLengthSquared((Stuff::Point3D)i.GetSelf().GetLocalToWorld(),
|
|
(Stuff::Point3D)nearest->GetLocalToWorld()) <= radius * radius)
|
|
{
|
|
LOG_AND_RETURN(1);
|
|
}
|
|
|
|
LOG_AND_RETURN(0);
|
|
}
|
|
|
|
if (i.GetDistanceFromTargetSquared() <= radius * radius)
|
|
{
|
|
LOG_AND_RETURN(1);
|
|
}
|
|
|
|
LOG_AND_RETURN(0);
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
|
|
Fuzzy Conditions::VehicleMoving(TacticInterface& i)
|
|
{
|
|
AILOGFUNC("Conditions::VehicleMoving");
|
|
|
|
if (i.Moving() == true)
|
|
{
|
|
LOG_AND_RETURN(1);
|
|
}
|
|
|
|
LOG_AND_RETURN(0);
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// VehicleCrouching
|
|
//
|
|
|
|
Fuzzy Conditions::VehicleCrouching(TacticInterface& i)
|
|
{
|
|
AILOGFUNC("Conditions::VehicleCrouching");
|
|
|
|
if (i.Crouching() == true)
|
|
{
|
|
LOG_AND_RETURN(1);
|
|
}
|
|
|
|
LOG_AND_RETURN(0);
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
|
|
Fuzzy Conditions::FacingTarget(TacticInterface& i)
|
|
{
|
|
AILOGFUNC("Conditions::FacingTarget");
|
|
|
|
const Stuff::LinearMatrix4D& my_matrix = i.GetSelf().GetLocalToWorld();
|
|
Stuff::Point3D target_pos(i.GetTarget().GetLocalToWorld());
|
|
|
|
Stuff::UnitVector3D my_forward;
|
|
my_matrix.GetLocalForwardInWorld(&my_forward);
|
|
Stuff::Point3D forward(my_forward);
|
|
forward += (Stuff::Point3D)my_matrix;
|
|
|
|
Stuff::UnitVector3D my_backward;
|
|
my_matrix.GetLocalBackwardInWorld(&my_backward);
|
|
Stuff::Point3D backward(my_backward);
|
|
backward += (Stuff::Point3D)my_matrix;
|
|
|
|
if (GetLengthSquared(forward,target_pos) < GetLengthSquared(backward,target_pos))
|
|
{
|
|
LOG_AND_RETURN(1);
|
|
}
|
|
|
|
LOG_AND_RETURN(0);
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
|
|
Fuzzy Conditions::InFrontOfTarget(TacticInterface& i, bool fUseTorso)
|
|
{
|
|
AILOGFUNC("Conditions::InFrontOfTarget");
|
|
AILOG1(fUseTorso);
|
|
|
|
LinearMatrix4D relative_to;
|
|
|
|
if ((fUseTorso == true) &&
|
|
(i.GetTarget().GetTorso() != 0) &&
|
|
(i.GetTarget().GetTorso()->twistJoint != 0))
|
|
{
|
|
Check_Object(i.GetTarget().GetTorso());
|
|
relative_to = i.GetTarget().GetTorso()->twistJoint->GetLocalToWorld();
|
|
}
|
|
else
|
|
{
|
|
relative_to = i.GetTarget().GetLocalToWorld();
|
|
}
|
|
|
|
Stuff::Point3D delta;
|
|
delta.Subtract((Stuff::Point3D)i.GetSelf().GetLocalToWorld(),(Stuff::Point3D)relative_to);
|
|
|
|
Stuff::UnitVector3D delta_normalized(delta);
|
|
|
|
Stuff::UnitVector3D local_forward;
|
|
relative_to.GetLocalForwardInWorld(&local_forward);
|
|
|
|
Stuff::Scalar bearing = delta_normalized * local_forward;
|
|
bearing += 1;
|
|
bearing *= 0.5f;
|
|
|
|
if (bearing >= 0.5f)
|
|
{
|
|
LOG_AND_RETURN(1);
|
|
}
|
|
|
|
LOG_AND_RETURN(0); // TODO: bearing is already a fuzzy; should return it as a Fuzzy!
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
Fuzzy Conditions::JumpedWithin(TacticInterface& i, Stuff::Scalar duration)
|
|
{
|
|
AILOGFUNC("Conditions::JumpedWithin");
|
|
AILOG1(duration);
|
|
|
|
if (i.GetLastTimeJumped() + duration >= gos_GetElapsedTime())
|
|
{
|
|
LOG_AND_RETURN(1);
|
|
}
|
|
|
|
LOG_AND_RETURN(0);
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
bool Conditions::Jumping(TacticInterface& i)
|
|
{
|
|
AILOGFUNC("Conditions::Jumping");
|
|
|
|
if (i.GetSelf().IsDerivedFrom(Mech::DefaultData) == true)
|
|
{
|
|
Mech* mech = Cast_Object(Mech*,&(i.GetSelf()));
|
|
|
|
if ((mech->GetJumpJet() != 0) &&
|
|
(mech->GetJumpJet()->executionState->GetState() == JumpJet::ExecutionStateEngine::JumpingState))
|
|
{
|
|
LOG_AND_RETURN(true);
|
|
}
|
|
}
|
|
|
|
LOG_AND_RETURN(false);
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
Fuzzy Conditions::CanBeSeenByTarget(TacticInterface& i, Stuff::Scalar within_distance)
|
|
{
|
|
AILOGFUNC("Conditions::CanBeSeenByTarget");
|
|
|
|
const Stuff::Scalar distance = GetApproximateLength((Stuff::Point3D)i.GetSelf().GetLocalToWorld(),
|
|
(Stuff::Point3D)i.GetTarget().GetLocalToWorld());
|
|
|
|
if (distance > within_distance)
|
|
{
|
|
LOG_AND_RETURN(0);
|
|
}
|
|
|
|
if ((MWMission::GetInstance() != 0) &&
|
|
(MWMission::GetInstance()->GetGameModel() != 0))
|
|
{
|
|
const Adept::Mission::GameModel* game_model = MWMission::GetInstance()->GetGameModel();
|
|
|
|
if (distance > game_model->m_generalFogEnd)
|
|
{
|
|
LOG_AND_RETURN(0);
|
|
}
|
|
}
|
|
|
|
FireData fire_data(i.GetSelf(),
|
|
i.GetSelf().GetLineOfSight(),
|
|
i.GetTarget().GetLineOfSight());
|
|
fire_data.Project();
|
|
|
|
if (fire_data.GetHitResult(&i.GetTarget()) == FireData::HIT_TARGET)
|
|
{
|
|
LOG_AND_RETURN(1);
|
|
}
|
|
|
|
LOG_AND_RETURN(0);
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
Fuzzy Conditions::IsHighOffGround(TacticInterface& i)
|
|
{
|
|
AILOGFUNC("Conditions::IsHighOffGround");
|
|
|
|
const Stuff::Point3D my_pos(i.GetSelf().GetLocalToWorld());
|
|
|
|
BYTE tempmaterial;
|
|
if (my_pos.y - 10 > GetMapY(my_pos.x,my_pos.z,&i.GetSelf(),tempmaterial))
|
|
{
|
|
LOG_AND_RETURN(1);
|
|
}
|
|
|
|
LOG_AND_RETURN(0);
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
|
|
Fuzzy Conditions::PlayerWillHitMe(TacticInterface& i,
|
|
Stuff::Scalar seconds,
|
|
Stuff::Scalar threshold)
|
|
{
|
|
AILOGFUNC("Conditions::PlayerWillHitMe");
|
|
AILOG2(seconds,threshold);
|
|
|
|
if ((Adept::Player::GetInstance() == 0) ||
|
|
(i.GetSelf_AsVehicle() == 0))
|
|
{
|
|
LOG_AND_RETURN(0);
|
|
}
|
|
|
|
MechWarrior4::MWPlayer* player = Cast_Object(MechWarrior4::MWPlayer*,Adept::Player::GetInstance());
|
|
Check_Object(player);
|
|
if (player->GetInterface() == 0)
|
|
{
|
|
LOG_AND_RETURN(0);
|
|
}
|
|
|
|
Adept::Entity* player_entity = player->GetInterface()->vehicle;
|
|
if ((player_entity == 0) ||
|
|
(player_entity->GetAlignment() == i.GetSelf().GetAlignment()) ||
|
|
(player_entity->IsDerivedFrom(MechWarrior4::Vehicle::DefaultData) == false))
|
|
{
|
|
LOG_AND_RETURN(0);
|
|
}
|
|
|
|
threshold *= threshold;
|
|
|
|
MechWarrior4::Vehicle* player_vehicle = Cast_Object(MechWarrior4::Vehicle*,player_entity);
|
|
if (GetLengthSquared((Stuff::Point3D)player_vehicle->GetLocalToWorld(),
|
|
(Stuff::Point3D)i.GetSelf().GetLocalToWorld()) < threshold)
|
|
{
|
|
LOG_AND_RETURN(1);
|
|
}
|
|
|
|
Stuff::Point3D next_player_pos;
|
|
player_vehicle->EstimateFuturePosition(&next_player_pos, (Scalar)seconds);
|
|
Stuff::Point3D next_self_pos;
|
|
i.GetSelf_AsVehicle()->EstimateFuturePosition(&next_self_pos, (Scalar)seconds);
|
|
if (GetLengthSquared(next_self_pos,
|
|
next_player_pos) < threshold)
|
|
{
|
|
LOG_AND_RETURN(1);
|
|
}
|
|
|
|
LOG_AND_RETURN(0);
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
|
|
Fuzzy Conditions::ClusterFuckingSomeone(TacticInterface& i,
|
|
Stuff::Scalar radius)
|
|
{
|
|
AILOGFUNC("Conditions::ClusterFuckingSomeone");
|
|
AILOG1(radius);
|
|
|
|
if (i.GetLastTimeRammedTarget() + 1.0f > gos_GetElapsedTime())
|
|
{
|
|
LOG_AND_RETURN(1);
|
|
}
|
|
|
|
Adept::Entity* entity = i.GetNearest();
|
|
|
|
if (entity != 0)
|
|
{
|
|
if (i.GetSelf().IsDerivedFrom(Mech::DefaultData) == false)
|
|
{
|
|
radius *= 0.8f; // this is to ensure that vehicles smaller than mechs have smaller dodge radii
|
|
}
|
|
|
|
if (GetLengthSquared((Stuff::Point3D)i.GetSelf().GetLocalToWorld(),
|
|
(Stuff::Point3D)entity->GetLocalToWorld()) < radius * radius)
|
|
{
|
|
LOG_AND_RETURN(1);
|
|
}
|
|
}
|
|
|
|
LOG_AND_RETURN(0);
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
|
|
Fuzzy Conditions::EliteLevelBetween(TacticInterface& i, UserConstants::ID min, UserConstants::ID max)
|
|
{
|
|
AILOGFUNC("Conditions::EliteLevelBetween");
|
|
AILOG2(min,max);
|
|
|
|
int int_min = (int)UserConstants::Instance()->Get(min);
|
|
int int_max = (int)UserConstants::Instance()->Get(max);
|
|
|
|
Verify(int_min <= int_max);
|
|
Verify(int_min >= 0);
|
|
Verify(int_max <= 100);
|
|
|
|
LOG_AND_RETURN((i.GetEliteLevel() >= int_min) && (i.GetEliteLevel() <= int_max));
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
|
|
Fuzzy Conditions::AttackThrottleBetween(TacticInterface& i, Stuff::Scalar min, Stuff::Scalar max)
|
|
{
|
|
AILOGFUNC("Conditions::AttackThrottleBetween");
|
|
AILOG2(min,max);
|
|
|
|
Verify(min >= 0);
|
|
Verify(max <= 100);
|
|
|
|
if ((i.GetAttackThrottle() >= min) &&
|
|
(i.GetAttackThrottle() <= max))
|
|
{
|
|
LOG_AND_RETURN(1);
|
|
}
|
|
|
|
LOG_AND_RETURN(0);
|
|
}
|