int BrigadeClass::UpdateParentStatistics (void)
	{
	GridIndex	nx,ny,x,y;
	int			engaged=0,combat=0,loss=0,te=0;
	Unit		e;

	// Update unit wide statistics. NOTE: some delay here- since elements are unmoved.
	nx = ny = te = 0;
	e = GetFirstUnitElement();
	while (e)
		{
		if (e->Engaged())
			engaged = 1;
		if (e->Combat())
			combat = 1;
		if (e->Losses())
			loss = 1;
		e->GetLocation(&x,&y);
//		nx += x;
//		ny += y;
		if (!nx && !ny)
			e->GetLocation(&nx,&ny);
		te++;
		e = GetNextUnitElement();
		}
	if (!te)
		{
		KillUnit();
		return 0;
		}
	if (!engaged)
		{
		SetEngaged(0);
		SetTarget(NULL);
		}
	SetEngaged(engaged);
	SetCombat(combat);
	SetLosses(loss);
	// Set our new averaged position
//	x = nx / te;
//	y = ny / te;
//	SetLocation(x,y);
	ShiAssert (nx && ny);
	// Set our position to our first element
	SetLocation(nx,ny);
	return te;
	}
int TaskForceClass::ChooseTarget (void)
{
    FalconEntity	*artTarget,*react_against=NULL,*air_react_against=NULL;
    CampEntity		e;
    float		d,react_distance,air_react_distance;
    int			react,best_reaction=1,best_air_react=1,combat,retval=0,pass=0,spot=0,estr=0,capture=0,nomove=0;
    int			search_dist;
    Team		who;

    if (IsChecked())
        return Engaged();

    who = GetTeam();
    react_distance = air_react_distance = 9999.0F;

#ifdef DEBUG
    DWORD				timec = GetTickCount();
#endif

    // Special case for fire support
    if (Targeted())
        artTarget = GetTarget();					// Save our target
    else
        artTarget = NULL;

    SetEngaged(0);
    SetCombat(0);
    SetChecked();

    search_dist = GetDetectionRange(Air);
    if (search_dist < MAX_GROUND_SEARCH)
        search_dist = MAX_GROUND_SEARCH;
#ifdef VU_GRID_TREE_Y_MAJOR
    VuGridIterator detit(RealUnitProxList,YPos(),XPos(),(BIG_SCALAR)GridToSim(search_dist));
#else
    VuGridIterator detit(RealUnitProxList,XPos(),YPos(),(BIG_SCALAR)GridToSim(search_dist));
#endif
    //  CalculateSOJ(detit); 2002-02-19 REMOVED BY S.G. eFalcon 1.10 SOJ code removed

    e = (CampEntity)detit.GetFirst();
    while (e)
    {
        if (GetRoE(who,e->GetTeam(),ROE_GROUND_FIRE) == ROE_ALLOWED)
        {
            combat = 0;
            react = DetectVs(e,&d,&combat,&spot);
            if (!e->IsFlight() && react >= best_reaction && d < react_distance)
            {
                // React vs a ground/Naval target
                best_reaction = react;
                react_distance = d;
                react_against = e;
                SetEngaged(1);
                SetCombat(combat);
            }
            else if (e->IsFlight() && react >= best_air_react && d < air_react_distance)
            {
                // React vs an air target -
                best_air_react = react;
                air_react_distance = d;
                air_react_against = e;
                if (!e->IsAggregate())
                {
                    // Pick a specific aircraft in the flight if it's deaggregated
                    CampEnterCriticalSection();
                    if (e->GetComponents())
                    {
                        VuListIterator	cit(e->GetComponents());
                        FalconEntity	*fe;
                        float			rsq,brsq=FLT_MAX;

                        fe = (FalconEntity *)cit.GetFirst();
                        while (fe)
                        {
                            rsq = DistSqu(XPos(),YPos(),fe->XPos(),fe->YPos());
                            if (rsq < brsq)
                            {
                                air_react_against = fe;
                                air_react_distance = (float)sqrt(rsq);
                                brsq = rsq;
                            }
                            fe = (FalconEntity *)cit.GetNext();
                        }
                    }
                    CampLeaveCriticalSection();
                }
                // Make sure our radar is on (if we have one)
                if (!IsEmitting() && class_data->RadarVehicle < 255 && GetNumVehicles(class_data->RadarVehicle))
                    SetEmitting(1);
                SetEngaged(1);
                SetCombat(combat);
            }
        }
        e = (CampEntity)detit.GetNext();
    }
    SetOdds ((GetTotalVehicles() * 10) / (estr+10));

    if (!Parent() && best_reaction > 1)
        EngageParent(this,react_against);

    if (air_react_against)
    {
        SetAirTarget(air_react_against);
        retval = 1;
    }
    if (react_against)
    {
        SetTarget(react_against);
        SetTargeted(0);
        retval = 1;
    }
    else if (artTarget && (!artTarget->IsUnit() || ((Unit)artTarget)->Engaged()) && orders == GORD_SUPPORT)
    {
        // Keep blowing away this target until the target gets out of range, disengages, or we get new orders
        // (Target will get reset after a null DoCombat result)
        SetTarget(artTarget);
        SetTargeted(1);
        SetEngaged(1);
        SetCombat(1);
        return -1;			// We want to sit here and shoot until we can't any longer
    }
    if (nomove)
        return -1;
    return retval;
}
int TaskForceClass::DoCombat (void)
{
    int combat;
    SetCombatTime(TheCampaign.CurrentTime);

#if 0 // JPO mthis stuff now done in Choose Target - like Battalion
    // KCK: Super simple targetting (c)
    Team				who = GetTeam();
    CampEntity			e;
    FalconEntity		*react_against=NULL,*air_react_against=NULL;
    int					react,spot,best_reaction=1,best_air_react=1;
    int					search_dist;
    float				react_distance,air_react_distance,d;
    react_distance = air_react_distance = 9999.0F;

    SetEngaged(0);
    SetCombat(0);
    SetChecked();

    search_dist = GetDetectionRange(Air);
#ifdef VU_GRID_TREE_Y_MAJOR
    VuGridIterator detit(RealUnitProxList,YPos(),XPos(),(BIG_SCALAR)GridToSim(search_dist));
#else
    VuGridIterator detit(RealUnitProxList,XPos(),YPos(),(BIG_SCALAR)GridToSim(search_dist));
#endif
    e = (CampEntity)detit.GetFirst();
    while (e)
    {
        if (GetRoE(who,e->GetTeam(),ROE_GROUND_FIRE) == ROE_ALLOWED)
        {
            combat = 0;
            react = DetectVs(e,&d,&combat,&spot);
            if (!e->IsFlight() && react >= best_reaction && d < react_distance)
            {
                // React vs a ground/Naval target
                best_reaction = react;
                react_distance = d;
                react_against = e;
                SetEngaged(1);
                SetCombat(combat);
            }
            else if (e->IsFlight() && react >= best_air_react && d < air_react_distance)
            {
                // React vs an air target -
                best_air_react = react;
                air_react_distance = d;
                air_react_against = e;
                if (!e->IsAggregate())
                {
                    // Pick a specific aircraft in the flight if it's deaggregated
                    CampEnterCriticalSection();
                    if (e->GetComponents())
                    {
                        VuListIterator	cit(e->GetComponents());
                        FalconEntity	*fe;
                        float			rsq,brsq=FLT_MAX;

                        fe = (FalconEntity *)cit.GetFirst();
                        while (fe)
                        {
                            rsq = DistSqu(XPos(),YPos(),fe->XPos(),fe->YPos());
                            if (rsq < brsq)
                            {
                                air_react_against = fe;
                                air_react_distance = (float)sqrt(rsq);
                                brsq = rsq;
                            }
                            fe = (FalconEntity *)cit.GetNext();
                        }
                    }
                    CampLeaveCriticalSection();
                }
                SetEngaged(1);
                SetCombat(combat);
            }
        }
        e = (CampEntity)detit.GetNext();
    }

    if (air_react_against)
        SetAirTarget(air_react_against);
    if (react_against)
        SetTarget(react_against);
#endif
    if (Engaged())
    {
        FalconEntity	*e = GetTarget();
        FalconEntity	*a = GetAirTarget();

        // Check vs our Ground Target
        if (!e)
            SetTarget(NULL);
        else
        {
            if (Combat() && IsAggregate())
            {
                combat = ::DoCombat(this,e);
                if (combat <= 0 || Targeted())
                    SetTargeted(0);
            }
        }
        // Check vs our Air Target
        if (!a)
            SetAirTarget(NULL);
        else if (Combat() && IsAggregate())
        {
            combat = ::DoCombat(this,a);
            if (combat < 0)
                SetAirTarget(NULL);							// Clear targeting data so we can look for another
        }
    }

    return 0;
}
void CombatManager::AttackSomeone(gemActor *attacker,gemObject *target,Stance stance)
{
    psCharacter *attacker_character = attacker->GetCharacterData();

    //we don't allow an overweight or defeated char to fight
    if (attacker->GetMode() == PSCHARACTER_MODE_DEFEATED || 
        attacker->GetMode() == PSCHARACTER_MODE_OVERWEIGHT)
        return;

    if (attacker->GetMode() == PSCHARACTER_MODE_COMBAT)  // Already fighting
    {
        SetCombat(attacker,stance);  // switch stance from Bloody to Defensive, etc.
        return;
    }
    else
    {
        if (attacker->GetMode() == PSCHARACTER_MODE_SIT) //we are sitting force the char to stand
            attacker->Stand();
        attacker_character->ResetSwings(csGetTicks());
    }

    // Indicator of whether any weapons are available to attack with
    bool startedAttacking=false;
    bool haveWeapon=false;

    // Step through each current slot and queue events for all that can attack
    for (int slot=0; slot<PSCHARACTER_SLOT_BULK1; slot++)
    {
        // See if this slot is able to attack
        if (attacker_character->Inventory().CanItemAttack((INVENTORY_SLOT_NUMBER) slot))
        {
            INVENTORY_SLOT_NUMBER weaponSlot = (INVENTORY_SLOT_NUMBER) slot;
            // Get the data for the "weapon" that is used in this slot
            psItem *weapon=attacker_character->Inventory().GetEffectiveWeaponInSlot(weaponSlot);

            csString response;
            if (weapon!=NULL && weapon->CheckRequirements(attacker_character,response) )
            {
                haveWeapon = true;
                Debug5(LOG_COMBAT,attacker->GetClientID(),"%s tries to attack with %s weapon %s at %.2f range",
                       attacker->GetName(),(weapon->GetIsRangeWeapon()?"range":"melee"),weapon->GetName(),
                       attacker->RangeTo(target,false));
                Debug3(LOG_COMBAT,attacker->GetClientID(),"%s started attacking with %s",attacker->GetName(),
                       weapon->GetName());
                
                // start the ball rolling
                QueueNextEvent(attacker,weaponSlot,target,attacker->GetClientID(),target->GetClientID());  
                
                startedAttacking=true;
            }
            else
            {
                if( weapon  && attacker_character->GetActor())
                {
                    Debug3(LOG_COMBAT,attacker->GetClientID(),"%s tried attacking with %s but can't use it.",
                           attacker->GetName(),weapon->GetName());
#ifdef COMBAT_DEBUG
                    psserver->SendSystemError(attacker_character->GetActor()->GetClientID(), response);
#endif
                } 
            }
        }
    }

    /* Only notify the target if any attacks were able to start.  Otherwise there are
     * no available weapons with which to attack.
     */
    if (haveWeapon)
    {
        if (startedAttacking)
        {
            // The attacker should now enter combat mode
            if (attacker->GetMode() != PSCHARACTER_MODE_COMBAT)
            {
                SetCombat(attacker,stance);
            }
        }
        else
        {
            psserver->SendSystemError(attacker->GetClientID(),"You are too far away to attack!");
            return;
        }
    }
    else
    {
        psserver->SendSystemError(attacker->GetClientID(),"You have no weapons equipped!");
        return;
    }
}