XIDPawn
Class IAController

source: C:\XIII\XIDPawn\Classes\IAController.uc
Core.Object
   |
   +--Engine.Actor
      |
      +--Engine.Controller
         |
         +--Engine.AIController
            |
            +--XIDPawn.IAController
Direct Known Subclasses:FBi_Helico01_Controller

class IAController
extends Engine.AIController

//============================================================================= // IAController. //=============================================================================
Variables
 float Angle_Visee
           vitesse de deplacements en strafe
 enum AttitudeInfo
 BaseSoldier BaseS
           =attaque= pote qui me bloque le chemin
 bool CHARGE_LES_LOGS
           Pour voir mes logs
 BaseSoldier CadavreWithPickup
           pour aller chercher pickups sur cadavre
 int CompteurRecalage
           utilise dans charge,attaque et TM pour savoir si se recale
 int CompteurTrame
           optimisation du Tick
 float DefaultHearingThreshold
           distance de tdetection des murs
 float DefaultPeripheralVision
           distance de tdetection des murs
 float DefaultSightRadius
           distance de tdetection des murs
 NavigationPoint DestNavPoint
           =patrouille= point de destination
 vector DirectionTir
           direction du tir
 float DistNearWall
           distance de tdetection des murs
 float DistanceDeplacement
           distance de test de deplacement dans errance et fuite
 NavigationPoint DoorP
           =ouvreporte= pour verifier qu'il y a des doorpoints
 vector EnemyTargetPos
           derniere position connue de l'enemy
 vector EnemyTargetVelocity
           derniere position connue de l'enemy
 name EtatNeutre
           etat neutre (tenir, patrouille ou tenir)
 float FireTimerRefresh
           temps de refresh du tir en auto
 GrenadFlying Grenade
           une grenade est lancee
 vector HidingSpot
           =tacticalmove=
 Actor Interrogation
           effet interrogation ou exclamation
 AttackPoint LastAttackPoint
           Point d'attaque courant
 XIIIPorte LastBumpedDoor
           last bumped door to avoid to be blocked
 PatrolPoint LastPatrolPoint
           =patrouille= dernier patrolpoint utilise
 StrategicPoint LastStrP
           =chasse= Dernier Safe Point
 Actor MoveActor
 Actor MoveActor
 vector MovePoint
 vector MovePoint
 int NbCoupsRiposte
           utilise dans timer pour savoir combien de coups ne sont pas bloques
 int NbPointChemin
           nb de point dans pathfinding
 int NextRouteCachePoint
           =attaqueScriptee= pour reprendre vers point suivant apres ouverture de porte
 int NiveauALerte
           niveau d'alerte
 int NiveauALerteEnAS
           niveau d'alerte
 int NombreDePointsSkippes
           =attaqueScriptee= pour calcul du prochain AP
 int NumeroProchainPoint
           =attaqueScriptee= choix entre differents AP
 AttackPoint OldAttackPoint
           Dernier Point d'attaque
 SafePoint OldSafePoint
           =chasse= Dernier Safe Point
 name PatrolAnim
           type d'anim de patrouille
 Pawn PeeredEnemy
           =investigation=
 Actor PointChemin[16]
           points intermediaire du pathfinding
 vector PointDestination
           =attaque= pour calculer destination
 NavigationPoint PointIntermediaire
           =attaque= point intermediaire de deplacement
 vector PointTenirPos
           =tenir= position de point de retour en tenir
 rotator PointTenirRot
           =tenir= direction point de retour en tenir
 Actor PointsInvestigation[3]
           =investigation=
 XIIIPorte PorteOuverte
           porte a ouvrir
 BaseSoldier Pote
           ben c'est un pote qu'il faut eviter de toucher. MAJ dans fonction native LineOfFireObstacle()
 XIIIPawn PoteQuiMeBloque
           =attaque= pote qui me bloque le chemin
 vector PoteQuiMeBloquePos
           =attaque= pos du pote qui me bloque la porte
 SafePoint SafePointOccupe
           =chasse= Dernier Safe Point
 vector Temp_Vect
           point de depart de la balle de l'arme mise a jour dans le moteur
 float Temp_float
           utilise partout
 float TempsDeclencheAlarme
           delai avant qu'il declenche l'alarme
 float Temps_Ref2
           timer
 float Temps_RefreshEnemyPos
           distance de tdetection des murs
 float Temps_errance
           temps d'errance entre patrouille et errance
 float Temps_ref
           timer
 float Timer_VaRecharger
           vitesse de deplacements en strafe
 name TurnLPatrolAnim
           type d'anim de demi-tour en patrouille vers gauche
 name TurnRPatrolAnim
           type d'anim de demi-tour en patrouille vers droite
 vector VecteurRecalage
           =attaque=
 float VitesseDeplacements
           vitesse de deplacements en strafe
 float VitesseHorizontaleSaut
           =attaqueScriptee= utilise pour saut
 name WaitPatrolAnim
           type d'anim d'attente en patrouille
 Weapon WeaponOnGround
           arme recuperee sur cadavre
 vector WeaponStartTrace
           point de depart de la balle de l'arme mise a jour dans le moteur
 XIIIPlayerPawn XIII
           =investigation=
 bool bARienVu
           je suis passe en point d'interro
 bool bAVuQuelquechose
           =acquisition= pour sortie interro et exclamation
 bool bAccroupiSurAP
           =attaqueScriptee= util. pour tir en rafale
 bool bAlarmeInstigator
           vrai pawn si declencheur de l'alarme
 bool bBloqueFuiteGrenades
           vrai pawn si declencheur de l'alarme
 bool bCadavreVu
           pour faire une retraite
 bool bCampeVersSafePoint
           pour faire une retraite
 bool bChercheStrategicPoint
           Pour voir mes logs
 bool bDejaVu
           pour faire une retraite
 bool bDeplacementsRoulade
           =attaqueScriptee=
 bool bDisableDamageattitudeto
           =attaque= etat = 0 inactif, etat=1 va a un point intermediaire,etat=2 va a un StrP et etat=3 reste sur un STrP
 bool bDontSeeAnyMore
           =attaqueScriptee= pour desactivation musique attaque
 bool bEnCouverture
           =attaque=
 bool bEtatAlerte
           en etat d'alerte donc attaque direct
 bool bFuitPourreloader
           =attaque=
 bool bImpactNoise
           pour faire une retraite
 bool bInWaitMode
           en attaque H2H pour savoir que je suis en train d'attendre
 bool bInterruptStateToOpenDoor
           en attaque H2H pour savoir que je suis en train d'attendre
 bool bLanceGrenade
           =attaque=
 bool bLookAtEnemy
           regarde si voit enemy pour recommencer a lui tirer dessus
 bool bPaffe
           pour faire une retraite
 bool bPotePaffe
           pour faire une retraite
 bool bPrecedentTirBloque
           utilise dans timer vers timer pour savoir si le precedent tir a ete bloque lors de prise d'otage
 bool bPremiereRafale
           vrai pawn si declencheur de l'alarme
 bool bPrisonnier
           utilise dans timer vers timer pour savoir si pote otage
 bool bReachable
 bool bRetraiteVersSafePoint
           pour faire une retraite
 bool bSaut
           =attaqueScriptee= je suis en train de sauter
 bool bStepNoise
           pour faire une retraite
 bool bSwitchMusicInWaitState
           //=attaqueScriptee= a fixe l'etat de musique en attente apres delai de pas vu.
 bool bTemp_Bool
           =attaqueScriptee= pour desactivation musique attaque
 bool bTirSurConeMax
           vrai pawn si declencheur de l'alarme
 bool bTire
           Pour voir mes logs
 bool bTraceable
 bool bTriggerBuffered
           en attaque H2H pour savoir que je suis en train d'attendre
 bool bUTurnMove
           =patrouille= deplacement pour les retournement en patrouille
 bool bVaVersAlarme
           car pote l'a declenchee
 bool bVigilant
           vigilant ou pas <-> setvigilant
 bool bWaitForMover
           utilise dans notifybump vers ouvreporte
 bool bWeaponNoise
           pour faire une retraite
 float fTimerAttackMusic
           =attaqueScriptee= pour faire repasser la musique en attente apres certain temps
 GenAlerte genalerte
           une grenade est lancee
 int iCompteur
           compteur utilise dans les boucle sur routecache
 int iEtatVaVersSTrp
           =attaque= etat = 0 inactif, etat=1 va a un point intermediaire,etat=2 va a un StrP et etat=3 reste sur un STrP
 int iNumEtat
           =attaqueScriptee= numero de l'etat (grenadage,...)
 name nextstate
           prochain etat apres vavers
 int numHuntPaths
           =chasse= nombre de points dans chasse
 name prevstate
           dernier etat avant ouvreporte
 bool result
           =attaqueScriptee= pour savoir si change de branche et pour grenade - utilise aussi dans opendoor
 float sleeptime
           =patrouille= temps de pause sur patrolpoint
 int temp_int
           compteur utilise dans les boucle sur routecache

States
AttaqueScriptee, OuvrePorte, VaVers, Investigation, FuiteGrenade, Fuite, temporise, Chasse, TacticalMove, Attaque, AttaqueH2H, Acquisition, ResteSurPlace, Tenir, Errance, Patrouille, init, faction, Mort, Otage

Function Summary
 rotator AdjustAim(Ammunition FiredAmmunition, vector projStart, int aimerror)
     
// ----------------------------------------------------------------------
// Adjust Aim
// ----------------------------------------------------------------------
 int AllianceLevel(Pawn Newenemy)
     
// ----------------------------------------------------------------------
// AllianceLevel()
//
// renvoi -1 (enemy) 0 (neutre) ou 1 (ami)suivant alliance
// ----------------------------------------------------------------------
 AttitudeInfo AttitudeToNMI(Pawn other)
     
// ----------------------------------------------------------------------
// FearAttitude()
// ----------------------------------------------------------------------
 void ChangeEtat()
     
// ----------------------------------------------------------------------
// ChangeEtat : retour vers etat neutre
// ----------------------------------------------------------------------
 bool ChangeToBestWeapon()
     
// ----------------------------------------------------------------------
// ChangeToBestWeapon()
// ----------------------------------------------------------------------
 void CheckLineOfFire()
     
// ----------------------------------------------------------------------
//  CheckLineOfFire()           //pote MAJ
//
//declenche pas sur le cote si pote devant
//et passe en chasse si peut pas tirer
// ----------------------------------------------------------------------
 void ChercheAlarme()
     
// ----------------------------------------------------------------------
// ChercheAlarme
// ----------------------------------------------------------------------
 AttackPoint ChercheAttackPoint()
     
// ----------------------------------------------------------------------
// ChercheAttackPoint
//
// ----------------------------------------------------------------------
 bool ChercheBonMatos(Pawn other)
     
// ----------------------------------------------------------------------
// ChercheBonMatos
//
//si oui ressort l'arme correspondante
// ----------------------------------------------------------------------
 XIIIPawn ChercheNMIPlusProche()
     
// ----------------------------------------------------------------------
//
//ChercheNMIPlusProche
//
// ----------------------------------------------------------------------
 void CherchePlanqueGrenade()
     
// ----------------------------------------------------------------------
// CherchePlanqueGrenade
//
// ----------------------------------------------------------------------
 bool CherchePointPourCamper()
     
// ----------------------------------------------------------------------
// CherchePointPourCamper  // pour camper
//
// ----------------------------------------------------------------------
 void CherchePointReload()
     
// ----------------------------------------------------------------------
// CherchePointReload      //priorite au dernier safepoint
//
// ----------------------------------------------------------------------
 void CherchePointRetraite()
     
// ----------------------------------------------------------------------
// CherchePointRetraite      //priorite au dernier safepoint
//
// ----------------------------------------------------------------------
 void CherchePointSafe()
     
// ----------------------------------------------------------------------
// CherchePointSafe
//
// ----------------------------------------------------------------------
 void ChercheReseauAttaque()
     
// ----------------------------------------------------------------------
// ChercheReseauAttaque
//
//retourne vrai si a trouve une grenade differente
// ----------------------------------------------------------------------
 void DamageAttitudeTo(Pawn Other, float Damage)
     
// ----------------------------------------------------------------------
// DamageAttitudeTo
// ----------------------------------------------------------------------
 vector DirectionDuTir()
     
// ----------------------------------------------------------------------
// DirectionDuTir()  //avant dispersion
//  Mise a jour de AnleDispersion et point de depart du tir (WeaponStartTrace)
// ----------------------------------------------------------------------
 bool FindBestPathTo(vector desti)
     
// ----------------------------------------------------------------------
// FindBestPathTo()
//
//
// ----------------------------------------------------------------------
 bool FindBestPathToward(Actor desired, optional float, optional float)
     
// ----------------------------------------------------------------------
// FindBestPathToward()
//
// assumes the desired destination is not directly reachable.
// It tries to set Destination to the location of the
// best waypoint, and returns true if successful
// ----------------------------------------------------------------------
 void FindNewStakeOutDir()
     
// ----------------------------------------------------------------------
// FindNewStakeOutDir
//
// trouve point de visee dans temporise
// ----------------------------------------------------------------------
 void FireEnemy()
     
// ----------------------------------------------------------------------
// FireEnemy
// ----------------------------------------------------------------------
 int GetFacingDirection()
     
// ----------------------------------------------------------------------
// GetFacingDirection
// ----------------------------------------------------------------------
 void HalteAuFeu()
     
// ----------------------------------------------------------------------
// HalteAuFeu
// ----------------------------------------------------------------------
 bool LigneVisee(vector TraceEnd, vector TraceStart)
     
// ----------------------------------------------------------------------
// LigneVisee()
// ----------------------------------------------------------------------
//permet de savoir si je peut tirer sur le perso (pour eviter de tirer dans les murs)
//collisionne avec level, levelgeometrie et mover
 int LineOfFireObstacle()
     
// ----------------------------------------------------------------------
//  LineOfFireObstacle()
//
//retourne type de perso
//=0 ligne de mire libre (rien, enemy ou breakable avec bcanseethrought)
//=1 un pote (la var pote est actualisee)
//=2 il y autre chose devant
// ----------------------------------------------------------------------
 void MoverFinished()
     
// ----------------------------------------------------------------------
// MoverFinished
// ----------------------------------------------------------------------
 bool NearWall(float walldist)
     
/* NearWall() returns true if there is a nearby barrier at eyeheight, and
changes FocalPoint to a suggested place to look
*/
 int NombrePotesPresents()
     
// ----------------------------------------------------------------------
//  NombrePotesPresents()
//
//  Nombre de potes dans rayon de 12m
// ----------------------------------------------------------------------
 void NotifyFiring()
     
// ----------------------------------------------------------------------
// NotifyFiring
// ----------------------------------------------------------------------
 void PawnDied()
 PatrolPoint PickStartPoint()
     
// ----------------------------------------------------------------------
// PickStartPoint
//
// prend point de depart pour patrouille
// ----------------------------------------------------------------------
 vector PseudoSteering()
     
// ----------------------------------------------------------------------
// PseudoSteering
// pseudo steering pour les deplacements en combat
// ----------------------------------------------------------------------
 void ReceiveWarning(Pawn shooter, float projSpeed, vector FireDir)
     
// ----------------------------------------------------------------------
// ReceiveWarning
//
// ----------------------------------------------------------------------
 float RelativeStrength(Pawn Other)
     
// ----------------------------------------------------------------------
//
// RelativeStrength()
//
//returns a value indicating the relative strength of other
//0.0 = equal to controlled pawn
//> 0 stronger than controlled pawn
//< 0 weaker than controlled pawn
//
//Since the result will be compared to the creature's aggressiveness, it should be
//on the same order of magnitude (-1 to 1)
//Estimation en fonction de la vie, des armes et des positions en hauteur.
// ----------------------------------------------------------------------
 void SeeEnemy()
 bool SetEnemy(Pawn NewEnemy)
     
// ----------------------------------------------------------------------
// SetEnemy
// ----------------------------------------------------------------------
 void SetVigilant(bool bEnAlerte)
     
//SightRadius augmente de 50%
//HearingThreshold augmente de 50%
 void SwitchToEnemy(Pawn newEnemy)
     
// ----------------------------------------------------------------------
// SwitchToEnemy: fait passer soldier neutre en ennemi
// ----------------------------------------------------------------------
 bool TestDirection(float mindist, float dist, vector dir, out vector)
     
// ----------------------------------------------------------------------
// TestDirection()
// ----------------------------------------------------------------------
//test le deplacement dans une direction (en collisionnant tout),suggere une position intermediaire
// sica passe pas et renvoi vrai si le deplacement suggere est superieur a une distance minimal e
 bool TestSonEntendu(Actor Son)
     
// ----------------------------------------------------------------------
// TestSonEntendu
// ----------------------------------------------------------------------
 void s_decalerte()
     
//[****] a virer
 void s_decattaque()
 void s_decattente()
 void s_incalerte()
 void s_incattaque()
 void s_incattente()


State AttaqueScriptee Function Summary
 void GetAttackPointProperties(AttackPoint PointAttaque, out float)
 void EndState()
 void BeginState()
 void CheckLineOfFire()
 void PasseEtatAlerteEnAttente()
 void PasseEtatAlerteEnAttaque()
 rotator AdjustAim(Ammunition FiredAmmunition, vector projStart, int aimerror)
 void NotifyFiring()
 void SeeEnemy()
 void DamageAttitudeto(Pawn Other, float Damage)


State OuvrePorte Function Summary
 void Endstate()
 void beginstate()
 void DamageAttitudeTo(Pawn Other, float Damage)


State VaVers Function Summary
 void endstate()
 void beginstate()
 void ActualiseSon(Actor son)


State Investigation Function Summary
 void endstate()
 void beginstate()
 bool EnregistrePointsVersEnemy()


State FuiteGrenade Function Summary
 void EndState()
 void BeginState()
 void PickDestination()
 void CheckNearestGrenad()


State Fuite Function Summary
 void EndState()
 void BeginState()
 void PickDestination()


State temporise Function Summary
 void EndState()
 void BeginState()
 bool CanStakeOut()
 bool ContinueStakeOut()


State Chasse Function Summary
 void EndState()
 void BeginState()
 bool FindViewSpot()
 void PickDestination()
     
//if (NewEnemy==XIII) TriggerEvent('XIIIVu', Self, pawn);  //trigger vu
        focus=enemy;
        gotostate('attaque');
    }
    


State TacticalMove Function Summary
 void EndState()
     
    {
        if (CHARGE_LES_LOGS) log(pawn@"Tactical Move");
        if (NiveauAlerte==0)
        {
            s_decAttente();
            s_incAttaque();
        }
        else if (NiveauAlerte==1)
        {
            s_decAlerte();
            s_incAttaque();
        }
        NiveauAlerte=2;
        bDisableDamageattitudeto=false;
        Temps_Ref=Level.timeseconds-2;
        settimer3(Temps_RefreshEnemyPos,true);
    }

    
 void BeginState()
     
    {
        local vector pick, pickdir;


        pickdir=(Enemy.location-pawn.location) cross vect(0,0,-1);
        pickdir.Z = 0;
        pickdir=normal(pickdir);

        if (TestDirectionAvoidingAlly(pickdir, pick,PoteAEviter))
        {
            Destination = pick;
            return true;
        }
        return false;
    }
    
 bool TestPasSurLaDroite(BaseSoldier PoteAEviter)
     
    {
        local vector pick, pickdir;

        pickdir=(Enemy.location-pawn.location) cross vect(0,0,1);
        pickdir.Z = 0;
        pickdir=normal(pickdir);

        if (TestDirectionAvoidingAlly(pickdir, pick,PoteAEviter))
        {
            Destination = pick;
            return true;
        }
        return false;
    }

    
 bool TestPasSurLaGauche(BaseSoldier PoteAEviter)
     
// pour partir a 80 degres si charge

        MoveDist=200;
        return TestDirection(110,MoveDist,pickdir, pick);
    }
    
 bool TestDirectionAvoidingAlly(vector pickdir, out vector, BaseSoldier PoteAEviter)
     
//test both right and left
    {
        local vector pick, pickdir;
        local bool success;
        local float MoveDist;

        pickdir=(Enemy.location-pawn.location) cross vect(0,0,1);
        pickdir.Z = 0;
        pickdir=normal(pickdir);
        if (Frand()>0.5)
            pickdir *= -1;

        MoveDist = 150+50* FRand();
        success = TestDirection(100,MoveDist,pickdir, pick);
        if (!success)
        {
            MoveDist = 270;
            success = TestDirection(100,MoveDist,-1*pickdir, pick);
            if (!success)
                return false;
        }
        Destination = pick;
        return success;
    }

    
 bool StrafeDestination()
     
//son
        bases.PlaySndPNJOno(pnjono'Onomatopees.hPNJHurt',bases.CodeMesh,bases.NumeroTimbre);

        if (bDisableDamageattitudeto)
            return;
        If (xiii.bPrisonner && XIII.LHand.pOnShoulder!=none && AllianceLevel(XIII.LHand.pOnShoulder)==1 && other==xiii)
        {
            if (CHARGE_LES_LOGS) log(pawn$"je riposte");
            NbCoupsRiposte=(2+bases.agressivite)*1.9;
            NbCoupsRiposte=Min(5,NbCoupsRiposte);
            NbCoupsRiposte=Max(1,NbCoupsRiposte);
        }
    }
    
 void DamageAttitudeto(Pawn Other, float Damage)
     
//decalage par rapport a l'arme
        CheckLineOfFire();
    }
    
 void NotifyFiring()
     
//CadavreWithPickup affecte a other dans Cherchebonmatos
        {
                    HalteAufeu();
            bDisableEventSeeDeadPawn=true;
            CadavreWithPickup.bDejaFouille=true;
            gotostate('tacticalmove','chercheobjet');
        }
    }
    event EnemyNotVisible()
    {
        if (LigneVisee(enemy.location, LastSeeingPos))
        {
            GotoState('TacticalMove','RecoverEnemy');
            return;
        }
        else
        {
            gotostate('temporise');
            return;
        }
    }
    


State Attaque Function Summary
 void EndState()
     
//temp_int=0; //utilise pour boucle sur pointchemin
        LastStrP=none;

    }
    
 void BeginState()
     
//log("tente grenadage "@FastTrace(enemy.location+vect(0,0,80),enemy.location));
                if (Vsize(enemy.location-pawn.location)<1200 && Vsize(enemy.location-pawn.location)>200 && FastTrace(enemy.location+vect(0,0,80),enemy.location) && FastTrace(enemy.location+vect(0,0,80),pawn.eyeposition()+pawn.location))
                    return true;
        }
        return false;
    }

    
 bool TenteGrenadage()
     
    {
        local GrenadeTarget GrenT;
        local int i;

        For(i=0;i
 GrenadeTarget ActiveGrenadeTarget()
     
// ELR End
        if (pawn.pendingweapon==none || !pawn.pendingweapon.HasAmmo())
        {
            log(pawn$"          BEN J'AI PAS DE GRENADE  $$$$$$$");
            return false;
        }
        else
        {
            Pawn.Weapon.PutDown();
            return true;
        }
    }
    
 bool SwitchSurGrenade()
     
// AI controlled creatures may duck if not falling
        if (bases.order=='garder' || bEnCouverture || iEtatVaVersStrp>0 || (Enemy == None)
            || (Pawn.Physics == PHYS_Falling) || (Pawn.Physics == PHYS_Swimming) )
            return;

        if (FRand() > 0.02 * skill)
            return;

        if (shooter==xiii)
        {
            if (!XIIIWeapon(shooter.weapon).AmmoType.bInstantHit)
            {
                enemyDist = VSize(shooter.Location - Pawn.Location);
                if (enemyDist/projSpeed > 0.11 + 0.15 * FRand())
                {
                    gotostate('TacticalMove','strafe');
                    return;
                }
            }
            else
					gotostate('TacticalMove','strafe');
        }
    }

    
 void ReceiveWarning(Pawn shooter, float projspeed, vector firedir)
     
//son
        bases.PlaySndPNJOno(pnjono'Onomatopees.hPNJHurt',bases.CodeMesh,bases.NumeroTimbre);

	     If (xiii.bPrisonner && XIII.LHand.pOnShoulder!=none && AllianceLevel(XIII.LHand.pOnShoulder)==1 && other==xiii)
        {
           if (CHARGE_LES_LOGS) log(pawn$"je riposte");
           NbCoupsRiposte=(2+bases.agressivite)*1.9;
           NbCoupsRiposte=Min(5,NbCoupsRiposte);
           NbCoupsRiposte=Max(1,NbCoupsRiposte);
        }
    }

    
 void DamageAttitudeto(Pawn Other, float Damage)
     
//log("pawn.weapon"@pawn.weapon.hasammo()@XIIIWeapon(pawn.weapon).reloadcount@(1.6-vsize(enemy.location-pawn.location)*0.002)>frand()@(1.6-vsize(enemy.location-pawn.location)*0.002));
            if (pawn.weapon.reloadcount==1 && pawn.weapon.default.reloadcount>1)
            {
                if (bases.order!='garder' && (1.6-vsize(enemy.location-pawn.location)*0.002)>frand())
                {
                    bFuitPourreloader=true;
                    Timer_VaRecharger=level.timeseconds;
                    CherchePointReload();
                }
            }
        }

    }
    
 void NotifyFiring()
     
//va vers point interdemediaire
                    {
                        PointIntermediaire.bAlreadyTargeted=false;
                        if (cansee(enemy)) fireenemy();
                    }
                    gotostate('attaque','vaversStrP');
                }
                else if (FindBestPathToward(LastStrP))
                {
                    LastStrP.Occupe();
                    if (bjump)
                    {
                        LastStrP.FinishJumpPoint.occupe();
                    }
                    for (i=0;i<16;i++)
                    {
                        if (routecache[i]==none)
                            break;
                        PointChemin[i]=routecache[i];
                    }
                    NbPointChemin=i;
                    gotostate('attaque','vaversStrP');
                }
            }
        }
    }

    


State AttaqueH2H Function Summary
 void EndState()
     
//temp_int=0; //utilise pour boucle sur pointchemin

    }
    
 void BeginState()
     
//			log(nav@vsize(nav.location-enemy.location)<300@Vsize(nav.location-pawn.location)>=(pawn.collisionradius*1.2)@(bestnav==none || vsize(nav.location-enemy.location)
 bool LookForNearestPoint()
     
    {
    }

	
 void ReceiveWarning(Pawn shooter, float projspeed, vector firedir)
     
//son
        bases.PlaySndPNJOno(pnjono'Onomatopees.hPNJHurt',bases.CodeMesh,bases.NumeroTimbre);
        If (xiii.bPrisonner && XIII.LHand.pOnShoulder!=none && AllianceLevel(XIII.LHand.pOnShoulder)==1 && other==xiii)
        {
           if (CHARGE_LES_LOGS) log(pawn$"je riposte");
           NbCoupsRiposte=(2+bases.agressivite)*1.9;
           NbCoupsRiposte=Min(5,NbCoupsRiposte);
           NbCoupsRiposte=Max(1,NbCoupsRiposte);
        }
    }

    
 void DamageAttitudeto(Pawn Other, float Damage)
     
//recupere direction du tir avant dispersion
        CheckLineOfFire();
    }
    
 void NotifyFiring()
     
//CadavreWithPickup affecte a other dans Cherchebonmatos
        {
            HalteAufeu();
            bDisableEventSeeDeadPawn=true;
            CadavreWithPickup.bDejaFouille=true;
            gotostate('tacticalmove','chercheobjet');
        }
    }
    event UpdateTactics()
    {
        if (Vsize(enemy.location-temp_vect)>50)
        {
            badvancedtactics=false;
            gotostate('AttaqueH2H','charge');
        }
    }

    


State Acquisition Function Summary
 void Endstate()
 void beginstate()
     
    {
    local NavigationPoint N, Best;
    local vector Dir, EnemyDir;
    local float Dist, BestVal, Val;

      EnemyDir = Normal(Enemy.Location - Pawn.Location);
      for ( N=Level.NavigationPointList; N!=None; N=N.NextNavigationPoint )
      {
      Dir = N.Location - LAstSeenPos;
      Dist = VSize(Dir);
      if (Dist<200)
      {
      Val = (EnemyDir Dot Dir/Dist);
      if ((Val > BestVal) && LineOfSightTo(N))
      {
      BestVal = Val;
      Best = N;
      }
      }
      }
      if ( Best != None )
      LastSeenPos = Best.Location + 0.5 * Pawn.CollisionHeight * vect(0,0,1);
     }  */
 void CherchePointPresDernierePos()
     
    /* [****] integrer si le positionnnement n'est pas bon
    A REVOIR ENTIEREMENT
    
 void InitReactions()
 void ChercheNMIDuRegard()
 void ActualiseSon(Actor son)
 void DamageAttitudeTo(Pawn Other, float Damage)
 void SeeEnemy()


State ResteSurPlace Function Summary
 void Endstate()
 void beginstate()
 bool TestPasSurCote(BaseSoldier PoteAEviter)
 bool TestDirectionAvoidingAlly(vector pickdir, out vector, BaseSoldier PoteAEviter)
 void DamageAttitudeTo(Pawn Other, float Damage)


State Tenir Function Summary
 void Endstate()
 void beginstate()
 void DamageAttitudeTo(Pawn Other, float Damage)


State Errance Function Summary
 void Endstate()
 void beginstate()
 bool IsInWanderingVolume(WanderingVolume aVolume)
 void PickDestination()
 void DamageAttitudeTo(Pawn Other, float Damage)


State Patrouille Function Summary
 void Endstate()
 void beginstate()
 bool IsPointInCylinder(Actor cylinder, Vector point, optional float, optional float)
 void PickDestination()
 void DamageAttitudeTo(Pawn Other, float Damage)


State init Function Summary
 void EndState()
 void BeginState()
 void BufferTrigger()


State faction Function Summary
 void endstate()
 void Beginstate()


State Mort Function Summary
 void Endstate()
 void BeginState()
 void Trigger(Actor Other, Pawn EventInstigator)
 void DamageAttitudeTo(Pawn Other, float Damage)
 bool NearWall(float walldist)


State Otage Function Summary
 void Endstate()
 void BeginState()
 void Trigger(Actor Other, Pawn EventInstigator)
 void DamageAttitudeTo(Pawn Other, float Damage)
 bool NearWall(float walldist)



Source Code


00001	//=============================================================================
00002	// IAController.
00003	//=============================================================================
00004	class IAController extends AIController native;
00005	//#exec OBJ LOAD FILE=XIIISound.uax PACKAGE=XIIISound
00006	#exec OBJ LOAD FILE="Onomatopees.uax" PACKAGE=Onomatopees
00007	
00008	//Structures
00009	
00010	Struct MovePointInfo
00011	{
00012	    var vector MovePoint;
00013	    var bool bTraceable;
00014	};
00015	var MovePointInfo MovePoint;
00016	Struct MoveActorInfo
00017	{
00018	    var actor MoveActor;
00019	    var bool bReachable;
00020	};
00021	var MoveActorInfo MoveActor;
00022	
00023	var enum AttitudeInfo
00024	{
00025	    ATTITUDE_Fear,
00026	        ATTITUDE_Impressed,
00027	        ATTITUDE_Charge
00028	} AttitudeTOInfo;
00029	
00030	
00031	//---------------------------------------------------
00032	// Variables
00033	//---------------------------------------------------
00034	var actor PointChemin[16];//points intermediaire du pathfinding
00035	var actor Interrogation; // effet interrogation ou exclamation
00036	var actor PointsInvestigation[3]; //=investigation=
00037	var pawn PeeredEnemy;
00038	var XiiiPlayerPawn XIII;
00039	var xiiipawn PoteQuiMeBloque;   //=attaque= pote qui me bloque le chemin
00040	var BaseSoldier BaseS;
00041	var basesoldier Pote; // ben c'est un pote qu'il faut eviter de toucher. MAJ dans fonction native LineOfFireObstacle()
00042	var basesoldier CadavreWithPickup; // pour aller chercher pickups sur cadavre
00043	var weapon WeaponOnGround; //arme recuperee sur cadavre
00044	var XIIIporte PorteOuverte;        //porte a ouvrir
00045	var XIIIporte LastBumpedDoor; //last bumped door to avoid to be blocked
00046	var navigationpoint DoorP;  //=ouvreporte= pour verifier qu'il y a des doorpoints
00047	var NavigationPoint DestNavPoint; //=patrouille= point de destination
00048	var navigationPoint PointIntermediaire; //=attaque=  point intermediaire de deplacement
00049	var patrolpoint LastPatrolPoint; //=patrouille= dernier patrolpoint utilise
00050	var AttackPoint LastAttackPoint; //Point d'attaque courant
00051	var AttackPoint OldAttackPoint; //Dernier Point d'attaque
00052	var SafePoint OldSafePoint; //=chasse= Dernier Safe Point
00053	var SafePoint SafePointOccupe;
00054	var StrategicPoint LastStrP;
00055	var grenadflying Grenade;  //une grenade est lancee
00056	var genalerte genalerte;
00057	
00058	var name EtatNeutre; // etat neutre (tenir, patrouille ou tenir)
00059	var name nextstate;  // prochain etat apres vavers
00060	var name prevstate;  // dernier etat avant ouvreporte
00061	var name PatrolAnim; //type d'anim de patrouille
00062	var name WaitPatrolAnim;//type d'anim d'attente en patrouille
00063	var name TurnLPatrolAnim;//type d'anim de demi-tour en patrouille vers gauche
00064	var name TurnRPatrolAnim;//type d'anim de demi-tour en patrouille vers droite
00065	
00066	
00067	var rotator PointTenirRot; //=tenir= direction point de retour en tenir
00068	
00069	
00070	var vector EnemyTargetPos; //derniere position connue de l'enemy
00071	var vector EnemyTargetVelocity;
00072	var vector DirectionTir;   //direction du tir
00073	var vector WeaponStartTrace; //point de depart de la balle de l'arme mise a jour dans le moteur
00074	var vector Temp_Vect;
00075	var vector HidingSpot;   //=tacticalmove=
00076	var vector PointTenirPos; //=tenir= position de point de retour en tenir
00077	var vector PoteQuiMeBloquePos; //=attaque= pos du pote qui me bloque la porte
00078	var vector PointDestination;     //=attaque=  pour calculer destination
00079	var vector VecteurRecalage; //=attaque=
00080	
00081	
00082	var float Temps_errance; //temps d'errance entre patrouille et errance
00083	var float DistanceDeplacement; // distance de test de deplacement dans errance et fuite
00084	var float DistNearWall;        //distance de tdetection des murs
00085	var float Temps_RefreshEnemyPos;
00086	var float DefaultPeripheralVision;
00087	var float DefaultSightRadius;
00088	var float DefaultHearingThreshold;
00089	var float VitesseDeplacements; //vitesse de deplacements en strafe
00090	var float Timer_VaRecharger;
00091	// cone de visee
00092	var float Angle_Visee;
00093	var float Temps_ref;  //timer
00094	var float Temps_Ref2; //timer
00095	var float Temp_float; //utilise partout
00096	var float FireTimerRefresh; //temps de refresh du tir en auto
00097	var float sleeptime; //=patrouille= temps de pause sur patrolpoint
00098	var float VitesseHorizontaleSaut; //=attaqueScriptee= utilise pour saut
00099	var float fTimerAttackMusic; //=attaqueScriptee= pour faire repasser la musique en attente apres certain temps
00100	var float TempsDeclencheAlarme; //delai avant qu'il declenche l'alarme
00101	
00102	var int NiveauALerte; //niveau d'alerte
00103	var int NiveauALerteEnAS; //niveau d'alerte
00104	var int NbCoupsRiposte; //utilise dans timer pour savoir combien de coups ne sont pas bloques
00105	var int CompteurRecalage;//utilise dans charge,attaque et TM pour savoir si se recale
00106	var int CompteurTrame; //optimisation du Tick
00107	var int NbPointChemin; // nb de point dans pathfinding
00108	var int iCompteur; //compteur utilise dans les boucle sur routecache
00109	var int temp_int;
00110	var int NumeroProchainPoint; //=attaqueScriptee= choix entre differents AP
00111	var int NombreDePointsSkippes;//=attaqueScriptee= pour calcul du prochain AP
00112	var int iNumEtat; //=attaqueScriptee= numero de l'etat (grenadage,...)
00113	var int NextRouteCachePoint; //=attaqueScriptee= pour reprendre vers point suivant apres ouverture de porte
00114	var int numHuntPaths; //=chasse= nombre de points dans chasse
00115	//var int NbTentativesDecrampage;  //=attaque=  pour tester crampage en melee
00116	var int iEtatVaVersSTrp;  //=attaque= etat = 0 inactif, etat=1 va a un point intermediaire,etat=2 va a un StrP et etat=3 reste sur un STrP
00117	
00118	
00119	var bool bDisableDamageattitudeto;
00120	var bool CHARGE_LES_LOGS; // Pour voir mes logs
00121	var bool bTire;
00122	var bool bChercheStrategicPoint;
00123	var bool bWaitForMover;  //utilise dans notifybump vers ouvreporte
00124	var bool bPrisonnier; //utilise dans timer vers timer pour savoir si pote otage
00125	var bool bPrecedentTirBloque; //utilise dans timer vers timer pour savoir si le precedent tir a ete bloque lors de prise d'otage
00126	var bool bVigilant; //vigilant ou pas  <-> setvigilant
00127	var bool bEtatAlerte; //en etat d'alerte  donc attaque direct
00128	var bool bRetraiteVersSafePoint; //pour faire une retraite
00129	var bool bCampeVersSafePoint;
00130	//reactions
00131	var bool bStepNoise;
00132	var bool bImpactNoise;
00133	var bool bWeaponNoise;
00134	var bool bCadavreVu;
00135	var bool bPaffe;
00136	var bool bDejaVu;
00137	var bool bPotePaffe;
00138	var bool bVaVersAlarme; //car pote l'a declenchee
00139	var bool bAlarmeInstigator; // vrai pawn si declencheur de l'alarme
00140	//var bool bADejaCrie;
00141	var bool bBloqueFuiteGrenades;
00142	var bool bPremiereRafale;
00143	var bool bTirSurConeMax;
00144	var bool bUTurnMove; //=patrouille= deplacement pour les retournement en patrouille
00145	var bool bAVuQuelquechose; // =acquisition= pour sortie interro et exclamation
00146	var bool bSwitchMusicInWaitState; ////=attaqueScriptee= a fixe l'etat de musique en attente apres delai de pas vu.
00147	var bool bSaut; //=attaqueScriptee=  je suis en train de sauter
00148	var bool result;       //=attaqueScriptee= pour savoir si change de branche  et pour grenade - utilise aussi dans opendoor
00149	var bool bAccroupiSurAP; //=attaqueScriptee= util. pour tir en rafale
00150	var bool bDeplacementsRoulade; //=attaqueScriptee=
00151	var bool bDontSeeAnyMore; //=attaqueScriptee= pour desactivation musique attaque
00152	var bool bTemp_Bool;
00153	var bool bEnCouverture;    //=attaque=
00154	var bool bLanceGrenade;  //=attaque=
00155	var bool bFuitPourreloader; //=attaque=
00156	var bool bARienVu; // je suis passe en point d'interro
00157	var bool bLookAtEnemy;//regarde si voit enemy pour recommencer a lui tirer dessus
00158	var bool bInWaitMode; // en attaque H2H pour savoir que je suis en train d'attendre
00159	var bool bInterruptStateToOpenDoor;
00160	var bool bTriggerBuffered;
00161	
00162	// ----------------------------------------------------------------------
00163	// ChercheBonMatos
00164	//
00165	//si oui ressort l'arme correspondante
00166	// ----------------------------------------------------------------------
00167	function bool ChercheBonMatos(pawn other)
00168	{
00169		CadavreWithPickup=basesoldier(other);
00170	   if (!bases.bFouilleCadavres || CadavreWithPickup==none || CadavreWithPickup.bDejaFouille || (enemy!=none && Vsize(enemy.location-pawn.location)<390))
00171	      return false;
00172	    if (other.weapon==none || !other.weapon.hasammo() || other.isa('cine2'))
00173		 {
00174			  CadavreWithPickup.bDejaFouille=true;
00175	        return false;
00176		 }
00177	 	 if (Vsize(other.location-pawn.location)>1000 || !actorreachable(other))
00178			   return false;
00179	
00180	    if (!pawn.weapon.hasammo() || other.weapon.airating>pawn.weapon.airating)  //meilleure arme ou meme arme si j'ai plus de muns
00181	        return true;
00182	    return false;
00183	}
00184	
00185	// ----------------------------------------------------------------------
00186	// CherchePlanqueGrenade
00187	//
00188	// ----------------------------------------------------------------------
00189	function CherchePlanqueGrenade()  //cherche safepoint le plus pres et a moins de 55m
00190	{                                   //GRENADE DOIT IMPRATIVEMENT NE PAS ETRE EGAL A none
00191	    local SafePoint Safe,BestSafe,secondsafe;
00192	    local int i;
00193		 local float DistOfSafeToGrenad;
00194	
00195	    if (grenade==none)
00196	    {
00197	        log(pawn@"WWWWWWAAAAAARRRRNNNNNNIIIIIIINNNNNGGGGGGG pas de grenade!!!");
00198	        return;
00199	    }
00200	 	 if (SafePointOccupe!=none)
00201			SafePointOccupe.timer(); //libere point
00202	    For(i=0;i<level.game.SafePointList.Length;i++)
00203	    {
00204	        safe=safepoint(level.game.SafePointList[i]);
00205	        //log("safe"@safe@!Safe.bAlreadyTargeted@VSize(safe.location-pawn.location)<4000);
00206	        if (!Safe.bAlreadyTargeted && VSize(safe.location-pawn.location)<4000 && VSize(safe.location-pawn.location)>pawn.collisionradius*2)
00207	        {
00208					DistOfSafeToGrenad=Vsize(safe.location-grenade.location);
00209	            if ((!FastTrace(Safe.location,grenade.location) || DistOfSafeToGrenad>1300) && (actorreachable(safe) || FindBestPathToward(safe)))
00210	            {
00211	                if (bestsafe== none || Vsize(bestsafe.location-grenade.location)>DistOfSafeToGrenad)
00212	                {
00213								secondsafe=bestsafe;
00214	                     bestsafe=safe;
00215	                }
00216	        		}
00217			  }
00218	    }
00219		 if (bestsafe==none)
00220				return;
00221		 else if (secondsafe!=none)
00222		 {
00223			 if (Vsize(bestsafe.location-pawn.location)>600 && (secondsafe.location-pawn.location) dot (grenade.location-pawn.location)<(bestsafe.location-pawn.location) dot (grenade.location-pawn.location))
00224				bestsafe=secondsafe;
00225		 }
00226		 //log("a trouve planque grenade"@bestsafe@actorreachable(bestsafe)@FindBestPathToward(bestSafe));
00227	    Movetarget=none;
00228	    if (actorreachable(bestsafe))
00229	    {
00230	        OldSafePoint=bestsafe;
00231	        MoveActor.MoveActor=bestsafe;
00232	        MoveActor.bReachable=true;
00233	        bestsafe.Occupe();
00234			  SafePointOccupe=bestsafe;
00235			  HalteAufeu();
00236	        gotostate('fuitegrenade','vaverssafepoint');
00237	    }
00238	    else if (FindBestPathToward(bestSafe))
00239	    {
00240	        OldSafePoint=bestsafe;
00241	        MoveActor.MoveActor=bestsafe;
00242	        MoveActor.bReachable=false;
00243	        for (i=0;i<16;i++)
00244	        {
00245	            if (routecache[i]==none)
00246	                break;
00247	            PointChemin[i]=routecache[i];
00248	        }
00249	        NbPointChemin=i;
00250				HalteAufeu();
00251	  		  SafePointOccupe=bestsafe;
00252	        bestsafe.Occupe();
00253	        gotostate('fuitegrenade','vaverssafepoint');
00254	    }
00255	}
00256	
00257	// ----------------------------------------------------------------------
00258	// CherchePointSafe
00259	//
00260	// ----------------------------------------------------------------------
00261	function CherchePointSafe()  //cherche safepoint le plus loin, pas visible par l'enemy et a moins de 55m
00262	{                                   //ENEMY DOIT IMPRATIVEMENT NE PAS ETRE EGAL A NONE
00263	    local SafePoint Safe,BestSafe;
00264	    local bool bFirstInPlace;
00265	    local bool bAngleDeVUe;
00266	    local int i;
00267	
00268	    if (enemy==none)
00269	    {
00270	        log(pawn@"WWWWWWWWWWWWWWAAAAAAAAAARRRRRRRRRRNNNNNNNNNIIIIIIIIIIIIIIIIINNNNNNNNNGGGGGGGGGGG !!!");
00271	        return;
00272	    }
00273	
00274	    For(i=0;i<level.game.SafePointList.Length;i++)
00275	    {
00276	        safe=safepoint(level.game.SafePointList[i]);
00277	        if (OldSafePoint!=safe && !Safe.bAlreadyTargeted && VSize(safe.location-pawn.location)<4000)
00278	        {
00279	            bFirstInPlace= 0.01+Vsize(Safe.location -pawn.location)/pawn.groundspeed<Vsize(Safe.location - enemy.location)/enemy.groundspeed;
00280	            if (Safe.baccroupi)
00281	                bAngleDeVUe=FastTrace(Safe.location+vect(0,0,8.4),enemy.location + enemy.eyeposition());
00282	            else
00283	                bAngleDeVUe=FastTrace(Safe.location+enemy.eyeposition(),enemy.location + enemy.eyeposition());
00284	            if (!bAngleDeVUe && bFirstInPlace)
00285	                if (bestsafe!=none)
00286	                {
00287	                    if (Vsize(bestsafe.location-pawn.location)<Vsize(safe.location- pawn.location))
00288	                        bestsafe=safe;
00289	                }
00290	                else
00291	                    bestsafe=Safe;
00292	        }
00293	    }
00294	    if (bestsafe==none)
00295	        return;
00296	    Movetarget=none;
00297	    if (actorreachable(bestsafe))
00298	    {
00299	        OldSafePoint=bestsafe;
00300	        MoveActor.MoveActor=bestsafe;
00301	        MoveActor.bReachable=true;
00302	        Nextstate='ResteSurPlace';
00303	        bestsafe.Occupe();
00304	        gotostate('vavers');
00305	    }
00306	    else if (FindBestPathToward(bestSafe))
00307	    {
00308	        OldSafePoint=bestsafe;
00309	        MoveActor.MoveActor=bestsafe;
00310	        MoveActor.bReachable=false;
00311	        for (i=0;i<16;i++)
00312	        {
00313	            if (routecache[i]==none)
00314	                break;
00315	            PointChemin[i]=routecache[i];
00316	        }
00317	        NbPointChemin=i;
00318	        Nextstate='ResteSurPlace';
00319	        bestsafe.Occupe();
00320	        gotostate('vavers');
00321	    }
00322	}
00323	// ----------------------------------------------------------------------
00324	// CherchePointRetraite      //priorite au dernier safepoint
00325	//
00326	// ----------------------------------------------------------------------
00327	function CherchePointRetraite()  //cherche safepoint le plus pres et pas visible par l'enemy a moins de 40m
00328	{                                   //ENEMY DOIT IMPRATIVEMENT NE PAS ETRE EGAL A NONE
00329	    local SafePoint Safe,BestSafe;
00330	    local bool bFirstInPlace;
00331	    local bool bAngleDeVUe;
00332	    local int i;
00333	
00334	    if (enemy==none)
00335	    {
00336	        log(pawn@"WWWWWWWWWWWWWWAAAAAAAAAARRRRRRRRRRNNNNNNNNNIIIIIIIIIIIIIIIIINNNNNNNNNGGGGGGGGGGG !!!");
00337	        return;
00338	    }
00339	    For(i=0;i<level.game.SafePointList.Length;i++)
00340	    {
00341	        safe=safepoint(level.game.SafePointList[i]);
00342	        if ((!Safe.bAlreadyTargeted || OldSafePoint==safe) && VSize(safe.location-pawn.location)<3200)
00343	        {
00344	            bFirstInPlace= 0.01+Vsize(Safe.location -pawn.location)/pawn.groundspeed<Vsize(Safe.location - enemy.location)/enemy.groundspeed;
00345	            if (Safe.baccroupi)
00346	                bAngleDeVUe=FastTrace(Safe.location+vect(0,0,8.4),enemy.location + enemy.eyeposition());
00347	            else
00348	                bAngleDeVUe=FastTrace(Safe.location+enemy.eyeposition(),enemy.location + enemy.eyeposition());
00349	            if (!bAngleDeVUe && bFirstInPlace)
00350	                if (bestsafe!=none)
00351	                {
00352	                    if (Vsize(bestsafe.location-pawn.location)>Vsize(safe.location- pawn.location))
00353	                        bestsafe=safe;
00354	                }
00355	                else
00356	                    bestsafe=Safe;
00357	        }
00358	    }
00359	    if (bestsafe==none)
00360	        return;
00361	    Movetarget=none;
00362	    if (actorreachable(bestsafe))
00363	    {
00364	        OldSafePoint=bestsafe;
00365	        halteaufeu();
00366	        MoveActor.MoveActor=bestsafe;
00367	        MoveActor.bReachable=true;
00368	        Nextstate='ResteSurPlace';
00369	        bRetraiteversSafePoint=true;
00370	        bestsafe.Occupe();
00371	        gotostate('vavers');
00372	    }
00373	    else if (FindBestPathToward(bestSafe))
00374	    {
00375	        MoveActor.MoveActor=bestsafe;
00376	        halteaufeu();
00377	        MoveActor.bReachable=false;
00378	        bRetraiteversSafePoint=true;
00379	        for (i=0;i<16;i++)
00380	        {
00381	            if (routecache[i]==none)
00382	                break;
00383	            PointChemin[i]=routecache[i];
00384	        }
00385	        NbPointChemin=i;
00386	        Nextstate='ResteSurPlace';
00387	        bestsafe.Occupe();
00388	        gotostate('vavers');
00389	    }
00390	}
00391	
00392	// ----------------------------------------------------------------------
00393	// CherchePointReload      //priorite au dernier safepoint
00394	//
00395	// ----------------------------------------------------------------------
00396	function CherchePointReload()  //cherche safepoint le plus pres et pas visible par l'enemy a moins de 40m
00397	{                                   //ENEMY DOIT IMPRATIVEMENT NE PAS ETRE EGAL A NONE
00398	    local SafePoint Safe,BestSafe;
00399	    local bool bFirstInPlace;
00400	    local bool bAngleDeVUe;
00401	    local int i;
00402	
00403	    if (enemy==none)
00404	    {
00405	        log(pawn@"WWWWWWWWWWWWWWAAAAAAAAAARRRRRRRRRRNNNNNNNNNIIIIIIIIIIIIIIIIINNNNNNNNNGGGGGGGGGGG !!!");
00406	        return;
00407	    }
00408	    For(i=0;i<level.game.SafePointList.Length;i++)
00409	    {
00410	        safe=safepoint(level.game.SafePointList[i]);
00411	        if ((OldSafePoint==safe || !Safe.bAlreadyTargeted) && VSize(safe.location-pawn.location)<1500)
00412	        {
00413	            bFirstInPlace= 0.01+Vsize(Safe.location -pawn.location)/pawn.groundspeed<Vsize(Safe.location - enemy.location)/enemy.groundspeed;
00414	            if (Safe.baccroupi)
00415	                bAngleDeVUe=FastTrace(Safe.location+vect(0,0,8.4),enemy.location + enemy.eyeposition());
00416	            else
00417	                bAngleDeVUe=FastTrace(Safe.location+enemy.eyeposition(),enemy.location + enemy.eyeposition());
00418	            if (!bAngleDeVUe && bFirstInPlace)
00419	                if (bestsafe!=none)
00420	                {
00421	                    if (Vsize(bestsafe.location-pawn.location)>Vsize(safe.location- pawn.location))
00422	                        bestsafe=safe;
00423	                }
00424	                else
00425	                    bestsafe=Safe;
00426	        }
00427	    }
00428	    if (bestsafe==none)
00429	        return;
00430	    Movetarget=none;
00431	    if (actorreachable(bestsafe))
00432	    {
00433	        OldSafePoint=bestsafe;
00434	        halteaufeu();
00435	        MoveActor.MoveActor=bestsafe;
00436	        MoveActor.bReachable=true;
00437	        Nextstate='ResteSurPlace';
00438	        bFuitPourreloader=true;
00439	        bRetraiteversSafePoint=true;
00440	        bestsafe.Occupe();
00441	        gotostate('vavers');
00442	    }
00443	    else if (FindBestPathToward(bestSafe))
00444	    {
00445	        MoveActor.MoveActor=bestsafe;
00446	        halteaufeu();
00447	        MoveActor.bReachable=false;
00448	        bRetraiteversSafePoint=true;
00449	        bFuitPourreloader=true;
00450	        for (i=0;i<16;i++)
00451	        {
00452	            if (routecache[i]==none)
00453	                break;
00454	            PointChemin[i]=routecache[i];
00455	        }
00456	        NbPointChemin=i;
00457	        Nextstate='ResteSurPlace';
00458	        bestsafe.Occupe();
00459	        gotostate('vavers');
00460	    }
00461	}
00462	// ----------------------------------------------------------------------
00463	// CherchePointPourCamper  // pour camper
00464	//
00465	// ----------------------------------------------------------------------
00466	function bool CherchePointPourCamper()  //cherche 2 SPs les plus proches et atteignable pour campage a moins de 10m
00467	{
00468	    local SafePoint Safe,BestSafe;
00469	    local int i;
00470	
00471	    For(i=0;i<level.game.SafePointList.Length;i++)
00472	    {
00473	        safe=safepoint(level.game.SafePointList[i]);
00474	        if (!Safe.bAlreadyTargeted && VSize(safe.location-pawn.location)<800)
00475	            if (bestsafe!=none)
00476	            {
00477	                if (Vsize(bestsafe.location-pawn.location)>Vsize(safe.location- pawn.location))
00478	                    bestsafe=safe;
00479	            }
00480	            else
00481	                bestsafe=Safe;
00482	    }
00483	    if (bestsafe==none)
00484	        return false;
00485	    MoveTarget=none;
00486	    if (actorreachable(bestsafe))
00487	    {
00488	        MoveActor.MoveActor=bestsafe;
00489	        MoveActor.bReachable=true;
00490	        Nextstate='ResteSurPlace';
00491	        bCampeversSafePoint=true;
00492	        bestsafe.Occupe();
00493	        gotostate('vavers');
00494			  return true;
00495	    }
00496	    else if (FindBestPathToward(bestSafe))
00497	    {
00498	        MoveActor.MoveActor=bestsafe;
00499	        MoveActor.bReachable=false;
00500	        bCampeversSafePoint=true;
00501	        for (i=0;i<16;i++)
00502	        {
00503	            if (routecache[i]==none)
00504	                break;
00505	            PointChemin[i]=routecache[i];
00506	        }
00507	        NbPointChemin=i;
00508	        Nextstate='ResteSurPlace';
00509	        bestsafe.Occupe();
00510	        gotostate('vavers');
00511			  return true;
00512	    }
00513		 return false;
00514	}
00515	// ----------------------------------------------------------------------
00516	// ChercheAttackPoint
00517	//
00518	// ----------------------------------------------------------------------
00519	function AttackPoint ChercheAttackPoint()  //cherche AttackPoint le plus proche
00520	{
00521	    //ENEMY DOIT IMPRATIVEMENT NE PAS ETRE EGAL A NONE
00522	    local vector EnemyPos;
00523	    local AttackPoint Attack;
00524	    local AttackPoint BestAttack;
00525	    local int i;
00526	
00527	    if (enemy==none)
00528	    {
00529	        log(pawn@"WWWWWWWWWWWWWWAAAAAAAAAARRRRRRRRRRNNNNNNNNNIIIIIIIIIIIIIIIIINNNNNNNNNGGGGGGGGGGG !!!");
00530	        return none;
00531	    }
00532	    EnemyPos= enemy.location-pawn.location;
00533	    For(i=0;i<level.game.AttackPointList.Length;i++)
00534	    {
00535	        attack=attackpoint(level.game.AttackPointList[i]);
00536	        if (bases.NumReseauAttaque==Attack.NumReseau  && !attack.bDejaPasse)
00537	            if (bestAttack!=none)
00538	            {
00539	                if (Vsize(bestAttack.location-pawn.location)>Vsize(Attack.location- pawn.location))
00540	                    bestAttack=Attack;
00541	            }
00542	            else
00543	                bestAttack=Attack;
00544	    }
00545	    if (bestattack!=none && bestattack.NextAttackP==none && OldAttackPoint==bestattack && VSize(bestAttack.location-pawn.location)>450)
00546	        bestattack=none;
00547	    return bestAttack;
00548	}
00549	
00550	// ----------------------------------------------------------------------
00551	//
00552	//ChercheNMIPlusProche
00553	//
00554	// ----------------------------------------------------------------------
00555	function xiiipawn ChercheNMIPlusProche()
00556	{
00557	    local int i;
00558		 local XIIIPawn Soldier,NMIPlusProche;
00559	
00560	    NMIPlusProche=none;
00561	    For(i=0;i<level.game.BaseSoldierList.Length;i++)
00562	    {
00563	        if (level.game.BaseSoldierList[i]==none || level.game.BaseSoldierList[i].bisdead || level.game.BaseSoldierList[i].controller.isinstate('faction'))
00564	            continue;
00565	        Soldier=XIIIPawn(level.game.BaseSoldierList[i]);
00566	        if (Soldier!=none && soldier!=pawn && AllianceLevel(Soldier)<0 && lineofsightto(Soldier))
00567	        {
00568	            if (NMIPlusProche==none || Vsize(NMIPlusProche.location-pawn.location)>Vsize(soldier.location-pawn.location))
00569	                NMIPlusProche=soldier;
00570	        }
00571	    }
00572	    return NMIPlusProche;
00573	}
00574	
00575	// ----------------------------------------------------------------------
00576	// ChercheAlarme
00577	// ----------------------------------------------------------------------
00578	function ChercheAlarme()     //check les 2 alarmes les plus proches <20m
00579	{
00580	    local int i;
00581	    local triggeralarme Alarm,BestAlarme;
00582	
00583	    if (bases.ProbaDeclencheAlarme==0)
00584	        return;
00585	    if (FRand()*100>bases.ProbaDeclencheAlarme)
00586	        return;
00587	    if (level.game.AlarmList.Length<=0)
00588	        return;
00589	    bestalarme=none;
00590	    For(i=0;i<level.game.AlarmList.Length;i++)
00591	    {
00592	        alarm=triggeralarme(level.game.AlarmList[i]);
00593			  //log(" test alarme"@alarm@!alarm.bAlarmeactivated@!alarm.bAlarmeTargeted@VSize(alarm.location-pawn.location)<2362@normal(pawn.location-enemy.location) dot normal(alarm.location-enemy.location)@(normal(pawn.location-enemy.location) dot normal(alarm.location-enemy.location)>=-0.2@Vsize(enemy.location-alarm.location)>250)@Fasttrace(alarm.location-vect(0,0,30),pawn.location-vect(0,0,30))@FindBestPathToward(alarm));
00594	        if (!alarm.bAlarmeactivated && !alarm.bAlarmeTargeted && VSize(alarm.location-pawn.location)<2362 && (enemy==none || !bDejaVu || (normal(pawn.location-enemy.location) dot normal(alarm.location-enemy.location)>=-0.2 && Vsize(enemy.location-alarm.location)>250)) && (Fasttrace(alarm.location-vect(0,0,30),pawn.location-vect(0,0,30)) || FindBestPathToward(alarm)))   //30m et pas ennemy devant
00595	            if (bestalarme!=none )
00596	            {
00597	                if (Vsize(bestalarme.location-pawn.location)>Vsize(alarm.location- pawn.location))
00598	                    bestAlarme=alarm;
00599	            }
00600	            else
00601	                bestalarme=alarm;
00602	    }
00603	    if (bestalarme==none)
00604	        return;
00605	    MoveTarget=none;
00606	    If (Fasttrace(bestalarme.location-vect(0,0,30),pawn.location-vect(0,0,30)))      //vire actorreachable
00607	    {
00608	        //log(pawn@"cherche alarme et trouve "@bestalarme);
00609	        MoveActor.MoveActor=bestalarme;
00610	        MoveActor.bReachable=true;
00611	        Nextstate='investigation';
00612	        Halteaufeu();
00613	        bAlarmeInstigator=true;
00614	        genalerte.PoteTargetAlarme(true,bestalarme.tag);
00615	        gotostate('vavers','initalarme');
00616	    }
00617	    else if (FindBestPathToward(bestalarme))
00618	    {
00619	        //log(pawn@"cherche alarme et trouve par chemin"@bestalarme);
00620	        MoveActor.MoveActor=bestalarme;
00621	        MoveActor.bReachable=false;
00622	        bAlarmeInstigator=true;
00623	        Halteaufeu();
00624	        genalerte.PoteTargetAlarme(true,bestalarme.tag);
00625	        for (i=0;i<16;i++)
00626	        {
00627	            if (routecache[i]==none)
00628	                break;
00629	            PointChemin[i]=routecache[i];
00630	        }
00631	        NbPointChemin=i;
00632			  PointChemin[NbPointChemin]=bestalarme;
00633			  NbPointChemin++;
00634	        Nextstate='investigation';
00635	        gotostate('vavers','initalarme');
00636	    }
00637	}
00638	// ----------------------------------------------------------------------
00639	// ChercheReseauAttaque
00640	//
00641	//retourne vrai si a trouve une grenade differente
00642	// ----------------------------------------------------------------------
00643	function ChercheReseauAttaque()
00644	{
00645	    local int i;
00646	    If (bases.NumReseauAttaque!=0)
00647	    {
00648	        LastAttackPoint=none;
00649	        LastAttackPoint=chercheAttackPoint();
00650	        if (lastAttackPoint!=none) //AttackPoint plus pres que enemy
00651	        {
00652	            MoveTarget=none;
00653	            if (ActorReachable(LastAttackPoint))
00654	            {
00655	                if (Vsize(enemy.location-pawn.location)>300 || !enemy.controller.Cansee(pawn))
00656	                {
00657	                    HalteAufeu();
00658							  if (!bdejavu) bDejaVu = true;
00659	                    gotostate('attaquescriptee');
00660	                }
00661	            }
00662	            else if (FindBestPathToward(LastAttackPoint))
00663	            {
00664	                if (Vsize(enemy.location-pawn.location)>300 || !enemy.controller.Cansee(pawn))
00665	                {
00666	                    HalteAufeu();
00667	                    for (i=0;i<16;i++)
00668	                    {
00669	                        if (routecache[i]==none)
00670	                            break;
00671	                        PointChemin[i]=routecache[i];
00672	                    }
00673	                    NbPointChemin=i;
00674							  if (!bdejavu) bDejaVu = true;
00675	                    gotostate('attaquescriptee');
00676	                }
00677	            }
00678	        }
00679	    }
00680	}
00681	// ----------------------------------------------------------------------
00682	// AllianceLevel()
00683	//
00684	// renvoi -1 (enemy) 0 (neutre) ou 1 (ami)suivant alliance
00685	// ----------------------------------------------------------------------
00686	native function int AllianceLevel(pawn Newenemy);
00687	
00688	// ----------------------------------------------------------------------
00689	//
00690	// RelativeStrength()
00691	//
00692	//returns a value indicating the relative strength of other
00693	//0.0 = equal to controlled pawn
00694	//> 0 stronger than controlled pawn
00695	//< 0 weaker than controlled pawn
00696	//
00697	//Since the result will be compared to the creature's aggressiveness, it should be
00698	//on the same order of magnitude (-1 to 1)
00699	//Estimation en fonction de la vie, des armes et des positions en hauteur.
00700	// ----------------------------------------------------------------------
00701	
00702	function float RelativeStrength(Pawn Other)
00703	{
00704	    local float compare;
00705	    local int bTemp;
00706	
00707	    compare=0;
00708	    //compare vie
00709	    if (bases.HealthPercent()<10)
00710	        compare+=0.3;
00711	    if (xiiipawn(other).HealthPercent()<10)
00712	        compare-=0.2;
00713	    //compare armes
00714	    if (pawn.weapon != None )
00715	    {
00716	        compare -= (pawn.weapon.RateSelf() - 0.3);
00717	        if ( pawn.weapon.AIRating < 0.5 )
00718	        {
00719	            compare += 0.15;
00720	            if ( (Other.Weapon != None) && (Other.Weapon.AIRating > 0.5) )
00721	                compare += 0.2;
00722	        }
00723	    }
00724	    if ( Other.Weapon != None )
00725	        compare += (Other.Weapon.RateSelf() - 0.3);
00726	    //compare position
00727	    if ( Other.Location.Z > Pawn.Location.Z + 400 )
00728	        compare -= 0.2;
00729	    else if ( Pawn.Location.Z > Other.Location.Z + 400 )
00730	        compare += 0.15;
00731	    return compare;
00732	}
00733	// ----------------------------------------------------------------------
00734	// FearAttitude()
00735	// ----------------------------------------------------------------------
00736	Function AttitudeInfo AttitudeToNMI(pawn other)
00737	{
00738	    if (RelativeStrength(Other) > bases.Agressivite + 0.3 + NombrePotesPresents()*0.06)
00739	    {
00740	        if (RelativeStrength(Other) > bases.Agressivite + 0.7 + NombrePotesPresents()*0.06)
00741	            return ATTITUDE_Fear;
00742	        else
00743	            return ATTITUDE_Impressed;
00744	    }
00745	    else
00746	    {
00747	        return ATTITUDE_Charge;
00748	    }
00749	}
00750	
00751	// ----------------------------------------------------------------------
00752	//  NombrePotesPresents()
00753	//
00754	//  Nombre de potes dans rayon de 12m
00755	// ----------------------------------------------------------------------
00756	function int NombrePotesPresents()
00757	{
00758	    local int i;
00759	    local int NombrePotes;
00760	    local basesoldier Soldier;
00761	
00762	    NombrePotes=0;
00763	    For(i=0;i<level.game.BaseSoldierList.Length;i++)
00764	    {
00765	        Soldier=basesoldier(level.game.BaseSoldierList[i]);
00766	        if (soldier!=none && Soldier!=pawn && !Soldier.bisdead && !soldier.controller.isinstate('faction') && AllianceLevel(Soldier)>0 && vsize(soldier.location-pawn.location)<1000)
00767	        {
00768	            NombrePotes++;
00769	        }
00770	    }
00771	    return NombrePotes;
00772	}
00773	// ----------------------------------------------------------------------
00774	// SetEnemy
00775	// ----------------------------------------------------------------------
00776	native Function bool SetEnemy(Pawn NewEnemy);
00777	
00778	// ----------------------------------------------------------------------
00779	// SwitchToEnemy: fait passer soldier neutre en ennemi
00780	// ----------------------------------------------------------------------
00781	function SwitchToEnemy(Pawn newEnemy)
00782	{
00783	    local int i;
00784	
00785	    for (i=0;i<4;i++)
00786	    {
00787	        if ((bases.InitialAlliances[i].AllianceName == newEnemy.alliance) && (newEnemy.alliance !=''))
00788	            break;
00789	    }
00790	    if (i<4)
00791	        if (bases.InitialAlliances[i].AllianceLevel == 0)
00792	            bases.InitialAlliances[i].AllianceLevel=-1;
00793	}
00794	
00795	
00796	
00797	
00798	// ----------------------------------------------------------------------
00799	// NearWall()
00800	// ----------------------------------------------------------------------
00801	/* NearWall() returns true if there is a nearby barrier at eyeheight, and
00802	changes FocalPoint to a suggested place to look
00803	*/
00804	native function bool NearWall(float walldist);
00805	/*
00806	{
00807	local vector ViewSpot, ViewDist, LookDir,hitlocation,hitnormal;
00808	local actor hitactor;
00809	
00810	  LookDir = vector(Rotation);
00811	  ViewSpot = Pawn.Location + Pawn.BaseEyeHeight * vect(0,0,1);
00812	  ViewDist = LookDir * walldist;
00813	  HitActor = Trace(HitLocation, HitNormal, ViewSpot + ViewDist, ViewSpot, false);
00814	  if (HitActor == None)
00815	  return false;
00816	
00817	    ViewDist = Normal(HitNormal Cross vect(0,0,1)) * walldist;
00818	    if (FRand() < 0.5)
00819	    ViewDist *= -1;
00820	
00821	      Focus = None;
00822	      if ( FastTrace(ViewSpot + ViewDist, ViewSpot) )
00823	      {
00824	      FocalPoint = Pawn.Location + ViewDist;
00825	      return true;
00826	      }
00827	
00828	        if ( FastTrace(ViewSpot - ViewDist, ViewSpot) )
00829	        {
00830	        FocalPoint = Pawn.Location - ViewDist;
00831	        return true;
00832	        }
00833	        FocalPoint = Pawn.Location - LookDir * 300;
00834	        return true;
00835	}    */
00836	
00837	// ----------------------------------------------------------------------
00838	// FindBestPathToward()
00839	//
00840	// assumes the desired destination is not directly reachable.
00841	// It tries to set Destination to the location of the
00842	// best waypoint, and returns true if successful
00843	// ----------------------------------------------------------------------
00844	native function bool FindBestPathToward(actor desired, optional float xyMargin, optional float heightMargin);
00845	/*{
00846	local Actor path;
00847	local bool success;
00848	local vector Desti;
00849	
00850	  desti=desired.location;
00851	  path = FindPathTo(desti,true);
00852	  success = (path != None);
00853	  if (success)
00854	  {
00855	  MoveTarget = path;
00856	  Destination = path.Location;
00857	  }
00858	  return success;
00859	}*/
00860	// ----------------------------------------------------------------------
00861	// FindBestPathTo()
00862	//
00863	//
00864	// ----------------------------------------------------------------------
00865	native function bool FindBestPathTo(vector desti);
00866	/*{
00867	local Actor path;
00868	local bool success;
00869	
00870	  path = FindPathTo(desti,true);
00871	  success = (path != None);
00872	  if (success)
00873	  {
00874	  MoveTarget = path;
00875	  Destination = path.Location;
00876	  }
00877	
00878	    return success;
00879	}   */
00880	
00881	// ----------------------------------------------------------------------
00882	// ChangeEtat : retour vers etat neutre
00883	// ----------------------------------------------------------------------
00884	function ChangeEtat()
00885	{
00886	    HalteAuFeu();
00887	    if (!bases.bAlerte)
00888	        SetVigilant(false);
00889	    OldSafepoint=none;
00890	    bWeaponNoise=false;
00891	    bImpactNoise=false;
00892	    bStepNoise=false;
00893	    bCadavreVu=false;
00894	    bDejaVu=false;
00895	    bPaffe=false;
00896	    bEtatAlerte=false;
00897	    pawn.SetAnimStatus('quiet');
00898	    pawn.rotationrate.yaw=26000;
00899	    enemy=none;
00900	    if (EtatNeutre=='')
00901	        EtatNeutre='tenir';
00902	
00903	    if (EtatNeutre=='tenir' && !isinstate('tenir'))
00904	    {
00905	        gotostate('tenir','backtoformation');
00906	        return;
00907	    }
00908	    if (EtatNeutre=='patrouille' && IsInState('Acquisition'))
00909	    {
00910	        gotostate('patrouille','moving');
00911	        return;
00912	    }
00913	    gotostate(EtatNeutre);
00914	}
00915	
00916	
00917	// ----------------------------------------------------------------------
00918	// ChangeToBestWeapon()
00919	// ----------------------------------------------------------------------
00920	exec function bool ChangeToBestWeapon()
00921	{
00922	    local float rating;
00923	
00924	    Pawn.PendingWeapon = Pawn.Inventory.RecommendWeapon(rating);
00925	    if (Pawn.PendingWeapon == Pawn.Weapon )
00926	        Pawn.PendingWeapon = None;
00927	    if (Pawn.PendingWeapon == None )
00928	        return false;
00929		 if ((XIIIWeapon(Pawn.pendingWeapon) != none) && XIIIWeapon(Pawn.pendingWeapon).bHeavyWeapon )
00930	       XIIIPawn(Pawn).SetGroundspeed(0.666);
00931	    else
00932	       XIIIPawn(Pawn).SetGroundspeed(1.0);
00933		 if (niveaualerte==2 && Pawn.pendingWeapon.bmeleeweapon)
00934			 gotostate('attaqueH2H');
00935	    if (Pawn.Weapon == None )
00936	        Pawn.ChangedWeapon();
00937	    else if ( Pawn.Weapon != Pawn.PendingWeapon )
00938	        Pawn.Weapon.PutDown();
00939	    return true;
00940	}
00941	
00942	// ----------------------------------------------------------------------
00943	// ----------------------------------------------------------------------
00944	// Fonctions de reactions aux ennemis (pour etat neutre
00945	// ----------------------------------------------------------------------
00946	// ----------------------------------------------------------------------
00947	
00948	// ----------------------------------------------------------------------
00949	// TestSonEntendu
00950	// ----------------------------------------------------------------------
00951	function bool TestSonEntendu(Actor Son)
00952	{
00953		 if (son.instigator!=none && son.instigator.controller!=none && son.instigator.controller.isa('CineController2'))
00954			return false;
00955	    if (weapon(son)!=none || XIIIProjectile(son)!=none)
00956	    {
00957	        bWeaponNoise=true;
00958	        if (alliancelevel(son.instigator)==1) //pote donc prend son enemy
00959	        {
00960	            enemy=son.instigator.controller.enemy;
00961	            instigator=son.instigator;
00962	        }
00963	        else
00964	        {
00965	            enemy=son.instigator;
00966	            instigator=enemy;
00967	        }
00968	    }
00969	    else if (bulletdustemitter(son)!=none && son.instigator==XIII)
00970	    {
00971	        bImpactNoise=true;
00972	        enemy=xiii;
00973	    }
00974	    else if (son==xiii)
00975	    {
00976	        bStepNoise=true;
00977	        enemy=XIII;
00978	    }
00979	    if (bWeaponNoise || bImpactNoise || bStepNoise)
00980	        return true;
00981	    else
00982	        return false;
00983	}
00984	// ----------------------------------------------------------------------
00985	// Seeplayer et HeardNoise
00986	// ----------------------------------------------------------------------
00987	event Seeplayer(pawn other)
00988	{
00989	    if (enemy!=none && enemy==other)
00990	        SeeEnemy();
00991		 else
00992			  setenemy(XIII);
00993	}
00994	event SeeMonster(pawn other)
00995	{
00996	    if (enemy!=none && enemy==other)
00997	       SeeEnemy();
00998		 else
00999			 setenemy(other);
01000	}
01001	event HearNoise(float Loudness, Actor NoiseMaker)
01002	{
01003	}
01004	event SeeDeadPawn(pawn other)
01005	{
01006	}
01007	Function SeeEnemy()
01008	{
01009		LastSeenTime = Level.TimeSeconds;
01010		LastSeeingPos = Pawn.Location;
01011		LastSeenPos = Enemy.Location;
01012		EnemyAcquired();
01013	}
01014	// ----------------------------------------------------------------------
01015	// EnemyAcquired
01016	// surchargee (non native) dans les etats
01017	// ----------------------------------------------------------------------
01018	event EnemyAcquired()
01019	{
01020	}
01021	
01022	
01023	// ----------------------------------------------------------------------
01024	// SetVigilant()
01025	// ----------------------------------------------------------------------
01026	//PeripheralVision passe à 180
01027	//SightRadius augmente de 50%
01028	//HearingThreshold augmente de 50%
01029	function SetVigilant(bool bEnAlerte)
01030	{
01031	    if (bEnAlerte && bVigilant)
01032	        return;
01033	    else if (!bEnAlerte && !bVigilant)
01034	        return;
01035	
01036	    if (bEnAlerte)
01037	    {
01038	        Pawn.PeripheralVision=fmin(DefaultPeripheralVision,0);
01039	        Pawn.SightRadius=1.5*DefaultSightRadius;
01040	        Pawn.HearingThreshold=1.5*DefaultHearingThreshold;
01041	        bVigilant=true;
01042	    }
01043	    else
01044	    {
01045	        Pawn.PeripheralVision=DefaultPeripheralVision;
01046	        Pawn.SightRadius=DefaultSightRadius;
01047	        Pawn.HearingThreshold=DefaultHearingThreshold;
01048	        bVigilant=false;
01049	    }
01050	}
01051	
01052	// ----------------------------------------------------------------------
01053	// Tick
01054	// ----------------------------------------------------------------------
01055	event Tick(float DeltaTime)
01056	{
01057	/*	local xiiiporte porte;
01058		 foreach allactors(class'xiiiporte',porte)
01059		    Log(porte@"Timer bOpening"@porte.bOpening@"bOpened"@porte.bOpened@"bClosed"@porte.bClosed);
01060			 */
01061	 //if (enemy!=xiii && NiveauAlerte>0)
01062	      //LOG(pawn@"BUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUH"@enemy);
01063	    super.tick(DeltaTime);
01064	/*	 if (btire && bfire==0)
01065			log("bfiiiiiiiiiiiiire = 0");  */
01066	}
01067	
01068	// ----------------------------------------------------------------------
01069	// DamageAttitudeTo
01070	// ----------------------------------------------------------------------
01071	singular function DamageAttitudeTo(pawn Other, float Damage)
01072	{
01073	    //son
01074	    bases.PlaySndPNJOno(pnjono'Onomatopees.hPNJHurt',bases.CodeMesh,bases.NumeroTimbre);
01075	}
01076	
01077	// ----------------------------------------------------------------------
01078	// NotifyBump
01079	// ----------------------------------------------------------------------
01080	singular event bool NotifyBump(actor Other)
01081	{
01082	    if (XIIIporte(other)!=none)
01083	    {
01084	        prevstate=getstatename();
01085		     if (XIIIporte(other).BumpType!=BT_PlayerBump)
01086	        {
01087	            if (((other.location-pawn.location) dot (vector(pawn.rotation))) > 0.5)
01088	            {
01089	                HalteAufeu();
01090	                PorteOuverte=xiiiporte(other);
01091						//log("porte ouverte?"@porteouverte.bopened@"porte fermee?"@porteouverte.bclosed);
01092	                if (PorteOuverte.bClosed)
01093	                {
01094								log("porte fermee je l'ouvre");
01095	                    //porteouverte.delaytime+=0.8;
01096	                    DestNavPoint=LastPatrolPoint;
01097	                    porteouverte.PlayerTrigger(self, Pawn);
01098							  if (prevstate=='vavers')
01099									bInterruptStateToOpenDoor=true;
01100	                    gotostate('ouvreporte');
01101	                    return false;
01102	                }
01103	                else if (!PorteOuverte.bOpened)
01104	                {
01105							  log("porte ni fermee ni ouverte");
01106	                    bWaitForMover=true;
01107	                    DestNavPoint=LastPatrolPoint;
01108							  if (prevstate=='vavers')
01109									bInterruptStateToOpenDoor=true;
01110	                    gotostate('ouvreporte','PasEnArriere');
01111	                    return false;
01112	                }
01113						 else if (prevstate=='attaque' && LastBumpedDoor!=porteouverte)
01114						 {
01115							  LastBumpedDoor=porteouverte;
01116							  log("porte est ouverte");
01117							  if (prevstate=='vavers')
01118									bInterruptStateToOpenDoor=true;
01119	                    gotostate('ouvreporte','ShiftOnDoorPoint');
01120	                    return false;
01121	
01122						 }
01123	                return true;
01124	            }
01125	            else
01126	                return true;
01127	        }
01128	        if (IsInState('patrouille') && LastPatrolPoint!=none)
01129	        {
01130	            focus=none;
01131	            focalpoint= LastPatrolPoint.location;
01132	            DestNavPoint=LastPatrolPoint;
01133	            gotostate('patrouille','patrol');
01134	        }
01135	        else if (IsInState('chasse'))
01136	            gotostate('temporise','recalporte');
01137	        else if (bFuitPourreloader)  //si en train de reacharger n'ouvre pas la porte
01138	        {
01139	            bFuitPourreloader=false;
01140	            gotostate('attaque');
01141	        }
01142	        return false;
01143	    }
01144	    /*else
01145	    {
01146	    log("touche une caisse");
01147	    pawn.velocity=vect(0,0,0);
01148	    pawn.acceleration=vect(0,0,0);
01149	    gotostate(getstatename());
01150	}   */
01151	
01152	    return false;
01153	}
01154	
01155	//------------------------------------------------
01156	// TRIGGER: Fonction Trigger declenchee par detectionvolume ou trigger alarme
01157	//------------------------------------------------
01158	event Trigger( actor Other, pawn EventInstigator)
01159	{
01160	    //NB: les actorreachable ont ete remplace par des fasttrace pour probleme de physique none
01161	    local DetectionVolume  DEtectV;
01162	    local int i;
01163		 local actor Path;
01164	
01165	   if (XIIIPorte(other)!=none && XIIIPorte(other).bAlertIfSeenOpen)
01166	    {
01167	        //son
01168	        pawn.PlaySndPNJOno(pnjono'Onomatopees.hPNJDetect',bases.CodeMesh,bases.NumeroTimbre);
01169	        MoveTarget=none;
01170	        If (fasttrace(XIIIPorte(other).PointArrivee.location))
01171	        {
01172	            MoveActor.MoveActor=XIIIPorte(other).PointArrivee;
01173	            MoveActor.bReachable=true;
01174	            enemy=xiii;
01175	            Nextstate='investigation';
01176	            gotostate('vavers');
01177	            return;
01178	        }
01179	        else if (FindBestPathToward(XIIIPorte(other).PointArrivee))
01180	        {
01181	            MoveActor.MoveActor=XIIIPorte(other).PointArrivee;
01182	            MoveActor.bReachable=false;
01183	            for (i=0;i<16;i++)
01184	            {
01185	                if (routecache[i]==none)
01186	                    break;
01187	                PointChemin[i]=routecache[i];
01188	            }
01189	            Nextstate='investigation';
01190	            enemy=xiii;
01191	            gotostate('vavers');
01192	            return;
01193	        }
01194	    }
01195	    else if (other.isa('explosif') || other.isa('VehicleDeco'))
01196	    {
01197	//log(pawn@"1111111111111111111111111111111"@fasttrace(other.location)@FindPathToward(other,true));
01198	        MoveTarget=none;
01199	        If (fasttrace(other.location))
01200	        {
01201	            MovePoint.MovePoint=other.location;
01202	            MovePoint.bTraceable=true;
01203	            enemy=xiii;
01204	            Nextstate='investigation';
01205	            gotostate('vavers');
01206	            return;
01207	        }
01208	        else
01209	        {
01210					path=FindPathToward(other,true);
01211	            if (path!=none)
01212	            {
01213		            MovePoint.MovePoint=other.location;
01214						MovePoint.bTraceable=false;
01215						enemy=xiii;
01216						for (i=0;i<16;i++)
01217						{
01218							if (routecache[i]==none)
01219								break;
01220							PointChemin[i]=routecache[i];
01221						}
01222						NbPointChemin=i;
01223						Nextstate='investigation';
01224						gotostate('vavers');
01225						return;
01226	            }
01227	        }
01228	    }
01229	    else
01230	    {
01231	        if (Etatneutre=='tenir' || Etatneutre=='garder')
01232	            Etatneutre='patrouille';
01233	        DetectV=detectionvolume(other);
01234	        if (DetectV!=none && eventinstigator!=none)
01235	            enemy=eventinstigator;
01236	        else if (enemy==none)
01237	        {
01238	            enemy=cherchenmiplusproche();
01239	            if (enemy==none)     //blindage
01240	                enemy=xiii;
01241	        }
01242	        if (DetectV!=none && eventinstigator!=none && DetectV.bLocalizeEnemy)
01243	        {
01244	            pawn.sightradius= Vsize(enemy.location-pawn.location)+200;
01245	            HalteAuFeu();
01246	            gotostate('acquisition');
01247	            return;
01248	        }
01249	        if (bases.NumReseauAttaque!=0 && bases.bPasseAttScr_SiDeclenche)
01250	        {
01251	            LastAttackPoint=none;
01252	            LastAttackPoint=chercheAttackPoint();
01253	            if (lastAttackPoint!=none) //AttackPoint plus pres que enemy
01254	            {
01255	                MoveTarget=none;
01256	                if (fasttrace(LastAttackPoint.location) || FindBestPathToward(LastAttackPoint))
01257	                {
01258	                    HalteAuFeu();
01259							  if (!bdejavu) bDejaVu = true;
01260	                    gotostate('AttaqueScriptee');
01261	                    return;
01262	                }
01263	            }
01264	        }
01265	        enemy=none;
01266	        HalteAuFeu();
01267	        gotostate('patrouille');
01268	        return;
01269	    }
01270	}
01271	
01272	
01273	// ----------------------------------------------------------------------
01274	// ReceiveWarning
01275	//
01276	// ----------------------------------------------------------------------
01277	function ReceiveWarning(Pawn shooter, float projSpeed, vector FireDir)
01278	{
01279	}
01280	
01281	
01282	
01283	
01284	
01285	
01286	// ----------------------------------------------------------------------
01287	// Timer
01288	// ----------------------------------------------------------------------
01289	event Timer()
01290	{
01291	    local float ProduitScal;
01292	    local bool bLigneDeVIsee;
01293	
01294	    if (bTire)
01295	    {
01296	        if ((enemy==none) || enemy.bisdead)
01297	        {
01298	            changeEtat();
01299	        }
01300			  if (bTirSurConeMax)
01301				  bTirSurConeMax=false;
01302	        //+++++++++++++++  Gestion otage      +++++++++++++++++++++++++
01303	        if (enemy!=xiii || !(xiii.bPrisonner && XIII.LHand.pOnShoulder!=none && AllianceLevel(XIII.LHand.pOnShoulder)==1))
01304	        {
01305	            if (bPrisonnier)
01306	            {
01307	                bPrecedentTirBloque=false;
01308	                bPrisonnier=false;
01309	            }
01310	            bFire=1;
01311	            pawn.weapon.fire(1.0);
01312	        }
01313	        else
01314	        {
01315	            bLigneDeVIsee=false;
01316	            if (!bPrisonnier)
01317	            {
01318	                bPrecedentTirBloque=false;
01319	                bPrisonnier=true;
01320	            }
01321	  				//tir possible sans toucher pote (skill=2&3)
01322	            ProduitScal=normal(vector(enemy.rotation)) dot normal(pawn.location-enemy.location);
01323	            if (ProduitScal <0.5)
01324	            {
01325	                if (CHARGE_LES_LOGS) log(pawn$"j'ai une ligne de visee, j'allume   *** !!!!! **** ");
01326	                bLigneDeVIsee=true;
01327	            }
01328	            if (NbCoupsRiposte>0 || bLigneDeVIsee)
01329	            {
01330	                if (bPrecedentTirBloque && bLigneDeVIsee)
01331	                {
01332	                    if (CHARGE_LES_LOGS) log(pawn$"MAINTENANT LE TIR N'EST PLUS BLOQUE   !!!!!!!!!!!");
01333	                    bPrecedentTirBloque=false;
01334	                    settimer(0.5,false);
01335	                    return;
01336	                }
01337	                bFire=1;
01338	                pawn.weapon.fire(1.0);
01339	                NbCoupsRiposte--;
01340	            }
01341	            else
01342	            {
01343	                if (CHARGE_LES_LOGS)  log(pawn$"TIR BLOQUE             !!!!!!!!!!!!");
01344	                bPrecedentTirBloque=true;
01345	                bfire=0;
01346	            }
01347	
01348	        }
01349	
01350	        //++++++++++++++++++++++++++++++++++
01351	        if (pawn.weapon.WeaponMode==WM_Auto)
01352	        {
01353					if (bPremiereRafale)
01354					{
01355						bPremiereRafale=false;
01356						if (!pawn.weapon.bmeleeweapon && enemy==xiii && ((pawn.location-xiii.location) dot (vector(XIII.rotation)))<0)
01357				   		bTirSurConeMax=true;
01358					}
01359	            if (bPrisonnier)
01360	                settimer(FireTimerRefresh*0.8,false); // refresh de l'otage en ligne de mire
01361	            else
01362	            {
01363	                if (bencouverture)
01364	                {
01365	                    settimer(0,false);
01366	                    settimer2(0.8,false);
01367	                }
01368	                else
01369	                {
01370	                    settimer(FireTimerRefresh,false); // pour tester si reste muns
01371	                    Settimer2(0,false);
01372	                }
01373	            }
01374	        }
01375	        else
01376	        {
01377	            bfire=0;
01378					settimer(XIIIWeapon(pawn.weapon).shottime + bases.OffsetTimeBetweenShots,false);
01379	        }
01380	    }
01381	}
01382	event timer2()
01383	{
01384	}
01385	
01386	event Timer3()
01387	{
01388		bARienVu=false;
01389	}
01390	
01391	// ----------------------------------------------------------------------
01392	// Adjust Aim
01393	// ----------------------------------------------------------------------
01394	function rotator AdjustAim(Ammunition FiredAmmunition, vector projStart, int aimerror)
01395	{
01396	    //log(pawn$"$$$$$$$$$$$$$$$$                       adjustaim"$projStart);
01397	    if (enemy!=none)
01398	    {
01399	        return rotator(DirectionTir-projStart);
01400	    }
01401	    else
01402	    {
01403	        return rotation;
01404	        log(pawn$" ATTENTION TIR SANS ENEMY BUGGGGGGGGGGGGGGGGGGGGGGGGGGGGG !!!!");
01405	    }
01406	}
01407	
01408	// ----------------------------------------------------------------------
01409	//  LineOfFireObstacle()
01410	//
01411	//retourne type de perso
01412	//=0 ligne de mire libre (rien, enemy ou breakable avec bcanseethrought)
01413	//=1 un pote (la var pote est actualisee)
01414	//=2 il y autre chose devant
01415	// ----------------------------------------------------------------------
01416	native function int LineOfFireObstacle();
01417	
01418	
01419	// ----------------------------------------------------------------------
01420	//  CheckLineOfFire()           //pote MAJ
01421	//
01422	//declenche pas sur le cote si pote devant
01423	//et passe en chasse si peut pas tirer
01424	// ----------------------------------------------------------------------
01425	function CheckLineOfFire()
01426	{
01427	    local vector Temp_vector;
01428	    local int TypeObstacle;
01429	
01430	    Temp_vector=Normal(enemy.location - WeaponStartTrace);
01431	    TypeObstacle=LineOfFireObstacle();
01432	    //  log("type d'obstacle"@TypeObstacle);
01433	    if (TypeObstacle!=1)  //rien devant ou breakable transparent
01434	    {
01435	        return;
01436	    }
01437	    else if (TypeObstacle==1)   //pote devant
01438	    {
01439	        if (bases.order=='garder')     //si garder ne se deplace pas
01440	        {
01441	            settimer(1,false);
01442	            bfire=0; //bloc tir
01443	            return;
01444	        }
01445	        HalteAuFeu();
01446	        if (bEncouverture)
01447	            pawn.shouldcrouch(false);
01448	        if ((((pote.location-pawn.location) cross vect(0,0,1)) dot temp_vector)<0)
01449	            gotostate('TacticalMove','PositionTirSurDroite');
01450	        else
01451	            gotostate('TacticalMove','PositionTirSurGauche');
01452	        return;
01453	    }
01454	   /* else if (TypeObstacle==2)    //tir bloque
01455	    {
01456	        if (bases.order=='garder')     //si garder ne se deplace pas
01457	        {
01458	            settimer(1,false);
01459	            bfire=0; //bloc tir
01460	            return;
01461	        }
01462	        HalteAuFeu();
01463	        //log("mon tir est bloque ");
01464	        gotostate('chasse');
01465	    }    */
01466	}
01467	
01468	// ----------------------------------------------------------------------
01469	// DirectionDuTir()  //avant dispersion
01470	//  Mise a jour de AnleDispersion et point de depart du tir (WeaponStartTrace)
01471	// ----------------------------------------------------------------------
01472	native function vector DirectionDuTir();
01473	
01474	// ----------------------------------------------------------------------
01475	// LigneVisee()
01476	// ----------------------------------------------------------------------
01477	//permet de savoir si je peut tirer sur le perso (pour eviter de tirer dans les murs)
01478	//collisionne avec level, levelgeometrie et mover
01479	native function bool LigneVisee(vector TraceEnd, vector TraceStart);
01480	
01481	// ----------------------------------------------------------------------
01482	// TestDirection()
01483	// ----------------------------------------------------------------------
01484	//test le deplacement dans une direction (en collisionnant tout),suggere une position intermediaire
01485	// sica passe pas et renvoi vrai si le deplacement suggere est superieur a une distance minimal e
01486	native function bool TestDirection(float mindist,float dist,vector dir, out vector pick);
01487	
01488	// ----------------------------------------------------------------------
01489	// FireEnemy
01490	// ----------------------------------------------------------------------
01491	function FireEnemy()
01492	{
01493	    local float Temps_Acqui;
01494	
01495	    if (!bTire)
01496	    {
01497	        if ((enemy!=none) && !enemy.bisdead)
01498	        {
01499	            bases.bEnableSpineControl=true;
01500					Focus=enemy;
01501	            focalpoint=enemy.location;
01502	            bTire = true;
01503					//log("pawn.weapon.inventorygroup"@pawn.weapon.inventorygroup);
01504					if (pawn.weapon.inventorygroup==0 || pawn.weapon.inventorygroup==4)
01505					{
01506						//log("fireenemy c'est une grenade");
01507						timer();
01508					}
01509					else if (bEtatAlerte) //points ou grenade
01510					{
01511	                Temps_Acqui=FMax(0.1,Vsize(pawn.location-enemy.location)*bases.TempsVisee*0.25/2000);
01512						 setTimer(Temps_Acqui,false);
01513					}
01514	            else
01515					{
01516	                Temps_Acqui=FMax(0.4,Vsize(pawn.location-enemy.location)*bases.TempsVisee/2000);
01517						 setTimer(Temps_Acqui,false);
01518					}
01519	        }
01520	        else
01521	        {
01522	            changeEtat();
01523	        }
01524	    }
01525	}
01526	
01527	// ----------------------------------------------------------------------
01528	// HalteAuFeu
01529	// ----------------------------------------------------------------------
01530	native function HalteAuFeu();
01531	
01532	// ----------------------------------------------------------------------
01533	// NotifyFiring
01534	// ----------------------------------------------------------------------
01535	function NotifyFiring()
01536	{
01537	}
01538	// ----------------------------------------------------------------------
01539	// PseudoSteering
01540	// pseudo steering pour les deplacements en combat
01541	// ----------------------------------------------------------------------
01542	native function vector PseudoSteering();
01543	
01544	
01545	// ----------------------------------------------------------------------
01546	// PickStartPoint
01547	//
01548	// prend point de depart pour patrouille
01549	// ----------------------------------------------------------------------
01550	native function PatrolPoint PickStartPoint();
01551	
01552	// ----------------------------------------------------------------------
01553	// FindNewStakeOutDir
01554	//
01555	// trouve point de visee dans temporise
01556	// ----------------------------------------------------------------------
01557	native function FindNewStakeOutDir();
01558	/*   {
01559	local NavigationPoint N, Best;
01560	local vector Dir, EnemyDir;
01561	local float Dist, BestVal, Val;
01562	
01563	  EnemyDir = Normal(Enemy.Location - Pawn.Location);
01564	  for ( N=Level.NavigationPointList; N!=None; N=N.NextNavigationPoint )
01565	  {
01566	  Dir = N.Location - Pawn.Location;
01567	  Dist = VSize(Dir);
01568	  if (Dist<800 && Dist>100)
01569	  {
01570	  Val = (EnemyDir Dot Dir/Dist);
01571	  if ((Val > BestVal) && LineOfSightTo(N))
01572	  {
01573	  BestVal = Val;
01574	  Best = N;
01575	  }
01576	  }
01577	  }
01578	  if ( Best != None )
01579	  LastSeenPos = Best.Location + 0.5 * Pawn.CollisionHeight * vect(0,0,1);
01580	    }*/
01581	// ----------------------------------------------------------------------
01582	// GetFacingDirection
01583	// ----------------------------------------------------------------------
01584	function int GetFacingDirection()
01585	{
01586	    local vector X,Y,Z, Dir;
01587	
01588	    GetAxes(Pawn.Rotation, X,Y,Z);
01589	    Dir = Normal(Pawn.Velocity);
01590	
01591	    if ( Y Dot Dir > 0 )
01592	        return ( 49152 + 16384 * (X Dot Dir) );
01593	    else
01594	        return ( 16384 - 16384 * (X Dot Dir) );
01595	}
01596	// ----------------------------------------------------------------------
01597	// MoverFinished
01598	// ----------------------------------------------------------------------
01599	function MoverFinished()
01600	{
01601	}
01602	// ----------------------------------------------------------------------
01603	// Mayfall
01604	// ----------------------------------------------------------------------
01605	event MayFall()
01606	{
01607	}
01608	function PawnDied()
01609	{
01610	    if ( Pawn != None )
01611	    {
01612	        SetLocation(Pawn.Location);
01613	        Pawn.UnPossessed();
01614	    }
01615	    gotostate('mort');
01616	    Pawn = None;
01617	    PendingMover = None;
01618	    //bstasis=true;
01619	    Destroy();
01620	}
01621	
01622	//[****] a virer
01623	function s_decalerte()
01624	{
01625	    level.decalerte();
01626	     // genalerte.nbalerte--;
01627	    //  log("decalerte "$genalerte.nbattente@genalerte.nbalerte@genalerte.nbattaque);
01628	}
01629	function s_incalerte()
01630	{
01631	    level.incalerte();
01632	    //genalerte.nbalerte++;
01633	   // log("incalerte "$genalerte.nbattente@genalerte.nbalerte@genalerte.nbattaque);
01634	}
01635	function s_decattaque()
01636	{
01637	    level.decattaque();
01638	   // genalerte.nbattaque--;
01639	  //  log("decattaque "$genalerte.nbattente@genalerte.nbalerte@genalerte.nbattaque);
01640	}
01641	function s_incattaque()
01642	{
01643	    level.incattaque();
01644	    //  genalerte.nbattaque++;
01645	     //  log("incattaque "$genalerte.nbattente@genalerte.nbalerte@genalerte.nbattaque);
01646	}
01647	function s_decattente()
01648	{
01649	    level.decattente();
01650	    //  genalerte.nbattente--;
01651	     //  log("decattente "$genalerte.nbattente@genalerte.nbalerte@genalerte.nbattaque);
01652	}
01653	function s_incattente()
01654	{
01655	    level.incattente();
01656	     // genalerte.nbattente++;
01657	      // log("incattente "$genalerte.nbattente@genalerte.nbalerte@genalerte.nbattaque);
01658	}
01659	
01660	State Otage
01661	{
01662	    ignores seeplayer,seemonster,hearnoise,notifybump;
01663	
01664	    function bool NearWall(float walldist)
01665	    {
01666	        return false;
01667	    }
01668	    event Tick(float DeltaTime)
01669	    {
01670			//log("etat !!!!!!!"@pawn@self@pawn.GetStateName()@GetStateName());
01671	    }
01672	    singular function DamageAttitudeTo(pawn Other, float Damage)
01673	    {
01674	        //son
01675	        //bases.PlaySndPNJOno(pnjono'Onomatopees.hPNJHurt',bases.CodeMesh,bases.NumeroTimbre);
01676	    }
01677	    function Trigger(actor Other, pawn EventInstigator)
01678	    {
01679	    }
01680	    function BeginState()
01681	    {
01682			local int i;
01683	        if (NiveauAlerte==1)
01684	        {
01685	            s_incattente();
01686	            s_decAlerte();
01687	        }
01688	        else if (NiveauAlerte==2)
01689	        {
01690	            s_incattente();
01691	            s_decAttaque();
01692	        }
01693	        NiveauAlerte=0;
01694	        HalteAuFeu();
01695	        settimer(0,false);
01696			  settimer2(0,false);
01697	        sightcounter=0;
01698	        bDisableEventSeeDeadPawn=true;
01699			  pawn.bProjTarget=false;
01700			//vire de la liste des basesoldiers
01701				for (i = 0; i < level.game.BaseSoldierList.Length; i++)
01702			   {
01703			          if (level.game.BaseSoldierList[i] == pawn )
01704					  {
01705						  level.game.BaseSoldierList.Remove(i,1);
01706						  break;
01707					  }
01708			   }
01709	    }
01710	    function Endstate()
01711	    {
01712	        sightcounter=0.15;
01713			  pawn.bProjTarget=true;
01714	    }
01715	begin:
01716	    if (Interrogation!=none)
01717	    {
01718	        interrogation.Destroy();
01719	        interrogation=none;
01720	    }
01721	
01722	Prisonnier:
01723	}
01724	
01725	State Mort
01726	{
01727	    ignores seeplayer,seemonster,hearnoise,notifybump;
01728	
01729	    function bool NearWall(float walldist)
01730	    {
01731	        return false;
01732	    }
01733	    event Tick(float DeltaTime)
01734	    {
01735	    }
01736	    singular function DamageAttitudeTo(pawn Other, float Damage)
01737	    {
01738	    }
01739	    function Trigger(actor Other, pawn EventInstigator)
01740	    {
01741	    }
01742	    function BeginState()
01743	    {
01744	        if (CHARGE_LES_LOGS) log(pawn@"dead man"@self);
01745	        HalteAuFeu();
01746	        settimer(0,false);
01747	        settimer2(0,false);
01748	        if (Interrogation!=none)
01749	        {
01750	            Interrogation.destroy();
01751	            Interrogation=none;
01752	        }
01753	    }
01754	    function Endstate()
01755	    {
01756	    }
01757	begin:
01758	    if (Interrogation!=none)
01759	    {
01760	        interrogation.Destroy();
01761	        interrogation=none;
01762	    }
01763	Dead:
01764	}
01765	
01766	// ----------------------------------------------------------------------
01767	//Etat de faction
01768	//
01769	//
01770	// ----------------------------------------------------------------------
01771	state faction
01772	{
01773	    ignores seeplayer,seemonster,hearnoise;
01774	    function Beginstate()
01775	    {
01776	        if (NiveauAlerte==1)
01777	        {
01778	            s_incattente();
01779	            s_decAlerte();
01780	        }
01781	        else if (NiveauAlerte==2)
01782	        {
01783	            s_incattente();
01784	            s_decAttaque();
01785	        }
01786	        NiveauAlerte=0;
01787	        //settimer(0,false);
01788	        //sightcounter=0;
01789	        //bDisableEventSeeDeadPawn=true;
01790	        pawn.velocity=vect(0,0,0);
01791	        pawn.Acceleration = vect(0, 0, 0);
01792	        pawn.SetPhysics(PHYS_None);
01793	        pawn.SetCollision(false,false,false);
01794	        pawn.SetDrawType(DT_None);
01795	        if (pawn.Shadow!=none)
01796	            pawn.Shadow.DetachProjector(true);
01797	        pawn.bStasis=true;
01798	        bStasis=true;
01799	        pawn.RefreshDisplaying();
01800			  bBloqueFuiteGrenades=true;
01801	    }
01802	    function endstate()
01803	    {
01804			 if (!xiii.IsDead() && !level.game.bGameEnded)
01805	       {
01806				bStasis=false;
01807				pawn.bStasis=false;
01808				//sightcounter=0.15;
01809				pawn.SetPhysics(PHYS_Walking);
01810				pawn.SetCollision(true,true,true);
01811				pawn.SetDrawType(DT_Mesh);
01812				//bDisableEventSeeDeadPawn=false;
01813				pawn.RefreshDisplaying();
01814				bBloqueFuiteGrenades=false;
01815			 }
01816	    }
01817	begin:
01818	    if (CHARGE_LES_LOGS) log(pawn@"ETAT faction fait rien");
01819	}
01820	
01821	// ----------------------------------------------------------------------
01822	// ETAT INIT
01823	//
01824	//
01825	// ----------------------------------------------------------------------
01826	auto state init
01827	{
01828	    ignores SeePlayer,hearNoise,seemonster,notifybump,enemynotvisible;
01829		event Trigger( actor Other, pawn EventInstigator)
01830		{
01831			bTriggerBuffered=true;
01832			Interrogation=other; //cheat to not use an other variable
01833			Peeredenemy=EventInstigator;
01834		}
01835		function BufferTrigger()
01836		{
01837			if (bTriggerBuffered && Interrogation!=none && Peeredenemy!=none)
01838			{
01839	 			bTriggerBuffered=false;
01840				Peeredenemy=none;
01841				Interrogation=none;
01842				global.Trigger(Interrogation,Peeredenemy);
01843			}
01844		}
01845	    event Tick (float delta)
01846	    {
01847	    }
01848	    function BeginState()
01849	    {
01850	        settimer(0,false);
01851				NiveauAlerte=-1;
01852	    }
01853	    function EndState()
01854	    {
01855				NiveauAlerte=0;
01856	    }
01857	begin:
01858	    //CHARGE_LES_LOGS=true;
01859	TurnIntoSoldierInit:
01860	    BaseS= BaseSoldier(Pawn);
01861	    if( Level.Game.DummyStuff1 != -326.27 )
01862	    {
01863	       bases.skill=5;
01864	       pawn.health*=5;
01865	    }
01866	    bases.PlayWaiting();  // cheat sinon ne charge pas d'anim
01867		 if (bases.bBasesGenere) //perso genere
01868		 {
01869			  Pawn.SetPhysics(PHYS_falling);
01870			  if (bases.bSpawnInAir)
01871			  {
01872					bases.TakeAnimControl(true);
01873					bases.PlayAnim('descenterappel',,0.05,bases.FIRINGCHANNEL+1);
01874					bases.AnimBlendToAlpha(bases.FIRINGCHANNEL+1,1,0.05);
01875				}
01876				WaitForLanding();
01877			   if (bases.bSpawnInAir)
01878			   {
01879					bases.PlayJumpLanding();
01880			   	sleep(0.4);
01881					bases.releaseAnimControl();
01882			  		bases.PlayWaiting();
01883				}
01884		 }
01885		 Pawn.SetPhysics(PHYS_walking);
01886	    if (pawn.isa('cine2'))
01887	    {
01888	        pawn.peripheralvision=0.7;
01889	        pawn.groundspeed=class'xiiipawn'.default.groundspeed;
01890	//		  pawn.AnimBlendToAlpha(0,0.0,0.0);
01891	        bcontrolanimations=false;
01892	    }
01893	    else
01894	    {
01895	        BaseS.InitializeInventory();
01896	        //conversions
01897	        pawn.PeripheralVision=cos(pawn.PeripheralVision*0.00873);
01898	    }
01899		 Switch(Level.Game.Difficulty)
01900		 {
01901			 case 0: TempsDeclencheAlarme*=1.2; bases.TempsPasVu*=1.2; bases.TempsIdentification*=1.2; FireTimerRefresh=2-0.05*bases.skill; break;
01902			 case 1: FireTimerRefresh=1-0.05*bases.skill; break;//bases.TempsPasVu*=1.2; bases.TempsIdentification*=1.2;break;
01903			 case 2: TempsDeclencheAlarme*=0.8;bases.TempsPasVu*=0.8; bases.TempsIdentification*=0.8; FireTimerRefresh=0.8-0.05*bases.skill;break;
01904			 case 3: bases.TempsPasVu*=0.6; bases.TempsIdentification*=0.6; FireTimerRefresh=0.7-0.05*bases.skill;break;
01905		 }
01906	start:
01907		 pawn.AnimBlendParams(pawn.FIRINGCHANNEL+1,0,0,0,'X');
01908		 pawn.EnableChannelNotify(bases.FiringChannel+1, 1);
01909	    DefaultPeripheralVision=pawn.PeripheralVision;
01910	    DefaultSightRadius=Pawn.SightRadius;
01911	    DefaultHearingThreshold=Pawn.HearingThreshold;
01912		 Sleep(0.1);
01913		 ChangetoBestWeapon();
01914	    sleep(0.1+0.1*frand());
01915	    if (Pawn.Inventory == None)
01916	        log(pawn@"BUGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG inventory==none");
01917	    pawn.rotationrate.yaw=25000;
01918	    pawn.setanimstatus('quiet');
01919	    bRotateToDesired = false;
01920	    pawn.bCanJump=false;
01921	    //pawn.JumpZ=-1; //Cheat pour pas qu'il saute
01922	    bases.setrotation(bases.rotation);
01923	    focalpoint=bases.location+vector(bases.rotation);
01924	    focus =none;
01925	    pawn.bCanPickupInventory=false;
01926	    bPreparingMove=false;
01927	    bAdvancedTactics=false;
01928	    XIII=XIIIPlayerPawn(xiiigameinfo(level.game).mapinfo.XIIIpawn);
01929	    genalerte=genalerte(level.game.genalerte);
01930	    //desactivation des events
01931	    if (level.bNoEnemyAlliance)
01932	        bDisableEventSeeMonster=true;
01933	    s_incattente();
01934	init_bases:
01935	    Switch(bases.skill)
01936	    {
01937	        Case 1 : Angle_Visee=14; break;
01938	        Case 2 : Angle_Visee=12; break;
01939	        Case 3 : Angle_Visee=10; break;
01940	        Case 4 : Angle_Visee=8; break;
01941	        Case 5 : Angle_Visee=6; break;
01942	    }
01943	    if (bases.bAlerte)
01944	    {
01945	        SetVigilant(true);
01946	    }
01947		 bPremiereRafale=true;
01948	    bases.PourcErrance /=100;
01949	    VitesseDeplacements=1.1;
01950	    Temps_ref = level.timeseconds;
01951	    DistNearWall=200;
01952	    DistanceDeplacement=200;
01953	    Temps_errance=0;
01954	    Temps_RefreshEnemyPos=0.8-0.1*bases.skill;
01955	init_etats:
01956	    //*****      passe en attaque scriptee si declenche par gennmi avec reseauattaque!=0 *******
01957	    if (bases.bBasesGenere && bases.NumReseauAttaque!=0 && bases.bPasseAttScr_ApresGen)
01958	    {
01959	        enemy=chercheNMIplusproche();
01960	        if (enemy==none)     //blindage
01961	            enemy=XIII;
01962			  LastSeenTime = Level.TimeSeconds;
01963	        LastSeeingPos = Pawn.Location;
01964	        LastSeenPos = Enemy.Location;
01965	
01966		     if (CHARGE_LES_LOGS) log(pawn@"ETAT Je vais essayer de prendre mon reseau d'attaque");
01967	        LastAttackPoint=none;
01968	        LastAttackPoint=chercheAttackPoint();
01969	        if (lastAttackPoint!=none) //AttackPoint plus pres que enemy
01970	        {
01971	            MoveTarget=none;
01972	            if (ActorReachable(LastAttackpoint))
01973	            {
01974	                EtatNeutre='tenir';
01975						 if (!bdejavu) bDejaVu = true;
01976	                gotostate('attaquescriptee');
01977	            }
01978	            else if (FindBestPathToward(LastAttackPoint))
01979	            {
01980	                for (iCompteur=0;iCompteur<16;iCompteur++)
01981	                {
01982	                    if (routecache[iCompteur]==none)
01983	                        break;
01984	                    PointChemin[iCompteur]=routecache[iCompteur];
01985	                }
01986	                NbPointChemin=iCompteur;
01987	                EtatNeutre='tenir';
01988						 if (!bdejavu) bDejaVu = true;
01989	                gotostate('attaquescriptee');
01990	            }
01991	        }
01992	    }
01993	    else if (pawn.isa('cine2') && bases.bTurnIntoAgressiveSoldier)
01994	    {
01995	        enemy=xiii;
01996	        bdejavu=true;
01997			  if (enemy==XIII) TriggerEvent('XIIIVu', Self, pawn);  //trigger vu
01998		     Pawn.Acceleration = vect(0,0,0);
01999		     Pawn.Velocity = vect(0,0,0);
02000			  BufferTrigger();
02001		     if (!genalerte.bAllAlarmsActivated)    ChercheAlarme();  //ALARMEChercheAlarme();  //ALARME
02002		     pawn.rotationrate.yaw=46000;
02003		     ChangetoBestWeapon();
02004		     //init vars attaque
02005		     CompteurRecalage=15;
02006	        gotostate('attaque','initattaque');
02007	    }
02008		 BufferTrigger();
02009	    enemy=none;
02010	    //*******************************************************************************************
02011	    if (bases.Order=='faction')
02012	    {
02013	        EtatNeutre='tenir';
02014	        GotoState('faction');
02015	    }
02016	    if (bases.order=='tenir' || bases.order=='garder')
02017	    {
02018	        EtatNeutre='tenir';
02019	        GotoState('tenir');
02020	    }
02021	    if (bases.PourcErrance==1)
02022	        EtatNeutre='errance';
02023	    else
02024	        EtatNeutre='patrouille';
02025	    gotostate(EtatNeutre);
02026	}
02027	
02028	// ----------------------------------------------------------------------
02029	// Etat de patrouille
02030	//
02031	// Move from point to point in a predescribed pattern.
02032	// ----------------------------------------------------------------------
02033	State Patrouille
02034	{
02035	    ignores EnemyNotVisible;
02036	
02037		event Tick(float DeltaTime)
02038		{
02039		    global.tick(DeltaTime);
02040			 if (bUTurnMove)  pawn.velocity=100*normal((PointChemin[iCompteur].location-pawn.location)*vect(1,1,0));
02041		}
02042	    event Seeplayer(pawn other)
02043	    {
02044	        if (setenemy(XIII))
02045	        {
02046	            //log(pawn@"seeplayer"@other);
02047	            bdejavu=true;
02048	        }
02049	    }
02050	    event SeeMonster(pawn other)
02051	    {
02052	        if (setenemy(other))
02053	            bdejavu=true;
02054	    }
02055	    event HearNoise(float Loudness, Actor NoiseMaker)
02056	    {
02057	        if (TestSonEntendu(NoiseMaker))
02058	            enemyacquired();
02059	    }
02060	    event SeeDeadPawn(pawn other)
02061	    {
02062	        local basesoldier Soldier;
02063	
02064	        Soldier=basesoldier(other);
02065	        if (bases.BNeVoitPascadavre || Soldier==none || Soldier.DrawType == DT_NONE || Soldier.bMonCadavreEstDejaVu || AllianceLevel(Soldier)!=1)
02066	            return;
02067	
02068	        instigator=other;
02069	        bCadavreVu=true;
02070	        Soldier.bMonCadavreEstDejaVu=true;
02071	        EnemyAcquired();
02072	        return;
02073	    }
02074	    event EnemyAcquired()
02075	    {
02076	        gotostate('acquisition');
02077	    }
02078	    singular function DamageAttitudeTo(pawn Other, float Damage)
02079	    {
02080	        //son
02081	        bases.PlaySndPNJOno(pnjono'Onomatopees.hPNJHurt',bases.CodeMesh,bases.NumeroTimbre);
02082	        if (setenemy(other))
02083	        {
02084	            //genalerte.potepaffe(pawn);
02085	            bPaffe=true;
02086	        }
02087	    }
02088	
02089	    function PickDestination()
02090	    {
02091	        if (PatrolPoint(DestNavPoint) != None)
02092	            DestNavPoint = PatrolPoint(DestNavPoint).NextPatrolPoint;
02093	        else
02094	            DestNavPoint = PickStartPoint();
02095	        if (DestNavPoint == None)  // can't go anywhere...
02096	        {
02097	            if (CHARGE_LES_LOGS) log(pawn@"can't go anywhere");
02098	            bases.PourcErrance=1;
02099	            etatneutre='Errance';
02100	            GotoState('Errance');
02101	        }
02102	    }
02103	    function bool IsPointInCylinder(Actor cylinder, Vector point,optional float extraRadius, optional float extraHeight)
02104	    {
02105	        local bool  bPointInCylinder;
02106	        local float tempX, tempY, tempRad;
02107	
02108	        tempX    = cylinder.Location.X - point.X;
02109	        tempX   *= tempX;
02110	        tempY    = cylinder.Location.Y - point.Y;
02111	        tempY   *= tempY;
02112	        tempRad  = cylinder.CollisionRadius + extraRadius;
02113	        tempRad *= tempRad;
02114	
02115	        bPointInCylinder = false;
02116	        if (tempX+tempY < tempRad)
02117	            if (Abs(cylinder.Location.Z - point.Z) < (cylinder.CollisionHeight+extraHeight))
02118	                bPointInCylinder = true;
02119	
02120	            return (bPointInCylinder);
02121	    }
02122	    function beginstate()
02123	    {
02124	        if (CHARGE_LES_LOGS) log(pawn@"ETAT patrol patrol");
02125	        settimer(0,false);
02126	        if (bases.bPatrolWithWalkSearchAnim)
02127	        {
02128	            pawn.SetAnimStatus('alert');
02129	        }
02130	        if (NiveauAlerte==1)
02131	        {
02132	            s_incattente();
02133	            s_decAlerte();
02134	        }
02135	        else if (NiveauAlerte==2)
02136	        {
02137	            s_incattente();
02138	            s_decAttaque();
02139	        }
02140	        NiveauAlerte=0;
02141	        //var temp
02142				//btemp_bool
02143	        //temp_int=0;
02144				//temp_vect utilise pour calcul dangle avec
02145			if (bases.codemesh==2)     //pas d'anim pour WIG
02146			{
02147				WaitPatrolAnim='WaitNeutre';
02148				PatrolAnim ='Walk';
02149			}
02150			else
02151			{
02152			  Switch (pawn.weapon.inventorygroup)
02153			  {
02154				  case 2: //beretta magnum
02155				  case 3:
02156						if (rand(2)<1)
02157						{
02158							WaitPatrolAnim='Waitpatrouille1Pistol';
02159							PatrolAnim='Patrouille1Pistol';
02160							TurnRPatrolAnim='TurnRPatrouille1Pistol';
02161							TurnLPatrolAnim='TurnLPatrouille1Pistol';
02162						}
02163						else
02164						{
02165							WaitPatrolAnim='Waitpatrouille2Pistol';
02166							PatrolAnim='Patrouille2Pistol';
02167							TurnRPatrolAnim='TurnRPatrouille2Pistol';
02168							TurnLPatrolAnim='TurnLPatrouille2Pistol';
02169						}
02170						break;
02171				  case 6 :   //arbalette et arbalette x3
02172				  case 7 :
02173				  case 9 :  //fusilpompe, kalash et M16
02174	           case 11 :
02175				  case 12:
02176						if (rand(4)<1)
02177						{
02178							WaitPatrolAnim='Waitpatrouille2Gun';
02179							PatrolAnim='Patrouille2Gun';
02180							TurnRPatrolAnim='TurnRPatrouille2Gun';
02181							TurnLPatrolAnim='TurnLPatrouille2Gun';
02182						}
02183						else
02184						{
02185							WaitPatrolAnim='Waitpatrouille1Gun';
02186							PatrolAnim='Patrouille1Gun';
02187							TurnRPatrolAnim='TurnRPatrouille1Gun';
02188							TurnLPatrolAnim='TurnLPatrouille1Gun';
02189						}
02190						break;
02191	
02192					case 16: //M60
02193						PatrolAnim ='WalkGatling';
02194						WaitPatrolAnim='WaitGatling';
02195						TurnRPatrolAnim='';
02196						TurnLPatrolAnim='';
02197						break;
02198					case 8:    //fusil de chasse et lance harpon
02199				  	case 10:
02200							WaitPatrolAnim='Waitpatrouille1Gun';
02201							PatrolAnim ='Patrouille1Gun';
02202							TurnRPatrolAnim='TurnRPatrouille1Gun';
02203							TurnLPatrolAnim='TurnLPatrouille1Gun';
02204						break;
02205				  case 13: //uzi
02206							WaitPatrolAnim='Waitpatrouille2Pistol';
02207							PatrolAnim ='Patrouille2Pistol';
02208							TurnRPatrolAnim='TurnRPatrouille2Pistol';
02209							TurnLPatrolAnim='TurnLPatrouille2Pistol';
02210						break;
02211				  case 15: //bazook
02212						WaitPatrolAnim='WaitBazooka';
02213						PatrolAnim ='WalkBazook';
02214						TurnRPatrolAnim='';
02215						TurnLPatrolAnim='';
02216						break;
02217					case 14:
02218						PatrolAnim ='WalkGatling';
02219						WaitPatrolAnim='SniperWait';
02220						TurnRPatrolAnim='';
02221						TurnLPatrolAnim='';
02222						break;
02223					default:
02224					    Switch (bases.CodeMesh)
02225						{
02226							case 3:
02227							case 7:
02228							case 9:
02229							case 17:
02230							case 11:
02231							case 12:
02232							case 13:
02233							case 14:
02234								WaitPatrolAnim='WaitNeutre';
02235								PatrolAnim ='Walk';
02236								break;
02237							default:
02238								WaitPatrolAnim='WaitNeutre';
02239								PatrolAnim ='WalkNeutre';
02240						}
02241	
02242				}
02243			}
02244	   	Settimer2(0,false);
02245			 pawn.AnimBlendToAlpha(bases.FIRINGCHANNEL+1,1,0.5);
02246			 bases.TakeAnimControl(false);
02247	    }
02248	    function Endstate()
02249	
02250	    {
02251	        if (bases.bPatrolWithWalkSearchAnim)
02252	        {
02253	            pawn.SetAnimStatus('quiet');
02254	        }
02255			  if (bControlAnimations) bases.ReleaseAnimControl();
02256	    	  bUTurnMove=false;
02257	    }
02258	Begin:
02259	    DestNavPoint = None;
02260	Patrol:
02261	    PickDestination();
02262	    LastPatrolPoint=PatrolPoint(DestNavPoint);
02263		 if (LastPatrolPoint==none)
02264		 {
02265				log(pawn@"PROBLEME DE RESEAU DE PATROUILLE");
02266				gotostate('tenir');
02267		 }
02268	combi_errance_patrouille:
02269	    if (Bases.PourcErrance>0)
02270	    {
02271	        if ((level.timeseconds-Temps_ref)>Temps_Errance)
02272	        {
02273	            Temps_errance=bases.PourcErrance*10+2*Frand();
02274	            Temps_ref=level.timeseconds;
02275	            gotostate('errance');
02276	        }
02277	    }
02278	
02279	Moving:
02280	    // Move from pathnode to pathnode until we get where we're going
02281		if (!IsPointInCylinder(pawn,LastPatrolPoint.Location,16-pawn.CollisionRadius))
02282		{
02283			MoveTarget=none;
02284			if (FastTrace(LastPatrolPoint.location-vect(0,0,30),pawn.location-vect(0,0,30)))
02285			{
02286				routecache[0]=LastPatrolPoint;
02287				routecache[1]=none;
02288			}
02289			else if (!FindBestPathToward(LastPatrolPoint))
02290			{
02291				if (CHARGE_LES_LOGS) log(pawn@"trouve pas le patrolpoint");
02292				bases.PourcErrance=1;
02293				Etatneutre='Errance';
02294				GotoState('Errance');
02295			}
02296			for (iCompteur=0;iCompteur<16;iCompteur++)
02297			{
02298				if (routecache[iCompteur]==none)
02299					break;
02300				PointChemin[iCompteur]=routecache[iCompteur];
02301			}
02302			NbPointChemin=iCompteur;
02303			for (iCompteur=0;iCompteur<NbPointChemin;iCompteur++)
02304			{
02305				if (LastPatrolPoint.bEnCourant)
02306				{
02307					focus=none;
02308					focalpoint=1000*(PointChemin[iCompteur].location-pawn.location)+pawn.location;
02309					pawn.bmoving=true; //pour tap tap
02310					bases.ReleaseAnimControl();
02311					MoveToward(PointChemin[iCompteur],none);
02312					bases.TakeAnimControl(false);
02313					pawn.AnimBlendToAlpha(bases.FIRINGCHANNEL+1,1,0.3);
02314				}
02315				else
02316				{
02317					Temp_vect=normal(PointChemin[iCompteur].location-pawn.location);
02318					if (TurnRPatrolAnim!='')
02319					{
02320						Temp_float= Temp_vect dot vector(pawn.rotation);
02321						//btemp_bool= true -> tourne vers droite sinon tourne vers gauche
02322						btemp_bool= (((Temp_vect cross vect(0,0,-1)) dot vector(pawn.rotation))<0);
02323					}
02324					else
02325						temp_float=2; //cheat
02326					focus=none;
02327					focalpoint=10000*Temp_vect+pawn.location;
02328					if (Temp_float<0.3)
02329					{
02330						if (btemp_bool) //droite
02331							pawn.PlayAnim(TurnRPatrolAnim,1,0.1,bases.FIRINGCHANNEL+1);
02332						else
02333							pawn.PlayAnim(TurnLPatrolAnim,1,0.2,bases.FIRINGCHANNEL+1);
02334	  				   pawn.rotationrate.yaw=20000*(1-temp_float)-1000;
02335					}
02336	
02337					if (Temp_float<0.3)
02338					{
02339						sleep(0.5);
02340						bUTurnMove=true;
02341						if (btemp_bool) //a droite anim plus longue
02342							sleep(0.68);
02343						else
02344							sleep(0.38);
02345					}
02346					pawn.bmoving=true; //pour tap tap
02347					pawn.LoopAnim(PatrolAnim,1,0.1,bases.FIRINGCHANNEL+1);
02348					if (Temp_float<0.3)
02349					{
02350						pawn.rotationrate.yaw=26000;
02351						bUTurnMove=false;
02352					}
02353					MoveToward(PointChemin[iCompteur],none,bases.walkingspeed);
02354				}
02355			}
02356		}
02357	Pausing:
02358	    // Turn in the direction dictated by the WanderPoint, or a random direction
02359	    //pawn.SpineYawControl(true,2000+rand(1000),0.8+0.6*frand());
02360		pawn.bmoving=false; //pour tap tap
02361		if (LastPatrolPoint.TypeSon!=rien && 100*frand()<=LastPatrolPoint.ProbaJouerOno)
02362		{
02363			Switch(LastPatrolPoint.TypeSon)
02364			{
02365				Case Sifflements: pawn.PlaySndPNJOno(pnjono'Onomatopees.hPNJWhistle',bases.CodeMesh,bases.NumeroTimbre); break;
02366				Case Eternuments: pawn.PlaySndPNJOno(pnjono'Onomatopees.hPNJSneeze',bases.CodeMesh,bases.NumeroTimbre); break;
02367				Case Toux: pawn.PlaySndPNJOno(pnjono'Onomatopees.hPNJCough',bases.CodeMesh,bases.NumeroTimbre); break;
02368				case OnoAleatoire :
02369					switch (rand(3))
02370					{
02371						Case 0: pawn.PlaySndPNJOno(pnjono'Onomatopees.hPNJWhistle',bases.CodeMesh,bases.NumeroTimbre); break;
02372						Case 1: pawn.PlaySndPNJOno(pnjono'Onomatopees.hPNJSneeze',bases.CodeMesh,bases.NumeroTimbre); break;
02373						Case 2: pawn.PlaySndPNJOno(pnjono'Onomatopees.hPNJCough',bases.CodeMesh,bases.NumeroTimbre); break;
02374					}
02375			}
02376		}
02377		if ((LastPatrolPoint.pausetime > 0) || (LastPatrolPoint.NextPatrolPoint == None))
02378		{
02379			pawn.Acceleration = vect(0, 0, 0);
02380			pawn.velocity=vect(0,0,0);
02381			if (LastPatrolPoint.PatrolAnim.length>0)
02382			{
02383				temp_int=rand(LastPatrolPoint.PatrolAnim.length);
02384				if (LastPatrolPoint.bBoucleSurAnim)
02385					bases.loopAnim(LastPatrolPoint.PatrolAnim[temp_int],,0.4,bases.FIRINGCHANNEL+1);
02386				else
02387					bases.playAnim(LastPatrolPoint.PatrolAnim[temp_int],,0.4,bases.FIRINGCHANNEL+1);
02388				FocalPoint = pawn.Location + LastPatrolPoint.lookdir;
02389				Focus=none;
02390				finishrotation();
02391			}
02392			else
02393			{
02394				/*Temp_vect=vector(LastPatrolPoint.rotation);
02395				Temp_float= Temp_vect dot vector(pawn.rotation);
02396				//btemp_bool= true -> tourne vers droite sinon tourne vers gauche
02397				btemp_bool= (((Temp_vect cross vect(0,0,-1)) dot vector(pawn.rotation))<0);
02398			 	if (abs(Temp_float)<0.707)  			//anim pietinement
02399				{
02400					if (btemp_bool) //droite
02401						pawn.loopAnim('RotationD',1,0.3,2);
02402					else
02403						pawn.loopAnim('RotationG',1,0.3,2);
02404				}
02405				pawn.AnimBlendToAlpha(2,1,0.3);
02406				pawn.LoopAnim(WaitPatrolAnim,1,0.3,bases.FIRINGCHANNEL+1);
02407			 	pawn.AnimBlendToAlpha(bases.FIRINGCHANNEL+1,0.5,0.3);   */
02408				pawn.LoopAnim(WaitPatrolAnim,1,0.3,bases.FIRINGCHANNEL+1);
02409				FocalPoint = pawn.Location + LastPatrolPoint.lookdir;
02410				Focus=none;
02411				finishrotation();
02412				//pawn.AnimBlendToAlpha(2,0,0.5);
02413				//pawn.AnimBlendToAlpha(bases.FIRINGCHANNEL+1,1,0.3);
02414			}
02415			sleeptime=Frand()*LastPatrolPoint.deltatime;
02416			if (FRand()<0.5)
02417				sleeptime*=-1;
02418			sleepTime += LastPatrolPoint.pausetime*0.55;
02419			sleeptime = fmax(0.02,sleeptime);
02420			Sleep(sleepTime);
02421			if (LastPatrolPoint.event != '')
02422			{
02423				TriggerEvent(LastPatrolPoint.event, pawn, pawn);
02424			}
02425		}
02426		if (LastPatrolPoint.bResteSurDernier)
02427		{
02428			if (CHARGE_LES_LOGS) log(pawn@"stay here");
02429			stop;
02430		}
02431	    Goto('Patrol');
02432	}
02433	
02434	// ----------------------------------------------------------------------
02435	// Etat d'errance
02436	//
02437	//
02438	// ----------------------------------------------------------------------
02439	state Errance
02440	{
02441	    ignores EnemyNotVisible;
02442	
02443	    event Seeplayer(pawn other)
02444	    {
02445	        if (setenemy(XIII))
02446	            bDejaVu=true;
02447	    }
02448	    event SeeMonster(pawn other)
02449	    {
02450	        if (setenemy(other))
02451	            bDejaVu=true;
02452	    }
02453	    event SeeDeadPawn(pawn other)
02454	    {
02455	        local basesoldier Soldier;
02456	
02457	        Soldier=basesoldier(other);
02458	        if (bases.BNeVoitPascadavre || Soldier==none || Soldier.DrawType == DT_NONE || Soldier.bMonCadavreEstDejaVu || AllianceLevel(Soldier)!=1)
02459	            return;
02460	        instigator=other;
02461	        bCadavreVu=true;
02462	        Soldier.bMonCadavreEstDejaVu=true;
02463	        EnemyAcquired();
02464	        return;
02465	    }
02466	    event EnemyAcquired()
02467	    {
02468	        gotostate('acquisition');
02469	    }
02470	    event HearNoise(float Loudness, Actor NoiseMaker)
02471	    {
02472	        if (TestSonEntendu(NoiseMaker))
02473	            enemyacquired();
02474	    }
02475	    singular function DamageAttitudeTo(pawn Other, float Damage)
02476	    {
02477	        //son
02478	        bases.PlaySndPNJOno(pnjono'Onomatopees.hPNJHurt',bases.CodeMesh,bases.NumeroTimbre);
02479	        if (setenemy(Other))
02480	        {
02481	            //genalerte.potepaffe(pawn);
02482	            bPaffe=true;
02483	        }
02484	    }
02485	    function PickDestination()
02486	    {
02487	        local vector pick, pickdir;
02488	        local bool success;
02489	        local float XY;
02490	        local float MoveDist;
02491	
02492	        //Favor XY alignment
02493	        //Log(self$" GetFacingDirection Y.Dir="$(Y dot dir)$" X.Dir="$(X dot dir));
02494	        XY = FRand();
02495	        if (XY < 0.3)
02496	        {
02497	            pickdir.X = 1;
02498	            pickdir.Y = 0;
02499	        }
02500	        else if (XY < 0.6)
02501	        {
02502	            pickdir.X = 0;
02503	            pickdir.Y = 1;
02504	        }
02505	        else
02506	        {
02507	            pickdir.X = 2 * FRand() - 1;
02508	            pickdir.Y = 2 * FRand() - 1;
02509	        }
02510	        if (Pawn.Physics != PHYS_Walking)
02511	        {
02512	            pickdir.Z = 2 * FRand() - 1;
02513	            pickdir = Normal(pickdir);
02514	        }
02515	        else
02516	        {
02517	            pickdir.Z = 0;
02518	            if (XY >= 0.6)
02519	                pickdir = Normal(pickdir);
02520	        }
02521	        MoveDist = 150+DistanceDeplacement*(0.4+0.6*Frand());
02522	        success = TestDirection(150.0,MoveDist,pickdir, pick);
02523	        if (!success)
02524	            if ((bTemp_Bool) && (FRand()<0.7))   //if don't work try to go straight
02525	            {
02526	                MoveDist = 150+DistanceDeplacement*(0.4+0.6*Frand());
02527	                success = TestDirection(150,MoveDist,vector(pawn.rotation), pick);
02528	            }
02529	            else      //if don't work try in the opposite side
02530	            {
02531	                MoveDist = 150+DistanceDeplacement*(0.4+0.6*Frand());
02532	                success = TestDirection(150,movedist,-1*pickdir, pick);
02533	            }
02534	
02535	            if (success)
02536	            {
02537	                bTemp_Bool=true;
02538	                DistNearWall=min(200,DistNearWall+5);
02539	                DistanceDeplacement=min(600,DistanceDeplacement+45);
02540	                Destination = pick;
02541	            }
02542	            else
02543	            {
02544	                bTemp_Bool=false;
02545	                DistNearWall=fmax(4*pawn.collisionradius,DistNearWall-40);
02546	                DistanceDeplacement=max(10,DistanceDeplacement-35);
02547	                GotoState('errance','Turn');
02548	            }
02549	    }
02550	
02551	    function bool IsInWanderingVolume(WanderingVolume aVolume)
02552	    {
02553	        local WanderingVolume V;
02554	
02555	        ForEach pawn.TouchingActors(class'WanderingVolume',V)
02556	            if ( V == aVolume )
02557	                return true;
02558	            return false;
02559	    }
02560	    function beginstate()
02561	    {
02562	        settimer(0,false);
02563	        if (NiveauAlerte==1)
02564	        {
02565	            s_incattente();
02566	            s_decAlerte();
02567	        }
02568	        else if (NiveauAlerte==2)
02569	        {
02570	            s_incattente();
02571	            s_decAttaque();
02572	        }
02573	        NiveauAlerte=0;
02574	        MinHitWall += 0.15;
02575	        //test si dnas volume d'errance
02576	        if (bases.MyWanderingVolume!=none && !IsInWanderingVolume(bases.MyWanderingVolume))   //dans volume
02577	        {
02578	            if (CHARGE_LES_LOGS) log(pawn$"pas dans le volume donc erre partout");
02579	            bases.MyWanderingVolume=none;
02580	        }
02581	    }
02582	    function Endstate()
02583	    {
02584	        MinHitWall -= 0.15;
02585	        pawn.SpineYawControl(false,0,0);
02586	    }
02587	
02588	Begin:
02589	    if (CHARGE_LES_LOGS) log(pawn@"ETAT  Wandering");
02590	Wander:
02591	    pawn.SpineYawControl(true,3000+rand(1000),1.2+0.8*frand());
02592	    PickDestination();
02593	combi_errance_patrouille:
02594	    if (Bases.PourcErrance<1)
02595	    {
02596	        if ((level.timeseconds-Temps_ref)>Temps_Errance)
02597	        {
02598	            Temps_errance=(1-bases.PourcErrance)*10+2*Frand();
02599	            Temps_ref=level.timeseconds;
02600	            gotostate('patrouille');
02601	        }
02602	    }
02603	Moving:
02604	    focalpoint=destination;
02605	    Temp_float=normal(destination-pawn.location) dot normal(vector(pawn.rotation));
02606	    if (Temp_float<0.3)
02607	        sleep(10000*(1-Temp_float)/pawn.rotationrate.yaw);
02608	    MoveTo(Destination,None, Bases.WalkingSpeed);
02609	Pausing:
02610	    Pawn.Acceleration = vect(0,0,0);
02611	    pawn.velocity=vect(0,0,0);
02612	    pawn.SpineYawControl(true,2000+rand(1000),0.8+0.6*frand());
02613	    if (bases.MyWanderingVolume!=none && !IsInWanderingVolume(bases.MyWanderingVolume))   //dans volume
02614	    {
02615	        //log(pawn$"ATTENTION je sort du volume demi-tour");
02616	        focalpoint=-DistanceDeplacement*vector(pawn.rotation)+pawn.location;
02617	        finishrotation();
02618	        DistanceDeplacement=max(10,DistanceDeplacement-40);
02619	        MoveTo(focalpoint,None, Bases.WalkingSpeed);
02620	    }
02621	    if (NearWall(DistNearWall))
02622	    {
02623	        DistanceDeplacement=max(10,DistanceDeplacement-10);
02624	        DistNearWall=fmax(2*pawn.collisionradius,DistNearWall-5);
02625	        FinishRotation();
02626	    }
02627	    Sleep(1.0);
02628	    goto('wander');
02629	Turn:
02630	    pawn.SpineYawControl(true,2000+rand(1000),0.8+0.6*frand());
02631	    pawn.velocity=vect(0,0,0);
02632	    Pawn.Acceleration = vect(0,0,0);
02633	    Focus = None;
02634	    FocalPoint = Location + 20 * VRand();
02635	    FinishRotation();
02636	    Goto('Pausing');
02637	}
02638	
02639	// ----------------------------------------------------------------------
02640	//Etat tenir
02641	//
02642	//
02643	// ----------------------------------------------------------------------
02644	state Tenir
02645	{
02646	    ignores EnemyNotVisible;
02647	    event Seeplayer(pawn other)
02648	    {
02649	        if (setenemy(XIII))
02650	            bDejaVu=true;
02651	    }
02652	    event SeeMonster(pawn other)
02653	    {
02654	        if (setenemy(other))
02655	            bDejaVu=true;
02656	    }
02657	    event SeeDeadPawn(pawn other)
02658	    {
02659	        local basesoldier Soldier;
02660	
02661	        Soldier=basesoldier(other);
02662	        if (bases.BNeVoitPascadavre || Soldier==none || Soldier.DrawType == DT_NONE || Soldier.bMonCadavreEstDejaVu || AllianceLevel(Soldier)!=1)
02663	            return;
02664	
02665	        instigator=other;
02666	        bCadavreVu=true;
02667	        Soldier.bMonCadavreEstDejaVu=true;
02668	        EnemyAcquired();
02669	        return;
02670	    }
02671	    event EnemyAcquired()
02672	    {
02673	        gotostate('acquisition');
02674	    }
02675	    event HearNoise(float Loudness, Actor NoiseMaker)
02676	    {
02677	        if (TestSonEntendu(NoiseMaker))
02678	            enemyacquired();
02679	    }
02680	    singular function DamageAttitudeTo(pawn Other, float Damage)
02681	    {
02682	        //son
02683	        bases.PlaySndPNJOno(pnjono'Onomatopees.hPNJHurt',bases.CodeMesh,bases.NumeroTimbre);
02684	        if (setenemy(Other))
02685	        {
02686	            //genalerte.potepaffe(pawn);
02687	            bPaffe=true;
02688	        }
02689	    }
02690	    function beginstate()
02691	    {
02692	        settimer(0,false);
02693	        if (NiveauAlerte==1)
02694	        {
02695	            s_incattente();
02696	            s_decAlerte();
02697	        }
02698	        else if (NiveauAlerte==2)
02699	        {
02700	            s_incattente();
02701	            s_decAttaque();
02702	        }
02703	        NiveauAlerte=0;
02704	        pawn.SpineYawControl(true,2000+rand(1000),0.8+0.6*frand());
02705	    }
02706	    function Endstate()
02707	    {
02708	        if (EtatNeutre == 'tenir')
02709	        {
02710	            PointTenirPos=pawn.location;
02711	            PointTenirRot=pawn.rotation;
02712	        }
02713	        pawn.SpineYawControl(false,0,0);
02714	    }
02715	
02716	BackToFormation:
02717	    if (CHARGE_LES_LOGS) log(pawn@"ETAT tiens position  BACKTO FORMATION");
02718	    if (FastTrace(PointTenirPos-vect(0,0,30)))
02719	    {
02720	        focalpoint=PointTenirPos;
02721	        focus=none;
02722	        MoveTo(PointTenirPos,none);
02723	        focalpoint=1000*vector(pointtenirRot)+pawn.location;
02724	        focus=none;
02725	    }
02726	    else
02727	    {
02728	        if (FindBestPathTo(PointTenirPos))
02729	        {
02730	            for (temp_int=0;temp_int<16;temp_int++)
02731	            {
02732	                if (routecache[temp_int]==none)
02733	                    break;
02734	                PointChemin[temp_int]=routecache[temp_int];
02735	            }
02736	            NbPointChemin=temp_int;
02737	            for (iCompteur=0;iCompteur<NbPointChemin;iCompteur++)
02738	            {
02739	                MoveToward(PointChemin[iCompteur],PointChemin[iCompteur]);
02740	            }
02741	            focalpoint=PointTenirPos;
02742	            focus=none;
02743	            MoveTo(PointTenirPos,none);
02744	            focalpoint=vector(pointtenirRot)+pawn.location;
02745	        }
02746	    }
02747	begin:
02748	    if (CHARGE_LES_LOGS) log(pawn@"ETAT tiens position");
02749	    pawn.velocity=vect(0,0,0);
02750	    pawn.Acceleration = vect(0,0,0);
02751	Targetenemy:
02752	}
02753	
02754	// ----------------------------------------------------------------------
02755	// Etat de ResteSurPlace
02756	//
02757	//
02758	// ----------------------------------------------------------------------
02759	state ResteSurPlace
02760	{
02761	    ignores EnemyNotVisible,hearnoise;
02762	
02763	    singular event bool NotifyBump(actor Other)
02764	    {
02765	        return false;
02766	    }
02767	
02768	    event Tick(float DeltaTime)
02769	    {
02770	        global.tick(DeltaTime);
02771	
02772	        if (bFuitPourreloader && (level.timeseconds-Timer_VaRecharger)>1.5)
02773	        {
02774	            bFuitPourreloader=false;
02775	            gotostate('attaque');
02776	        }
02777	    }
02778	
02779	    event Seeplayer(pawn other)
02780	    {
02781				if (enemy==none || !bdejavu)
02782				{
02783					if (setenemy(XIII))
02784	                bDejaVu=true;
02785				}
02786				else  if (enemy!=none && enemy==other)
02787	            	SeeEnemy();
02788	    }
02789	    event SeeMonster(pawn other)
02790	    {
02791	        if (enemy==none || !bdejavu)
02792				{
02793					if (setenemy(other))
02794	                bDejaVu=true;
02795				}
02796				else
02797				{
02798				  if (enemy!=none && enemy==other)
02799	            	SeeEnemy();
02800			  }
02801	    }
02802	    event SeeDeadPawn(pawn other)
02803	    {
02804	        local basesoldier Soldier;
02805	
02806	        Soldier=basesoldier(other);
02807	        if (bases.BNeVoitPascadavre || Soldier==none || Soldier.DrawType == DT_NONE || Soldier.bMonCadavreEstDejaVu || AllianceLevel(Soldier)!=1)
02808	            return;
02809	        Soldier.bMonCadavreEstDejaVu=true;
02810	        instigator=other;
02811	        bCadavreVu=true;
02812	        EnemyAcquired();
02813	        return;
02814	    }
02815	    event EnemyAcquired()
02816	    {
02817	        if (bCampeversSafePoint)
02818	            gotostate('acquisition');
02819	        else
02820	            gotostate('attaque');
02821	    }
02822	
02823	    singular function DamageAttitudeTo(pawn Other, float Damage)
02824	    {
02825	        //son
02826	        bases.PlaySndPNJOno(pnjono'Onomatopees.hPNJHurt',bases.CodeMesh,bases.NumeroTimbre);
02827	
02828	        if (bDisableDamageattitudeto)
02829	            return;
02830	        if (setenemy(Other))
02831	        {
02832	            //genalerte.potepaffe(pawn);
02833	            bPaffe=true;
02834	        }
02835	    }
02836	    function bool TestDirectionAvoidingAlly(vector pickdir, out vector pick,basesoldier PoteAEviter)
02837	    {
02838	        local float MoveDist;
02839	
02840	        if (Vsize(PoteAEviter.location - pawn.location)>160)
02841	            pickdir += 0.99*normal(Enemy.location-pawn.location); // pour partir a 45 degres si charge
02842	        else
02843	            pickdir +=0.3*normal(Enemy.location-pawn.location); // pour partir a 80 degres si charge
02844	
02845	        if (Vsize(PoteAEviter.location - enemy.location)<300 || Vsize(PoteAEviter.location - pawn.location)<=160)
02846	            MoveDist=140;
02847	        else
02848	            MoveDist=110+150*FRand();
02849	        return TestDirection(110,MoveDist,-1*pickdir, pick);
02850	    }
02851	
02852	    function bool TestPasSurCote(basesoldier PoteAEviter)
02853	    {
02854	        local vector pick, pickdir;
02855	        local bool success;
02856	
02857	        pickdir=(Enemy.location-pawn.location) cross vect(0,0,1);
02858	        pickdir.Z = 0;
02859	        pickdir=normal(pickdir);
02860	
02861	        success = TestDirectionAvoidingAlly(pickdir, pick,PoteAEviter);
02862	        if (!success)
02863	            success = TestDirectionAvoidingAlly(-1*pickdir, pick,PoteAEviter);
02864	        Destination = pick;
02865	        return success;
02866	    }
02867	
02868	    function beginstate()
02869	    {
02870	        //reactions
02871	        //bDisableEventSeeDeadPawn=true; //desactive detection cadavre
02872	        if (!bCadavreVU)
02873		     		focus=xiii; //cheat Il sait ou est XIII
02874	         else
02875		     		focus=none;
02876	        if (bCampeversSafePoint)
02877	        {
02878	            bdejavu=false;
02879	            bases.balerte=true;
02880	            SetVigilant(true);
02881	            bEtatAlerte=true;
02882	            enemy=none;
02883	        }
02884	        else
02885	        {
02886	            bDejaVu=true;     //desactive detection son
02887	        }
02888	        settimer(0,false);
02889	        if (NiveauAlerte==0)
02890	        {
02891	            s_decattente();
02892	            s_incAlerte();
02893	        }
02894	        else if (NiveauAlerte==2)
02895	        {
02896	            s_incalerte();
02897	            s_decAttaque();
02898	        }
02899	        NiveauAlerte=1;
02900	        bFuitPourreloader=false;
02901	    }
02902	    function Endstate()
02903	    {
02904		    if (bcontrolanimations) bases.ReleaseAnimControl();
02905	        if (pawn.biscrouched)
02906	            pawn.shouldcrouch(false);
02907	        bDisableDamageattitudeto=false;
02908	        bCampeversSafePoint=false;
02909	        bRetraiteVersSafePoint=false;
02910				if (SafePointOccupe!=none)
02911				{
02912					SafePointOccupe.timer();
02913					SafePointOccupe=none;
02914				}
02915				if (bCadavreVU)
02916		 		{
02917					bcadavrevu=false;
02918					Pawn.PeripheralVision=fmin(DefaultPeripheralVision,0);
02919				}
02920	    }
02921	
02922	    //y rester 10 s si alarme ou fuite, sinon tout le temps (pour bruit d'impact et quoique)
02923	begin:
02924	    pawn.velocity=vect(0,0,0);
02925	    pawn.acceleration=vect(0,0,0);
02926	    if (CHARGE_LES_LOGS) log(pawn@"ETAT Reste SUr Place");
02927		 if (bCadavreVU)
02928		 {
02929				pawn.playwaiting();
02930				focus=none;
02931				focalpoint+=0.5*vsize(focalpoint)*normal(XIII.location-pawn.location);
02932	      	finishrotation();
02933				sleep(0.1);
02934				Pawn.PeripheralVision=fmin(DefaultPeripheralVision,-0.5);
02935				bases.PlayQuickLookAround();
02936				FinishAnim(bases.firingChannel+1);
02937				Bases.ReleaseAnimControl();
02938				pawn.playwaiting();
02939				sleep(1.15);
02940				bases.Shouldcrouch(true);
02941	    }
02942		 if (enemy!=none)
02943	    {
02944	        focus=enemy;
02945	        finishrotation();
02946	    }
02947	    if (bRetraiteVersSafePoint)
02948	    {
02949	        sleep(1+4*frand());
02950	        gotostate('attaque');
02951	    }
02952	    stop;
02953	PoteMeBLoque:
02954	    if (PoteQuiMeBloque==none)  //blindage
02955	        gotostate('attaque');
02956	    log(pawn@"POTE ME BLOQUE J4ATTEND EN ME RECALANT");
02957	    disable('seeplayer');
02958	    disable('seemonster');
02959	    pawn.velocity=vect(0,0,0);
02960	    pawn.acceleration=vect(0,0,0);
02961		if (enemy!=none)
02962	   {
02963			//if (fasttrace(-200*vector(pawn.rotation)+pawn.location))
02964	      Moveto(-200*vector(pawn.rotation)+pawn.location,enemy,bases.walkingspeed);
02965	   }
02966	   else
02967	   {
02968	
02969	      //if (fasttrace(-200*vector(pawn.rotation)+pawn.location))
02970	      Moveto(-200*vector(pawn.rotation)+pawn.location,PoteQuiMeBloque,bases.walkingspeed);
02971	   }
02972	    //boucle pour un max de 3s
02973		sleep(0.5+frand());
02974	    for (temp_int=0;temp_int<6;temp_int++)
02975	    {
02976	        if (PoteQuiMeBloque.bisdead || vsize(PoteQuiMeBloque.location-PoteQuiMeBloquePos)>100)
02977	            break;
02978				sleep(0.5);
02979	    }
02980		bases.bslave=false;
02981		bases.bDetecteBloquage=false;
02982	   PoteQuiMeBloque=none;
02983	   gotostate(prevstate);
02984	}
02985	// ----------------------------------------------------------------------
02986	// Etat d'acquisition        (enemy!=none)
02987	//
02988	//
02989	// ----------------------------------------------------------------------
02990	
02991	state Acquisition
02992	{
02993		Function SeeEnemy()
02994		{
02995			LastSeenTime = Level.TimeSeconds;
02996			LastSeeingPos = Pawn.Location;
02997			LastSeenPos = Enemy.Location;
02998			EnemyAcquired();
02999		}
03000		event timer2()
03001		{
03002				LOCAL Rotator rl;
03003				LOCAL int n;
03004	
03005				if ( PeeredEnemy!=none )
03006				{
03007					rl=rotator(PeeredEnemy.Location-pawn.Location)-pawn.Rotation;
03008	
03009					n=rl.Yaw;//-16384;
03010					n=((n+32768)&65535)-32768;
03011	
03012					if ((15000>n) && (n>-15000))
03013					{
03014						pawn.HeadYaw = pawn.HeadYaw*0.6+0.4*n;
03015						rl.Yaw=0;
03016						rl.Pitch=0;
03017						rl.Roll=pawn.HeadYaw;
03018						pawn.SetBoneRotation('X HEAD',rl,,0.75);
03019					}
03020					else
03021					{
03022						pawn.HeadYaw = pawn.HeadYaw*0.7;
03023						rl.Yaw=0;
03024						rl.Pitch=0;
03025						rl.Roll= pawn.HeadYaw;
03026						pawn.SetBoneRotation('X HEAD',rl,,0.75);
03027					}
03028				}
03029				else
03030				{
03031					if ( pawn.HeadYaw!=0 )
03032					{
03033						pawn.HeadYaw = pawn.HeadYaw*0.8;
03034						if (pawn.HeadYaw > 100 )
03035						{
03036							rl.Yaw=0;
03037							rl.Pitch=0;
03038							rl.Roll= pawn.HeadYaw;
03039							pawn.SetBoneRotation('X HEAD',rl,,0.75);
03040						}
03041						else
03042						{
03043							pawn.HeadYaw=0;
03044							rl.Yaw=0;
03045							rl.Pitch=0;
03046							rl.Roll= 0;
03047							settimer2(0,false);
03048							pawn.SetBoneRotation('X HEAD',rl,,0.0);
03049						}
03050					}
03051				}
03052		}
03053		 event Seeplayer(pawn other)
03054	    {
03055				if (!bDejaVu && enemy!=none && enemy==other)
03056	            	SeeEnemy();
03057				else
03058					setenemy(XIII);
03059	    }
03060	    event SeeMonster(pawn other)
03061	    {
03062	        if (!bDejaVu && enemy!=none && enemy==other)
03063	            	SeeEnemy();
03064			  else
03065					setenemy(other);
03066	    }
03067	    event SeeDeadPawn(pawn other)
03068	    {
03069	        local basesoldier soldier;
03070	
03071	        soldier=basesoldier(other);
03072	
03073	        if (bases.BNeVoitPascadavre || bCadavreVu || !bStepNoise || soldier==none || Soldier.DrawType == DT_NONE || soldier.bMonCadavreEstDejaVu || AllianceLevel(Soldier)!=1)
03074	            return;
03075	        bStepNoise=false;
03076	        bCadavreVu=true;
03077	        instigator=other;
03078	        enemy=none;
03079	        InitReactions();
03080	        Soldier.bMonCadavreEstDejaVu=true;
03081	        gotostate('acquisition','CadavreVu');
03082	    }
03083	    event EnemyNotVisible()
03084	    {
03085	        if (bAVuQuelquechose)
03086	        {
03087	            gotostate('investigation');
03088	        }
03089	        else
03090	        {
03091					if (!bARienVu)
03092					{
03093						bARienVu=true;
03094					   settimer3(8+2*frand(),false);
03095					}
03096	            Changeetat(); //dans vu si voit plus s'arrete
03097	        }
03098	    }
03099	    event EnemyAcquired()
03100	    {
03101	        bDejaVu=true;
03102	        bPaffe=false;
03103	        bCadavreVu=false;
03104	        bStepNoise=false;
03105	        bImpactNoise=false;
03106	        bWeaponNoise=false;
03107	        pawn.SpineYawControl(false,0,0);
03108	        disable('seeplayer');
03109	        disable('seemonster');
03110	        gotostate('acquisition','attaque');
03111	    }
03112	    event hearnoise(float loudness, actor NoiseMaker)
03113	    {
03114	        ActualiseSon(NoiseMaker);
03115	    }
03116	    event Trigger(actor Other, pawn EventInstigator)
03117	    {
03118	    }
03119	    singular function DamageAttitudeTo(pawn Other, float Damage)
03120	    {
03121	        local int Level;
03122	
03123	        if (bDisableDamageattitudeto)
03124	            return;
03125	        //son
03126	        bases.PlaySndPNJOno(pnjono'Onomatopees.hPNJHurt',bases.CodeMesh,bases.NumeroTimbre);
03127	        level=AllianceLevel(Other);
03128	        if (level<=0)
03129	        {
03130	            if (level==0)
03131	                SwitchToEnemy(Other);
03132	            bPaffe=true;
03133	            bCadavreVu=false;
03134	            bStepNoise=false;
03135	            bImpactNoise=false;
03136	            enemy=Other;
03137	            InitReactions();
03138	            gotostate('acquisition','Paffe');
03139	        }
03140	    }
03141	    function ActualiseSon(actor son)
03142	    {
03143			  if (son.instigator!=none && son.instigator.controller!=none && son.instigator.controller.isa('CineController2'))
03144					return;
03145	        //bruit d'arme prioritaire sur bruitpas
03146	        if (weapon(son)!=none || XIIIProjectile(son)!=none)
03147	        {
03148	            if (alliancelevel(son.instigator)==1) //pote donc prend son enemy
03149	            {
03150	                enemy=son.instigator.controller.enemy;
03151	                instigator=son.instigator;
03152	            }
03153	            else
03154	            {
03155	                enemy=son.instigator;
03156	                instigator=enemy;
03157	            }
03158	            bStepNoise=false;
03159	            bImpactNoise=false;
03160	            bCadavreVu=false;
03161	            bPaffe=false;
03162	            bWeaponNoise=true;
03163	            InitReactions();
03164	            gotostate('acquisition','BruitArme');
03165	        }
03166	        else if ((bStepNoise || bCadavreVu) && BulletDustEmitter(son)!=none && son.instigator==XIII)
03167	        {
03168	            bImpactNoise=true;
03169	            bStepNoise=false;
03170	            bCadavreVu=false;
03171	            enemy=xiii;
03172	            gotostate('acquisition','BruitImpact');
03173	        }
03174	    }
03175	    function ChercheNMIDuRegard() // dans cone de 45 degre autour pos other
03176	    {
03177	        local int Sens;
03178	        local vector Norm;
03179	
03180	        Sens=1;
03181	        if (frand()<0.5)
03182	            Sens=-1;
03183	        Norm=normal(enemy.location-pawn.location);
03184	        focalpoint=1000*(Norm+0.8*(Norm cross (sens*vect(0,0,1))))+pawn.location;
03185	    }
03186	
03187	    Function InitReactions()
03188	    {
03189	        bDisableDamageattitudeto=false;
03190	        //si bruit de pas desactive rien
03191	        if (!bStepNoise)
03192	        {
03193	            //bDisableEventSeeDeadPawn=true;
03194	            if (!bImpactNoise && !bCadavreVu)
03195	            {
03196	                bDisableDamageattitudeto=true;
03197	                if (!bPaffe) //donc vu ou bruit d'arme
03198	                {
03199	                    disable('hearnoise');
03200	                    if (bDejaVu)
03201	                    {
03202	                        disable('seeplayer');
03203	                        disable('seemonster');
03204	                    }
03205	                }
03206	            }
03207	        }
03208	    }
03209	    /* [****] integrer si le positionnnement n'est pas bon
03210	    A REVOIR ENTIEREMENT
03211	    function CherchePointPresDernierePos()
03212	    {
03213	    local NavigationPoint N, Best;
03214	    local vector Dir, EnemyDir;
03215	    local float Dist, BestVal, Val;
03216	
03217	      EnemyDir = Normal(Enemy.Location - Pawn.Location);
03218	      for ( N=Level.NavigationPointList; N!=None; N=N.NextNavigationPoint )
03219	      {
03220	      Dir = N.Location - LAstSeenPos;
03221	      Dist = VSize(Dir);
03222	      if (Dist<200)
03223	      {
03224	      Val = (EnemyDir Dot Dir/Dist);
03225	      if ((Val > BestVal) && LineOfSightTo(N))
03226	      {
03227	      BestVal = Val;
03228	      Best = N;
03229	      }
03230	      }
03231	      }
03232	      if ( Best != None )
03233	      LastSeenPos = Best.Location + 0.5 * Pawn.CollisionHeight * vect(0,0,1);
03234	     }  */
03235	    function beginstate()
03236	    {
03237	        disable('enemynotvisible');
03238	        if (NiveauAlerte==0)
03239	        {
03240	            s_decAttente();
03241	            s_incAlerte();
03242	        }
03243	        else if (NiveauAlerte==2)
03244	        {
03245	            s_decAttaque();
03246	            s_incAlerte();
03247	        }
03248	        NiveauAlerte=1;
03249			  bAVuQuelquechose=false;
03250	        SetVigilant(true); //vigilant
03251	        settimer(0,false);
03252	        //temp_vect utilise pour calcul dest vers cadavre
03253	    }
03254	    function Endstate()
03255	    {
03256		//		local rotator rl;
03257	
03258	        if (interrogation!=none)
03259	        {
03260	            interrogation.destroy();
03261	            interrogation=none;
03262	        }
03263				//remettre tete
03264		/*	  PeeredEnemy=none;
03265			  settimer2(0,false);
03266			  pawn.HeadYaw=0;
03267			  rl.Yaw=0;
03268			 rl.Pitch=0;
03269				rl.Roll= 0;
03270				pawn.SetBoneRotation('X HEAD',rl,,0.0); */
03271	        pawn.SpineYawControl(false,0,0);
03272	    }
03273	
03274	Begin:
03275	    if (CHARGE_LES_LOGS) log(pawn@"ETAT acquisition");
03276	    if (CHARGE_LES_LOGS) log("bStepNoise"$bStepNoise@"bImpactNoise"$bImpactNoise@"bCadavreVu"$bCadavreVu@"bPaffe"$bPaffe@"bWeaponNoise"$bWeaponNoise@"bDejaVu"$bDejaVu@"enemy"$enemy);
03277	
03278	    InitReactions();
03279	    if (!bcadavrevu && enemy.bisdead)
03280	    {
03281	        ChangeEtat();
03282	    }
03283	    Pawn.Acceleration = vect(0,0,0);
03284	    Pawn.Velocity = vect(0,0,0);
03285	Init:
03286	    if (!bDejaVu)
03287	    {
03288	        pawn.SetAnimStatus('alert');
03289			  //son
03290	    	  Interrogation=Spawn(class'exclamation',self,,bases.location+(vector(bases.rotation) cross vect(0,0,1))*6 + 120*vect(0,0,1));
03291	        interrogation.setbase(pawn);
03292	        pawn.SpineYawControl(true,2000+rand(1000),0.8+0.6*frand());
03293	        if ((bStepNoise || bImpactNoise || bPaffe || bWeaponNoise) && enemy==none)
03294	       		ChangeEtat();
03295	        if ((bCadavreVu || bWeaponNoise) && instigator==none)
03296	       		ChangeEtat();
03297	        if (bStepNoise)
03298			  {
03299	            goto('BruitPas');
03300	        }
03301	        else
03302			  {
03303	  			  pawn.PlaySndPNJOno(pnjono'Onomatopees.hPNJDetect',bases.CodeMesh,bases.NumeroTimbre);//se retourne vers bruit et reste sur place
03304		        if (bImpactNoise)
03305		            goto('BruitImpact');
03306		        else if (bCadavreVu)
03307		            goto('CadavreVu');
03308		        else if (bPaffe)
03309		            goto('Paffe');
03310		        else if (bWeaponNoise)
03311		            goto('BruitArme');
03312			  }
03313	    }
03314	    else
03315		 {
03316			  	if (enemy==none)
03317					Changeetat();
03318	        goto('Vu');
03319		 }
03320	BruitPas:
03321	    ChercheNMIDuRegard();
03322	    FinishRotation();
03323	    sleep(2);
03324	    Changeetat();
03325	CadavreVu:
03326	    //va vers cadavre, alarme, investigation (???)
03327		 Focus=none;
03328	    Focalpoint=10000*(instigator.location-pawn.location)+pawn.location;
03329	    FinishRotation();
03330	    sleep(0.5);
03331	    pawn.PlaySndPNJOno(pnjono'Onomatopees.hPNJDetect',bases.CodeMesh,bases.NumeroTimbre);
03332	    pawn.SpineYawControl(false,0,0);
03333	    if (Vsize(instigator.location-pawn.location)<100)   //vavers cadavre
03334	        temp_vect=instigator.location;
03335	    else
03336	        temp_vect=(Vsize(instigator.location-pawn.location)-100)*normal(instigator.location-pawn.location)+pawn.location;
03337	    MoveTo(temp_vect,none);
03338	    TriggerEvent('cadavrevu', self, pawn);
03339	    if (!genalerte.bAllAlarmsActivated)    ChercheAlarme();  //ALARMEChercheAlarme();  //ALARME
03340	    bCampeversSafePoint=true;
03341	    gotostate('ResteSurPlace');
03342	BruitImpact:
03343	    //se retourne vers bruit, alarme, cherche safepoint sinon investigation
03344	    ChercheNMIDuRegard();
03345	    FinishRotation();
03346	    if (!genalerte.bAllAlarmsActivated)    ChercheAlarme();  //ALARMEChercheAlarme();  //ALARME
03347	    if (bases.order!='garder') CherchePointPourCamper(); //interruption possible vers vavers
03348	    gotostate('investigation');
03349	Paffe:
03350	    //se retourne vers tireur (60d), alarme, cherche safepoint sinon investigation
03351	    ChercheNMIDuRegard();
03352	    FinishRotation();
03353	    if (!genalerte.bAllAlarmsActivated)    ChercheAlarme();  //ALARMEChercheAlarme();  //ALARME
03354	    if (bases.order!='garder') CherchePointPourCamper();
03355	    gotostate('investigation');
03356	BruitArme:
03357	    //se retourne vers bruit, alarme, va vers bruit,investigation
03358	    ChercheNMIDuRegard();
03359	    FinishRotation();
03360	    if (!genalerte.bAllAlarmsActivated)    ChercheAlarme();  //ALARMEChercheAlarme();  //ALARME
03361	    if (bases.bRappliqueSiAlerte)
03362	    {
03363	        MoveTarget=none;
03364	        if (Fasttrace(instigator.location-vect(0,0,30),pawn.location-vect(0,0,30)))
03365	        {
03366	            MoveActor.MoveActor=none;
03367	            MovePoint.MovePoint=instigator.location;
03368	            MovePoint.bTraceable=true;
03369	            nextstate='investigation';
03370	            gotostate('vavers');
03371	        }
03372	        else if (FindBestPathToward(instigator))
03373	        {
03374	            MoveActor.MoveActor=none;
03375	            MovePoint.MovePoint=instigator.location;
03376	            MovePoint.bTraceable=false;
03377	            for (iCompteur=0;iCompteur<16;iCompteur++)
03378	            {
03379	                if (routecache[iCompteur]==none)
03380	                    break;
03381	                PointChemin[iCompteur]=routecache[iCompteur];
03382	            }
03383	            NbPointChemin=iCompteur;
03384	            nextstate='investigation';
03385	            gotostate('vavers');
03386	        }
03387	    }
03388	    if (bases.order!='garder') CherchePointPourCamper();       //si peut pas rappliquer ou peut pas aller vers alarme
03389	    gotostate('investigation');
03390	Vu:
03391		 if (enemy==none || enemy.bisdead)
03392	    {
03393	        ChangeEtat();
03394	    }
03395	    if (bases.bAlerte)
03396	        goto('attaque');
03397		 else if (bARienVu)
03398				goto('Identification');
03399	    enable('enemynotvisible');
03400	PointInterro:
03401	
03402	    //    if (Vsize(pawn.location-enemy.location)>320)
03403	    Interrogation=Spawn(class'interro',self,,bases.location+110*vect(0,0,1));  // INTERRO
03404	    interrogation.setbase(pawn);
03405	    focus=enemy;
03406	/*
03407		 PeeredEnemy=enemy; */
03408	//	 settimer2(0.05,true);
03409	    sleep(FMin(1.5,bases.TempsPasVu*Vsize(pawn.location-enemy.location)*0.00025));
03410		 if (Vsize(pawn.location-enemy.location)>320)
03411	    {
03412		 	  sleep(FMin(1.5,bases.TempsPasVu*Vsize(pawn.location-enemy.location)*0.00025));
03413		 }
03414		// focus=enemy;
03415		// peeredenemy=none;
03416	Identification:
03417	    if (enemy==none || enemy.bisdead)
03418	    {
03419	        ChangeEtat();
03420	    }
03421		 if (bARienVu)
03422		 {
03423			  enable('enemynotvisible');
03424			  bARienVu=false;
03425			  focus=enemy;
03426			  Settimer3(0,false);
03427		 }
03428	    bAVuQuelquechose=true;
03429	    pawn.SetAnimStatus('alert');
03430	    if (enemy==xiii) Playercontroller(XIII.controller).MyHud.LocalizedMessage(class'XIIIDialogMessage', 3, none, none, pawn, "?!! ");
03431	    //son
03432	    pawn.PlaySndPNJOno(pnjono'Onomatopees.hPNJDetect',bases.CodeMesh,bases.NumeroTimbre);//se retourne vers bruit et reste sur place
03433	    if (interrogation!=none)
03434	    {
03435	       interrogation.destroy();
03436	       interrogation=none;
03437	    }
03438	    if (Vsize(pawn.location-enemy.location)>320)
03439	    {
03440	        Interrogation=Spawn(class'exclamation',self,,bases.location+(vector(bases.rotation) cross vect(0,0,1))*6 + 120*vect(0,0,1));
03441	        interrogation.setbase(pawn);
03442	        sleep(fmin(1.5,(Vsize(pawn.location-enemy.location)*bases.TempsIdentification)*0.00025));
03443			  if (Vsize(pawn.location-enemy.location)>320)
03444					sleep(fmin(1.5,(Vsize(pawn.location-enemy.location)*bases.TempsIdentification)*0.00025));
03445	    }
03446		 disable('enemynotvisible');
03447	    bAVuQuelquechose=false;
03448	attaque:
03449		 if (enemy==none || enemy.bisdead)
03450	    {
03451	        ChangeEtat();
03452	    }
03453		 bDisableDamageattitudeto=true;
03454	    if (enemy==XIII) TriggerEvent('XIIIVu', Self, pawn);  //trigger vu
03455	    Pawn.Acceleration = vect(0,0,0);
03456	    Pawn.Velocity = vect(0,0,0);
03457	    if (!genalerte.bAllAlarmsActivated)    ChercheAlarme();  //ALARMEChercheAlarme();  //ALARME
03458	    pawn.rotationrate.yaw=46000;
03459	    finishrotation();
03460	    ChangetoBestWeapon();
03461	    //init vars attaque
03462	    CompteurRecalage=15;    //utilise dans attaque pour savoir si doit se recaler
03463	    gotostate('attaque','initattaque');
03464	}
03465	
03466	// ----------------------------------------------------------------------
03467	// Etat d'attaqueH2H         (enemy!=none)
03468	//
03469	//
03470	// ----------------------------------------------------------------------
03471	state AttaqueH2H
03472	{
03473		ignores hearnoise;
03474	
03475	    event EnemyNotVisible()
03476	    {
03477	        if (LigneVisee(enemy.location, LastSeeingPos))
03478	        {
03479					HalteAuFeu();
03480	            GotoState('TacticalMove','RecoverEnemy');
03481	            return;
03482	        }
03483	        else
03484	        {
03485					HalteAuFeu();
03486	            gotostate('temporise');
03487	            return;
03488	        }
03489	    }
03490	    event Tick(float deltaseconds)
03491	    {
03492	        local int i;
03493	        local iacontroller iacontr;
03494	        local actor nav;
03495	        local AttitudeInfo attitude;
03496	        local float distanceAXIII;
03497	        local int NBAllieEnCouverture;
03498	
03499	        global.tick(deltaseconds);
03500	
03501	        if ((enemy==none) || enemy.bisdead)
03502	        {
03503	            ChangeEtat();
03504	            return;
03505	        }
03506	        if ((level.timeSeconds-Temps_Ref2)>5 && bases.order!='garder')
03507	        {
03508	            Attitude=AttitudeToNMI(enemy);
03509	            if (Attitude==ATTITUDE_Fear)    //actualisation attitude
03510	            {
03511	                HalteAuFeu();
03512	                gotostate('fuite');
03513	                return;
03514	            }
03515	            else if (Attitude==ATTITUDE_Impressed)
03516	            {  //retraite possible si enemmi de dos ou assez loin
03517	                if (((enemy.location-pawn.location) dot vector(enemy.rotation))>0 || Vsize(enemy.location-pawn.location)>600)
03518	                    CherchePointRetraite();
03519	            }
03520	            Temps_Ref2=level.timeseconds;
03521	        }
03522	        if ((Level.timeseconds-Temps_ref)>3)
03523	        {
03524	            //recherche alarme
03525					//log(" cherche alarme"@!genalerte.bAllAlarmsActivated);
03526	            if (!genalerte.bAllAlarmsActivated)    ChercheAlarme();  //ALARMEChercheAlarme();  //ALARME
03527	           //si otage
03528	            if (xiii.bPrisonner && XIII.LHand.pOnShoulder!=none && AllianceLevel(XIII.LHand.pOnShoulder)==1 && enemy==xiii && VSize(pawn.location-enemy.location) < 125)
03529	            {
03530	                if (CHARGE_LES_LOGS) log(pawn$"me colle trop je tir");
03531	                NbCoupsRiposte=(2+bases.agressivite)*1.5;
03532	                NbCoupsRiposte=Min(4,NbCoupsRiposte);
03533	                NbCoupsRiposte=Max(1,NbCoupsRiposte);
03534	            }
03535	      /* [*] a priori que les points
03536					if (bases.order!='garder')
03537	                ChangetoBestWeapon();   //test nouvelle armeChangetoBestWeapon();   //test nouvelle arme*/
03538	
03539	            //Attaquescriptee
03540	            ChercheReseauAttaque();
03541	            Temps_Ref=Level.timeseconds;
03542	        }
03543	    }
03544		event timer3()
03545	   {
03546	      EnemyTargetPos=enemy.location;
03547	      EnemyTargetVelocity=enemy.velocity;
03548			if (bInWaitMode && (Vsize(enemy.location-temp_vect)>50 || VSize(enemy.location-pawn.location)<120))
03549		   {
03550				bInWaitMode=false;
03551				HalteAufeu();
03552				bases.releaseAnimControl(true);
03553				gotostate('attaqueH2H','charge');
03554			}
03555	   }
03556	    event SeeDeadPawn(pawn other)
03557	    {
03558	        if (ChercheBonMatos(other))		//CadavreWithPickup affecte a other dans Cherchebonmatos
03559	        {
03560	            HalteAufeu();
03561	            bDisableEventSeeDeadPawn=true;
03562	            CadavreWithPickup.bDejaFouille=true;
03563	            gotostate('tacticalmove','chercheobjet');
03564	        }
03565	    }
03566	    event UpdateTactics()
03567	    {
03568	        if (Vsize(enemy.location-temp_vect)>50)
03569	        {
03570	            badvancedtactics=false;
03571	            gotostate('AttaqueH2H','charge');
03572	        }
03573	    }
03574	
03575	    function NotifyFiring()
03576	    {
03577			  if (enemy==none)
03578					return;
03579	
03580			  DirectionTir=DirectionDuTir(); //recupere direction du tir avant dispersion
03581	        CheckLineOfFire();
03582	    }
03583	    function DamageAttitudeto(pawn Other, float Damage)
03584	    {
03585	        if (bases.bisdead)
03586	            return;
03587	        //son
03588	        bases.PlaySndPNJOno(pnjono'Onomatopees.hPNJHurt',bases.CodeMesh,bases.NumeroTimbre);
03589	        If (xiii.bPrisonner && XIII.LHand.pOnShoulder!=none && AllianceLevel(XIII.LHand.pOnShoulder)==1 && other==xiii)
03590	        {
03591	           if (CHARGE_LES_LOGS) log(pawn$"je riposte");
03592	           NbCoupsRiposte=(2+bases.agressivite)*1.9;
03593	           NbCoupsRiposte=Min(5,NbCoupsRiposte);
03594	           NbCoupsRiposte=Max(1,NbCoupsRiposte);
03595	        }
03596	    }
03597	
03598	    function ReceiveWarning(pawn shooter, float projspeed,vector firedir)
03599	    {
03600	    }
03601	
03602		function bool LookForNearestPoint()
03603		{
03604			local navigationpoint nav,bestnav;
03605			local float DistancePoint;
03606			local float DistanceNMI;
03607			local int i;
03608	
03609			DistancePoint=1000;  //init
03610			if (enemy==none)
03611				return false;
03612	      btemp_bool=false;
03613			nav = Level.NavigationPointList;
03614	      while (nav != None)
03615	      {
03616				DistanceNMI=vsize(nav.location-enemy.location);
03617	//			log(nav@vsize(nav.location-enemy.location)<300@Vsize(nav.location-pawn.location)>=(pawn.collisionradius*1.2)@(bestnav==none || vsize(nav.location-enemy.location)<vsize(bestnav.location-enemy.location)));
03618				if (DistanceNMI<300)
03619				{
03620					if (Vsize(nav.location-pawn.location)<(pawn.collisionradius*2) && rand(3)<2)
03621					{
03622						 nav = nav.nextNavigationPoint;
03623						continue;
03624					}
03625					if (DistanceNMI<DistancePoint)
03626					{
03627						DistancePoint=DistanceNMI;
03628						Bestnav=nav;
03629					}
03630				}
03631	         nav = nav.nextNavigationPoint;
03632			}
03633			if (BestNav==none)
03634				return false;
03635			if (actorreachable(BestNav))
03636			{
03637				btemp_bool=true;
03638				movetarget=BestNav;
03639				return true;
03640			}
03641			else if (findBestPathToward(BestNav))
03642			{
03643				btemp_bool=false;
03644				movetarget=BestNav;
03645				return true;
03646			}
03647			return false;
03648		 }
03649	    function BeginState()
03650	    {
03651	        disable('enemynotvisible');
03652			  //log(pawn@"ajoute perso dans la liste des basesoldierinfight");
03653	        genalerte.SoldierInFightList.length=genalerte.SoldierInFightList.length+1;
03654	        genalerte.SoldierInFightList[genalerte.SoldierInFightList.Length-1]=bases;
03655	        pawn.SetAnimStatus('alert');
03656			  EnemyTargetPos=enemy.location;
03657	    		EnemyTargetVelocity=enemy.velocity;
03658	        if (NiveauAlerte==0)
03659	        {
03660	            s_decAttente();
03661	            s_incAttaque();
03662	        }
03663	        else if (NiveauAlerte==1)
03664	        {
03665	            s_decAlerte();
03666	            s_incAttaque();
03667	        }
03668	        NiveauAlerte=2;
03669			  bARienVu=false;
03670	        Temps_Ref2=level.timeseconds-2;
03671	        Temps_Ref=Temps_Ref2;
03672	        settimer3(Temps_RefreshEnemyPos,true);
03673			//	btemp_bool=false; //sert a savoir si le nearestpoint est directement atteignable ou par chemin
03674	        //***** Var temp *******
03675	        //temp_float=0.0;
03676	        ///temp_vect=vect(0,0,0);  //1) pour garder ancienne position ennemi dans updatetacics 2) dans saut
03677	        //PointDestination=vect(0,0,0);
03678	        //temp_int=0; //utilise pour boucle sur pointchemin
03679	
03680	    }
03681	    function EndState()
03682	    {
03683	        local int i;
03684	
03685	        settimer3(0,false);
03686	        bAdvancedTactics=false;
03687	        bEtatAlerte=true;
03688	        //vire soldierinfightlist
03689			  //log(pawn@"VIRE perso dans la liste ");
03690	        for (i=0;i<genalerte.SoldierInFightList.Length; i++)
03691	        {
03692	            if (genalerte.SoldierInFightList[i] == pawn )
03693	            {
03694						//log(pawn@"JE ME VIRE de la liste des basesoldierinfight");
03695	                genalerte.SoldierInFightList.Remove(i,1);
03696	                break;
03697	            }
03698	        }
03699			  if (bcontrolanimations) bases.releaseanimcontrol();
03700	    }
03701	begin:
03702	    if (CHARGE_LES_LOGS) log(pawn@"Etat attaqueH2H    "$enemy);
03703	    if (enemy==none)
03704	    {
03705	        log(pawn@"ENEMY==none ** ENEMY==none ** ENEMY==none ** ENEMY==none ** ENEMY==none **");
03706	        //enemy=xiii;
03707	    }
03708	    temp_vect=enemy.location;
03709	    focus=enemy;
03710	charge:
03711		 if (CHARGE_LES_LOGS) log(pawn$"charge de melee H2H"@btire);
03712	    if ((enemy==none) || enemy.bisdead)
03713	    {
03714	        ChangeEtat();
03715	    }
03716	    enable('enemynotvisible');
03717	    PointDestination=vect(0,0,1000000);
03718	    temp_float=Vsize(enemy.location - pawn.location);
03719	
03720	        if (Vsize((enemy.location - pawn.location)*vect(1,1,0)) > (pawn.collisionradius+enemy.collisionradius +50))
03721	        {
03722	            PointDestination= pawn.location+(enemy.location - pawn.location)*(Temp_float-
03723	                    (pawn.collisionradius+enemy.collisionradius))/Temp_float;
03724	            if (!ActorReachable(enemy))
03725	            {
03726						if (FindBestPathToward(enemy))
03727	               {
03728	                   //log(pawn$"je cherche reseau");
03729	                   goto('GoToEnemyPosByPath');
03730	               }
03731	               else
03732	               {
03733							 if (LookForNearestPoint() )
03734							 {
03735								   //log(pawn$"je vais au point le plus proche");
03736									goto('GoTONearestPoint');
03737							 }
03738							 else
03739							 {
03740		                   //log(pawn$"je suis archi crampe c'est inextricable");
03741								 goto('WaitHere');
03742							}
03743	               }
03744	            }
03745	        }
03746	DeplacementCharge:
03747	        if (CHARGE_LES_LOGS) log(pawn$"DeplacementChargeH2H "$PointDestination!=vect(0,0,1000000));
03748	        if (PointDestination!=vect(0,0,1000000))
03749	        {
03750	            //HalteAuFeu();
03751	            bAdvancedTactics=true;
03752					MoveTo(PointDestination,enemy);
03753	            bAdvancedTactics=false;
03754	            temp_vect=enemy.location;
03755	        }
03756	KickH2H:
03757	     if (CHARGE_LES_LOGS) log(pawn@"KickH2H"@btire@bfire);
03758		 bInWaitMode=true;
03759	     pawn.velocity=vect(0,0,0);
03760	     pawn.acceleration=vect(0,0,0);
03761		  temp_vect=enemy.location;
03762	     fireenemy();
03763	     sleep(1);
03764	     if (Interrogation!=none)
03765	     {
03766	        Interrogation.destroy();
03767	        Interrogation=none;
03768	     }
03769		  bInWaitMode=false;
03770		  HalteAufeu();
03771	     goto('charge');
03772	GoToEnemyPosByPath:
03773	     if (CHARGE_LES_LOGS) log(pawn$"ReseauAttaqueH2H dans $$$$$$$$$$$$$$$$$$$$$ ");
03774	     if (Vsize(enemy.location-pawn.location)>( pawn.collisionradius+enemy.collisionradius +10))
03775	     {
03776	         While (movetarget!=none)
03777	         {
03778					 focus=none;
03779					 focalpoint=(Movetarget.location-pawn.location)*10000+pawn.location;
03780	             MoveToward(MoveTarget,none);
03781					 if (Vsize(Movetarget.location-pawn.location)>50)
03782					 {
03783						  log(pawn@"je suis archi crampe en H2H je fais une pause");
03784						  goto('WaitHere');
03785						  break;
03786					 }
03787					 if (actorreachable(enemy))
03788					 {
03789						PointDestination= pawn.location+(enemy.location - pawn.location)*(Temp_float-
03790	                    (pawn.collisionradius+enemy.collisionradius +5))/Temp_float;
03791	                goto('DeplacementCharge');
03792						break;
03793					 }
03794	             if (!FindBestPathToward(enemy))
03795						break;
03796	         }
03797	     }
03798	     goto('charge');
03799	GoToNearestPoint:
03800		if (CHARGE_LES_LOGS) log(pawn$"GoToNearestPoint"@movetarget);
03801		if (btemp_bool)
03802	  	{
03803			if (vsize(pawn.location-movetarget.location)>pawn.collisionradius*2)
03804			{
03805				focalpoint=10000*(movetarget.location-pawn.location) +pawn.location;
03806	   	   MoveToward(movetarget,none);
03807			}
03808		}
03809		else
03810		{
03811			 for (temp_int=0;temp_int<16;temp_int++)
03812		    {
03813				 if (routecache[temp_int]==none)
03814					break;
03815				 focalpoint=10000*(routecache[temp_int].location-pawn.location) +pawn.location;
03816		       MoveToward(routecache[temp_int],none);
03817				 if (actorreachable(enemy))
03818				 {
03819						PointDestination= pawn.location+(enemy.location - pawn.location)*(Temp_float-
03820		                    (pawn.collisionradius+enemy.collisionradius +5))/Temp_float;
03821		            goto('DeplacementCharge');
03822						break;
03823				}
03824			 }
03825		}
03826		//log("Vsize(enemy.location-pawn.location)"@Vsize(enemy.location-pawn.location));
03827		if (Vsize(enemy.location-pawn.location)<150)
03828			goto('KickH2H');
03829	WaitHere:
03830		if (CHARGE_LES_LOGS) log(pawn$"WaitHere");
03831	   temp_vect=enemy.location;
03832		bInWaitMode=true;
03833		HalteAufeu();
03834		bases.PlayH2HProvoc();
03835		focus=enemy;
03836		pawn.velocity=vect(0,0,0);
03837		pawn.acceleration=vect(0,0,0);
03838		sleep(1);
03839		if (Vsize(enemy.location-pawn.location)<100)
03840		{
03841			bases.ReleaseAnimControl(true);
03842			bInWaitMode=false;
03843			goto('KickH2H');
03844		}
03845		sleep(1+2*frand());
03846		bases.ReleaseAnimControl(true);
03847		bInWaitMode=false;
03848		goto('charge');
03849	}
03850	// ----------------------------------------------------------------------
03851	// Etat d'attaque         (enemy!=none)
03852	//
03853	//
03854	// ----------------------------------------------------------------------
03855	state Attaque
03856	{
03857	    ignores hearnoise;
03858	
03859	    event Seeplayer(pawn other)
03860	    {
03861	        if (other==enemy)
03862	        {
03863	            Switch (iEtatVaVersStrp)
03864	            {
03865	                case 1: return;
03866	                case 2: fireenemy();
03867	                    return;
03868	            }
03869	        }
03870	        setenemy(XIII);
03871	    }
03872	    event EnemyNotVisible()
03873	    {
03874	        Switch (iEtatVaVersStrp)
03875	        {
03876	            case 1: return;
03877	            case 2: HalteAufeu();
03878	                return;
03879	        }
03880	        if (TenteGrenadage())
03881	        {
03882	            if (bencouverture)
03883	            {
03884	                Switch(bases.skill)
03885	                {
03886	                    Case 1 : Angle_Visee=14; break;
03887	                    Case 2 : Angle_Visee=12; break;
03888	                    Case 3 : Angle_Visee=10; break;
03889	                    Case 4 : Angle_Visee=8; break;
03890	                    Case 5 : Angle_Visee=6; break;
03891	                }
03892	                pawn.shouldcrouch(false);
03893	                bEnCouverture=false;
03894	                GenAlerte.NbAllieEnCouverture--;
03895	            }
03896	            if (iEtatVaVersStrp>1)
03897	            {
03898	                LastStrP.Libere();
03899	                iEtatVaVersStrp=0;
03900	                LastStrP=none;
03901	            }
03902	            HalteAuFeu();
03903	            gotostate('attaque','LanceGrenadeTarget');
03904	            return;
03905	        }
03906	        else if (LigneVisee(enemy.location, LastSeeingPos))
03907	        {
03908					HalteAuFeu();
03909	            GotoState('TacticalMove','RecoverEnemy');
03910	            return;
03911	        }
03912	        else
03913	        {
03914					HalteAuFeu();
03915	            gotostate('temporise');
03916	            return;
03917	        }
03918	    }
03919	    event Tick(float deltaseconds)
03920	    {
03921	        local int i;
03922	        local iacontroller iacontr;
03923	        local actor nav;
03924	        local AttitudeInfo attitude;
03925	        local float distanceAXIII;
03926	        local int NBAllieEnCouverture;
03927	
03928	        global.tick(deltaseconds);
03929	
03930	        if ((enemy==none) || enemy.bisdead)
03931	        {
03932	            ChangeEtat();
03933	            return;
03934	        }
03935	        if (iEtatVaVersStrp>0 || bLanceGrenade)
03936	            return;
03937	        if ((level.timeSeconds-Temps_Ref2)>5 && bases.order!='garder')
03938	        {
03939	            Attitude=AttitudeToNMI(enemy);
03940	            if (Attitude==ATTITUDE_Fear)    //actualisation attitude
03941	            {
03942	                HalteAuFeu();
03943	                gotostate('fuite');
03944	                return;
03945	            }
03946	            else if (Attitude==ATTITUDE_Impressed)
03947	            {  //retraite possible si enemmi de dos ou assez loin
03948	                if (((enemy.location-pawn.location) dot vector(enemy.rotation))>0 || Vsize(enemy.location-pawn.location)>600)
03949	                    CherchePointRetraite();
03950	            }
03951	            Temps_Ref2=level.timeseconds;
03952	        }
03953	        if ((Level.timeseconds-Temps_ref)>3)
03954	        {
03955					Temps_Ref=Level.timeseconds;
03956	            //recherche alarme
03957					//log(" cherche alarme"@!genalerte.bAllAlarmsActivated);
03958	            if (!genalerte.bAllAlarmsActivated)    ChercheAlarme();  //ALARMEChercheAlarme();  //ALARME
03959	            //si otage
03960	            if (xiii.bPrisonner && XIII.LHand.pOnShoulder!=none && AllianceLevel(XIII.LHand.pOnShoulder)==1 && enemy==xiii && VSize(pawn.location-enemy.location) < 125)
03961	            {
03962	                if (CHARGE_LES_LOGS) log(pawn$"me colle trop je tir");
03963	                NbCoupsRiposte=(2+bases.agressivite)*1.5;
03964	                NbCoupsRiposte=Min(4,NbCoupsRiposte);
03965	                NbCoupsRiposte=Max(1,NbCoupsRiposte);
03966	            }
03967	            if (bases.order!='garder')
03968	                ChangetoBestWeapon();   //test nouvelle armeChangetoBestWeapon();   //test nouvelle arme
03969	
03970	            //couverture
03971	            //log(genalerte.SoldierInFightList.length@!pawn.weapon.bmeleeweapon@(float(GenAlerte.NBAllieEnCouverture)/GenAlerte.SoldierInFightList.length)<0.3 && vsize(pawn.location-enemy.location)>500);
03972	            distanceAXIII=vsize(pawn.location-enemy.location);
03973	            NBAllieEnCouverture=genalerte.NBAllieEnCouverture;
03974	            if (bencouverture)
03975	                NBAllieEnCouverture--;
03976	            if (genalerte.SoldierInFightList.length>1 && (float(NBAllieEnCouverture)/GenAlerte.SoldierInFightList.length)<0.3 && distanceAXIII>500 && distanceAXIII<1.5*bases.DistanceAttaque)
03977	            {
03978	                if (!bEnCouverture)
03979						{
03980								//log(pawn@"passe en couverture"@Fasttrace(DirectionTir, WeaponStartTrace-vect(0,0,30)));
03981	                    gotostate('Attaque','Couverture');
03982						}
03983	            }
03984	            else if (bEnCouverture)
03985	            {
03986	                Switch(bases.skill)
03987	                {
03988	                    Case 1 : Angle_Visee=14; break;
03989	                    Case 2 : Angle_Visee=12; break;
03990	                    Case 3 : Angle_Visee=10; break;
03991	                    Case 4 : Angle_Visee=8; break;
03992	                    Case 5 : Angle_Visee=6; break;
03993	                }
03994	                pawn.shouldcrouch(false);
03995	                bEnCouverture=false;
03996	                GenAlerte.NbAllieEnCouverture--;
03997	                gotostate('attaque','charge');
03998	            }
03999	            //Attaquescriptee
04000	            ChercheReseauAttaque();
04001	        }
04002	    }
04003	    event Timer2()
04004	    {
04005	        if (btire)
04006	        {
04007	            bfire=0;
04008	            settimer(0.5,false);
04009	        }
04010	    }
04011	    event timer3()
04012	    {
04013	        EnemyTargetPos=enemy.location;
04014	        EnemyTargetVelocity=enemy.velocity;
04015	        if (bases.order=='garder')
04016	        {
04017	            if (ChangetoBestWeapon() && Pawn.pendingWeapon.bmeleeweapon) //test nouvelle arme et si passe aux points donc ne peut plus garder
04018	            {
04019	                bases.order='tenir';
04020	                gotostate('attaqueH2H','charge');
04021	            }
04022	        }
04023	    }
04024	    event SeeDeadPawn(pawn other)
04025	    {
04026	        if (ChercheBonMatos(other))		//CadavreWithPickup affecte a other dans Cherchebonmatos
04027	        {
04028	            HalteAufeu();
04029	            bDisableEventSeeDeadPawn=true;
04030	            CadavreWithPickup.bDejaFouille=true;
04031	            gotostate('tacticalmove','chercheobjet');
04032	        }
04033	    }
04034	    event UpdateTactics()
04035	    {
04036	            VecteurRecalage=vect(0,0,0);
04037	            VecteurRecalage= PseudoSteering();
04038	            if (VecteurRecalage!=vect(0,0,0) || Vsize(enemy.location-temp_vect)>150)   //l'ennemi a bouge ou steering
04039	            {
04040	                CompteurRecalage=15;
04041	                badvancedtactics=false;
04042	                gotostate('attaque','charge');
04043	            }
04044	    }
04045	    event Trigger(actor Other, pawn EventInstigator)
04046	    {
04047	        local bool bLigneVisee;
04048	        local bool bJump;
04049	        local int i;
04050	
04051	        if (iEtatVaVersStrp>1)
04052	            return;
04053	        //log("trigger"@bases.StrategicPointAttraction);
04054	        LastStrP=StrategicPoint(other);
04055	        if (LastStrP!=none) // STRATEGIC POINTS
04056	        {
04057	            if (frand()*100<=bases.StrategicPointAttraction && Vsize(enemy.location-pawn.location)>400)
04058	            {
04059	                if (LastStrP.FinishJumpPoint!=none)
04060	                {
04061	                    bJump=true;
04062	                }
04063	                Movetarget=none;
04064	                if (Fasttrace(LastStrP.location-vect(0,0,30),pawn.location-vect(0,0,30)))
04065	                {
04066	                    LastStrP.Occupe();
04067	                    if (bjump)
04068	                    {
04069	                        LastStrP.FinishJumpPoint.occupe();
04070	                    }
04071	                    if (iEtatVaVersStrp==1) //va vers point interdemediaire
04072	                    {
04073	                        PointIntermediaire.bAlreadyTargeted=false;
04074	                        if (cansee(enemy)) fireenemy();
04075	                    }
04076	                    gotostate('attaque','vaversStrP');
04077	                }
04078	                else if (FindBestPathToward(LastStrP))
04079	                {
04080	                    LastStrP.Occupe();
04081	                    if (bjump)
04082	                    {
04083	                        LastStrP.FinishJumpPoint.occupe();
04084	                    }
04085	                    for (i=0;i<16;i++)
04086	                    {
04087	                        if (routecache[i]==none)
04088	                            break;
04089	                        PointChemin[i]=routecache[i];
04090	                    }
04091	                    NbPointChemin=i;
04092	                    gotostate('attaque','vaversStrP');
04093	                }
04094	            }
04095	        }
04096	    }
04097	
04098	    function NotifyFiring()
04099	    {
04100			  if (enemy==none)
04101					return;
04102			  if (pawn.weapon.bmeleeweapon)
04103			  {
04104					gotostate('attaqueH2H');
04105					HalteAuFeu();
04106					return;
04107			  }
04108	        DirectionTir=DirectionDuTir(); //recupere direction du tir avant dispersion
04109	        CheckLineOfFire();
04110	        if (btire)//je vais tirer
04111	        {
04112	            //log("pawn.weapon"@pawn.weapon.hasammo()@XIIIWeapon(pawn.weapon).reloadcount@(1.6-vsize(enemy.location-pawn.location)*0.002)>frand()@(1.6-vsize(enemy.location-pawn.location)*0.002));
04113	            if (pawn.weapon.reloadcount==1 && pawn.weapon.default.reloadcount>1)
04114	            {
04115	                if (bases.order!='garder' && (1.6-vsize(enemy.location-pawn.location)*0.002)>frand())
04116	                {
04117	                    bFuitPourreloader=true;
04118	                    Timer_VaRecharger=level.timeseconds;
04119	                    CherchePointReload();
04120	                }
04121	            }
04122	        }
04123	
04124	    }
04125	    function DamageAttitudeto(pawn Other, float Damage)
04126	    {
04127	        if (bases.bisdead)
04128	            return;
04129	        //son
04130	        bases.PlaySndPNJOno(pnjono'Onomatopees.hPNJHurt',bases.CodeMesh,bases.NumeroTimbre);
04131	
04132		     If (xiii.bPrisonner && XIII.LHand.pOnShoulder!=none && AllianceLevel(XIII.LHand.pOnShoulder)==1 && other==xiii)
04133	        {
04134	           if (CHARGE_LES_LOGS) log(pawn$"je riposte");
04135	           NbCoupsRiposte=(2+bases.agressivite)*1.9;
04136	           NbCoupsRiposte=Min(5,NbCoupsRiposte);
04137	           NbCoupsRiposte=Max(1,NbCoupsRiposte);
04138	        }
04139	    }
04140	
04141	    function ReceiveWarning(pawn shooter, float projspeed,vector firedir)
04142	    {
04143	        local float enemyDist;
04144	        local vector X,Y,Z, enemyDir;
04145	
04146	        // AI controlled creatures may duck if not falling
04147	        if (bases.order=='garder' || bEnCouverture || iEtatVaVersStrp>0 || (Enemy == None)
04148	            || (Pawn.Physics == PHYS_Falling) || (Pawn.Physics == PHYS_Swimming) )
04149	            return;
04150	
04151	        if (FRand() > 0.02 * skill)
04152	            return;
04153	
04154	        if (shooter==xiii)
04155	        {
04156	            if (!XIIIWeapon(shooter.weapon).AmmoType.bInstantHit)
04157	            {
04158	                enemyDist = VSize(shooter.Location - Pawn.Location);
04159	                if (enemyDist/projSpeed > 0.11 + 0.15 * FRand())
04160	                {
04161	                    gotostate('TacticalMove','strafe');
04162	                    return;
04163	                }
04164	            }
04165	            else
04166						gotostate('TacticalMove','strafe');
04167	        }
04168	    }
04169	
04170	    function bool SwitchSurGrenade()
04171	    {
04172	        if (pawn.weapon.isa('grenad'))
04173	            return true;
04174	        // ELR Remove Class reference
04175	        //pawn.pendingweapon = XIIIWeapon(pawn.FindInventoryType(class'grenad'));
04176	        Pawn.PendingWeapon = Pawn.Inventory.WeaponChange(4);
04177	        if ( Pawn.PendingWeapon == none )
04178	          Pawn.PendingWeapon = Pawn.Inventory.WeaponChange(20); // try Frag Grenad
04179	        // ELR End
04180	        if (pawn.pendingweapon==none || !pawn.pendingweapon.HasAmmo())
04181	        {
04182	            log(pawn$"          BEN J'AI PAS DE GRENADE  $$$$$$$");
04183	            return false;
04184	        }
04185	        else
04186	        {
04187	            Pawn.Weapon.PutDown();
04188	            return true;
04189	        }
04190	    }
04191	    function GrenadeTarget ActiveGrenadeTarget()
04192	    {
04193	        local GrenadeTarget GrenT;
04194	        local int i;
04195	
04196	        For(i=0;i<level.game.GrenadeTargetList.Length;i++)
04197	        {
04198	            grent=GrenadeTarget(level.game.GrenadeTargetList[i]);
04199	            if (GrenT.bActive)
04200	                return GrenT;
04201	        }
04202	        return none;
04203	    }
04204	    function bool TenteGrenadage()
04205	    {
04206	        local GrenadeTarget GrenT;
04207	        local inventory GRE;
04208	
04209	        if (enemy.base==none)
04210	            return false;
04211	        // ELR No more cast/Class ref to grenad
04212	//        if ( (grenad(pawn.weapon) != none) && pawn.weapon.hasammo() )
04213	        if ( (pawn.weapon != none) && ((Pawn.Weapon.InventoryGroup == 4) || (Pawn.Weapon.InventoryGroup == 20)) && pawn.weapon.hasammo() )
04214	        {
04215	            GrenT=ActiveGrenadeTarget();
04216	            if (GrenT!=none)
04217	                if (Vsize(GrenT.location-pawn.location)<500 && Vsize(GrenT.location-pawn.location)>300 && FastTrace(GrenT.location))
04218	                {
04219	                    return true;
04220	                }
04221	                if (Vsize(enemy.location-pawn.location)<1200 && Vsize(enemy.location-pawn.location)>200 && FastTrace(enemy.location+vect(0,0,80),enemy.location) && FastTrace(enemy.location+vect(0,0,80),pawn.eyeposition()+pawn.location))
04222	                    return true;
04223	        }
04224	        else
04225	        {
04226	            // ELR Remove Class reference
04227	            //GRE=pawn.FindInventoryType(class'grenad');
04228	            GRE = Pawn.Inventory.WeaponChange(4);
04229	            if ( GRE == none )
04230	              GRE = Pawn.Inventory.WeaponChange(20); // try Frag Grenad
04231	            // ELR End
04232	            if (GRE==none)
04233	                return false;
04234	            GrenT=ActiveGrenadeTarget();
04235	            if (GrenT!=none)
04236	                if (Vsize(GrenT.location-pawn.location)<500 && Vsize(GrenT.location-pawn.location)>300 && FastTrace(GrenT.location))
04237	                {
04238	                    return true;
04239	                }
04240	                //log("tente grenadage "@FastTrace(enemy.location+vect(0,0,80),enemy.location));
04241	                if (Vsize(enemy.location-pawn.location)<1200 && Vsize(enemy.location-pawn.location)>200 && FastTrace(enemy.location+vect(0,0,80),enemy.location) && FastTrace(enemy.location+vect(0,0,80),pawn.eyeposition()+pawn.location))
04242	                    return true;
04243	        }
04244	        return false;
04245	    }
04246	
04247	    function BeginState()
04248	    {
04249	        disable('enemynotvisible');
04250			  //log(pawn@"ajoute perso dans la liste des basesoldierinfight");
04251	        genalerte.SoldierInFightList.length=genalerte.SoldierInFightList.length+1;
04252	        genalerte.SoldierInFightList[genalerte.SoldierInFightList.Length-1]=bases;
04253	        pawn.SetAnimStatus('alert');
04254			  EnemyTargetPos=enemy.location;
04255	    		EnemyTargetVelocity=enemy.velocity;
04256	        if (NiveauAlerte==0)
04257	        {
04258	            s_decAttente();
04259	            s_incAttaque();
04260	        }
04261	        else if (NiveauAlerte==1)
04262	        {
04263	            s_decAlerte();
04264	            s_incAttaque();
04265	        }
04266	        NiveauAlerte=2;
04267			  bARienVu=false;
04268	        Temps_Ref2=level.timeseconds-2;
04269	        Temps_Ref=Temps_Ref2;
04270	        settimer3(Temps_RefreshEnemyPos,true);
04271	        //***** Var temp *******
04272	        //temp_float=0.0;
04273	        ///temp_vect=vect(0,0,0);  //1) pour garder ancienne position ennemi dans updatetacics 2) dans saut
04274	        //PointDestination=vect(0,0,0);
04275	        //temp_int=0; //utilise pour boucle sur pointchemin
04276	        LastStrP=none;
04277	
04278	    }
04279	    function EndState()
04280	    {
04281	        local int i;
04282	
04283	       pawn.bcanjump=false;
04284	        if (bencouverture)
04285	        {
04286	            Switch(bases.skill)
04287	            {
04288	                Case 1 : Angle_Visee=14; break;
04289	                Case 2 : Angle_Visee=12; break;
04290	                Case 3 : Angle_Visee=10; break;
04291	                Case 4 : Angle_Visee=8; break;
04292	                Case 5 : Angle_Visee=6; break;
04293	            }
04294	            pawn.shouldcrouch(false);
04295	            bEnCouverture=false;
04296	            GenAlerte.NbAllieEnCouverture--;
04297	        }
04298	        settimer3(0,false);
04299	        bAdvancedTactics=false;
04300	        bEtatAlerte=true;
04301	        //vire soldierinfightlist
04302			  //log(pawn@"VIRE perso dans la liste ");
04303	        for (i=0;i<genalerte.SoldierInFightList.Length; i++)
04304	        {
04305	            if (genalerte.SoldierInFightList[i] == pawn )
04306	            {
04307						//log(pawn@"JE ME VIRE de la liste des basesoldierinfight");
04308	                genalerte.SoldierInFightList.Remove(i,1);
04309	                break;
04310	            }
04311	        }
04312	        if (iEtatVaVersStrp>0)
04313	        {
04314	            if (iEtatVaVersStrp==1)
04315	            {
04316	                PointIntermediaire.bAlreadyTargeted=false;
04317	                PointIntermediaire=none;
04318	            }
04319	            else
04320	            {
04321	                LastStrP.Libere();
04322	                if (LastStrP.bAccroupi)
04323	                    pawn.shouldcrouch(false);
04324	                LastStrP=none;
04325	            }
04326	            iEtatVaVersStrp=0;
04327	            LastStrP=none;
04328	        }
04329	
04330	    }
04331	
04332	initattaque:
04333	    pawn.velocity=vect(0,0,0);
04334	    pawn.acceleration=vect(0,0,0);
04335	    if ((enemy==none) || enemy.bisdead)
04336	    {
04337	        ChangeEtat();
04338	    }
04339	    focus=enemy;
04340	    finishrotation();
04341	 	 if (!pawn.weapon.bmeleeweapon)
04342				ChercheReseauAttaque();     //peut passer dans attaque scriptee
04343	
04344	    if (AttitudeToNMI(enemy)==ATTITUDE_FEAR)
04345	    {
04346	        HalteAufeu();
04347	        gotostate('fuite');
04348	    }
04349	    if (bases.bAlerteAmisEnCriant)
04350	    {
04351	        sleep(0.5*frand());
04352	        Interrogation=Spawn(class'XIIIalerteEmitter',self,,pawn.location+vect(0,0,70));
04353	        interrogation.setbase(pawn);
04354	        //son
04355	        //pawn.PlaySndPNJOno(pnjono'Onomatopees.hPNJAlert',bases.CodeMesh,bases.NumeroTimbre);
04356	        genalerte.PoteBeugle(pawn);
04357	    }
04358	begin:
04359		 if (pawn.weapon.bmeleeweapon)
04360		 {
04361			gotostate('attaqueH2H');
04362		 }
04363	    if (CHARGE_LES_LOGS) log(pawn@"Etat attaque    "$enemy);
04364	    if (enemy==none)
04365	    {
04366	        log(pawn@"ENEMY==none ** ENEMY==none ** ENEMY==none ** ENEMY==none ** ENEMY==none **");
04367	        //enemy=xiii;
04368	    }
04369	    temp_vect=enemy.location;
04370	    focus=enemy;
04371	    FireEnemy();
04372	    if (bases.order=='garder')
04373	    {
04374	       enable('enemynotvisible');
04375	       stop;
04376	    }
04377	charge:
04378	    if ((enemy==none) || enemy.bisdead)
04379	    {
04380	        ChangeEtat();
04381	    }
04382	    enable('enemynotvisible');
04383	    //log("est-ce que ca necessite que je bouge???"@CompteurRecalage@CompteurRecalage + Vsize(enemy.location-temp_vect)*(1.0/80.0)> 8-3*bases.agressivite);
04384	    if ((CompteurRecalage + Vsize(enemy.location-temp_vect)*(1.0/80.0)> 8-3*bases.agressivite))
04385	    {
04386	        PointDestination=vect(0,0,1000000);
04387	        temp_float=Vsize(enemy.location - pawn.location);
04388	            PointDestination= pawn.location +VecteurRecalage+(enemy.location-pawn.location)*(Temp_float-bases.DistanceAttaque)/Temp_float;
04389	            if (Vsize(PointDestination-pawn.location)<50 || !FastTrace(PointDestination-vect(0,0,30),pawn.location-vect(0,0,30)) || !LigneVisee(enemy.location,PointDestination))
04390	            {
04391	                CompteurRecalage--;
04392	                //log(pawn@" DEBUG"@"je ne bouge pas en fait");
04393	                PointDestination=vect(0,0,1000000);  //alors bouge pa
04394	                Movetarget=none;
04395	                if (vsize(enemy.location-pawn.location)>bases.DistanceAttaque*1.2 && FindBestPathToward(enemy))
04396	                {
04397	                    for (temp_int=0;temp_int<16;temp_int++)
04398	                    {
04399	                        if (routecache[temp_int]==none)
04400	                            break;
04401	                        PointChemin[temp_int]=routecache[temp_int];
04402	                    };
04403								if (temp_int==1)
04404									NbPointChemin=1;
04405								else
04406							  		NbPointChemin=(Temp_int/2);
04407	                    Pointintermediaire=navigationpoint(RouteCache[NbPointChemin-1]);
04408								if (!Pointintermediaire.bAlreadyTargeted && vsize(Pointintermediaire.location-enemy.location)>80)
04409	                    {
04410									//log(pawn@"poinnnnnnnnnnnnnt intermediaire pas targete"@temp_int@NbPointChemin@RouteCache[NbPointChemin-1]@Pointintermediaire);
04411	                        movetarget=Pointintermediaire;
04412	                        HalteAufeu();
04413	                        Pointintermediaire.bAlreadyTargeted=true;
04414	                        gotostate('attaque','VaVersPointIntermediaire');
04415	                    }
04416	                    else if (RouteCache[NbPointChemin]!=none)
04417	                    {
04418	                        Pointintermediaire=navigationpoint(RouteCache[NbPointChemin]);
04419									//log(pawn@"poinnnnnnnnnnnnnt intermediaire deja targete"@temp_int@NbPointChemin@RouteCache[NbPointChemin-1]@Pointintermediaire);
04420	                        if (!Pointintermediaire.bAlreadyTargeted && vsize(Pointintermediaire.location-enemy.location)>80)
04421	                        {
04422	                            movetarget=Pointintermediaire;
04423	                            HalteAufeu();
04424	                            Pointintermediaire.bAlreadyTargeted=true;
04425	                            NbPointChemin++;
04426	                            gotostate('attaque','VaVersPointIntermediaire');
04427	                        }
04428	                    }
04429	                }
04430	            }
04431	DeplacementCharge:
04432	        //log(pawn$"DeplacementCharge "$PointDestination!=vect(0,0,1000000)$Vsize(PointDestination-pawn.location)>150$FastTrace(PointDestination,pawn.location+pawn.eyeposition()));
04433	        if (PointDestination!=vect(0,0,1000000))
04434	        {
04435	            if (LastStrP!=none)
04436	            {
04437	                LastStrP.Libere();
04438	                iEtatVaVersStrp=0;
04439	                LastStrP=none;
04440	            }
04441	            bAdvancedTactics=true;
04442	            if ((enemy.location-pawn.location) dot (pointdestination-pawn.location)<0)  //c'est que je recule
04443	            {
04444	                MoveTo(PointDestination,enemy,bases.walkingspeed);
04445	            }
04446	            else
04447	            {
04448	                MoveTo(PointDestination,enemy);
04449	            }
04450	            bAdvancedTactics=false;
04451	            CompteurRecalage=0;
04452	            temp_vect=enemy.location;
04453	        }
04454	     }
04455	ContinueFight:
04456	     if (CHARGE_LES_LOGS) log(pawn@"ContinueFight");
04457	
04458	     pawn.velocity=vect(0,0,0);
04459	     pawn.acceleration=vect(0,0,0);
04460	     CompteurRecalage++;
04461	     sleep(1);
04462	     goto('charge');
04463	Couverture:
04464	     bEnCouverture=true;
04465	     GenAlerte.NbAllieEnCouverture++;
04466	     pawn.velocity=vect(0,0,0);
04467	     pawn.acceleration=vect(0,0,0);
04468	     pawn.shouldcrouch(true);
04469	     fireenemy();
04470	     Angle_Visee-=2;
04471	     sleep(2+6*(1-(abs(bases.distanceattaque-vsize(pawn.location-enemy.location))/(bases.distanceattaque))));
04472	     Switch(bases.skill)
04473	     {
04474	         Case 1 : Angle_Visee=14; break;
04475	         Case 2 : Angle_Visee=12; break;
04476	         Case 3 : Angle_Visee=10; break;
04477	         Case 4 : Angle_Visee=8; break;
04478	         Case 5 : Angle_Visee=6; break;
04479	     }
04480	     pawn.shouldcrouch(false);
04481	     bEnCouverture=false;
04482	     GenAlerte.NbAllieEnCouverture--;
04483	     goto('charge');
04484	VaVersPointIntermediaire:
04485	     iEtatVaVersStrp=1;
04486	     HalteAuFeu();
04487	     for (iCompteur=0;iCompteur<NbPointChemin;iCompteur++)
04488	     {
04489	         focalpoint=1000*(PointChemin[iCompteur].location-pawn.location)+pawn.location;
04490	         focus=none;  //focus=none;
04491	         MoveToward(PointChemin[iCompteur],none);
04492	     }
04493	     PointIntermediaire.bAlreadyTargeted=false;
04494	     If (cansee(enemy))
04495	         fireenemy();
04496	     iEtatVaVersStrp=0;
04497	     //log("fin vavers sTrp");
04498	     goto('charge');
04499	VaVersStrP:
04500	     iEtatVaVersStrp=2;
04501	     HalteAuFeu();
04502	     if (movetarget==none)
04503	     {
04504	         focalpoint=1000*(LastStrp.location-pawn.location)+pawn.location;
04505	         focus=none;
04506	         MoveToward(LastStrp,none);
04507	         focus=enemy;
04508	    }
04509	     else
04510	     {
04511	         for (iCompteur=0;iCompteur<NbPointChemin-1;iCompteur++)
04512	         {
04513	             focalpoint=1000*(PointChemin[iCompteur].location-pawn.location)+pawn.location;
04514	             focus=none;
04515	             MoveToward(PointChemin[iCompteur],none);
04516	         }
04517	         MoveToward(LastStrp,enemy); //va vers point en regardant enemy
04518	     }
04519	     if (LastStrP.FinishJumpPoint!=none)
04520	         goto('SauteSurStrP');
04521	     if (LastStrP.bAccroupi)
04522	         pawn.shouldcrouch(true);
04523	     iEtatVaVersStrp=3;
04524	     sleep(2+4*frand());
04525	     if (LastStrP.bAccroupi)
04526	         pawn.shouldcrouch(false);
04527	     iEtatVaVersStrp=0;
04528	     If (cansee(enemy))
04529	         fireenemy();
04530	     //log("fin vavers sTrp");
04531	     goto('charge');
04532	SauteSurStrP:
04533	     //pawn.velocity=vect(0,0,0);
04534	     //pawn.acceleration=vect(0,0,0);
04535	     //sleep(0.5);
04536	     disable('enemynotvisible');
04537	     focalpoint=1000*(LastStrP.FinishJumpPoint.location-LastStrP.location) + pawn.location;
04538	     focus=none;
04539	     pawn.bcanjump=true;
04540	     finishrotation();
04541	     temp_float=sqrt(2*948*(LastStrP.jumpHeight));     //Vz0
04542	     PointDestination=LastStrP.FinishJumpPoint.location-LastStrP.location;
04543	     if (abs(PointDestination.z)<0.1)
04544	         pawn.velocity=vect(1,1,0)*PointDestination*948/(2*temp_float);
04545	     else
04546	         pawn.velocity=vect(1,1,0)*PointDestination*(temp_float/(2*PointDestination.z))*(1-sqrt(1-(2*PointDestination.z*948/(temp_float*temp_float))));
04547	     pawn.jumpz=temp_float;
04548	     pawn.acceleration=vect(0,0,0);
04549	     pawn.Dojump(true);
04550	     pawn.jumpz=420;
04551	     if (LastStrP.FinishJumpPoint.bAccroupi)
04552	         pawn.shouldcrouch(true);
04553	     waitforlanding();
04554	     enable('enemynotvisible');
04555	     pawn.bcanjump=false;
04556	     if (CHARGE_LES_LOGS) log(pawn$"fini saut sur STRP");
04557	     sleep(1+4*frand());
04558	     if (LastStrP.FinishJumpPoint.bAccroupi)
04559	         pawn.shouldcrouch(false);
04560	     iEtatVaVersStrp=0;
04561	     goto('charge');
04562	
04563	LanceGrenadeTarget:
04564	     bLanceGrenade=true;
04565	     focus=enemy;
04566	     disable('EnemyNotVisible');
04567	     disable('seeplayer');
04568	     disable('seemonster');
04569	     if (!SwitchSurGrenade())
04570	         gotostate('temporise');
04571	     if (!bases.bDontCallFriends) pawn.PlaySndPNJOno(pnjono'Onomatopees.hPNJGrenade',bases.CodeMesh,bases.NumeroTimbre);
04572		  sleep(1.2);
04573	WaitGrenadReady:
04574		  sleep(0.2);
04575		  if (!pawn.weapon.isa('grenad') || pawn.weapon.isinstate('active'))
04576				goto('WaitGrenadReady');
04577	     Fireenemy();
04578	     sleep(1);
04579	     ChangetoBestWeapon();
04580	     sleep(0.5);
04581	     bLanceGrenade=false;
04582	     goto('charge');
04583	
04584	}
04585	
04586	// ----------------------------------------------------------------------
04587	//
04588	// TacticalMove        (enemy!=none)
04589	//
04590	// ----------------------------------------------------------------------
04591	state TacticalMove
04592	{
04593	    ignores enemynotvisible,hearnoise;
04594	    event Seeplayer(pawn other)
04595	    {
04596				if (enemy!=none && enemy==other)
04597	            	SeeEnemy();
04598	    }
04599	    event SeeMonster(pawn other)
04600	    {
04601	        if (enemy!=none && enemy==other)
04602	            	SeeEnemy();
04603	    }
04604	    event Tick(float deltaseconds)
04605	    {
04606	        local int i;
04607	        global.tick(deltaseconds);
04608	
04609	        if (enemy==none || enemy.bisdead)
04610	        {
04611	            ChangeEtat();
04612	            return;
04613	        }
04614	        if ((Level.timeseconds-Temps_ref)>3)
04615	        {
04616	            //si otage
04617	            if (XIII.bPrisonner && XIII.LHand.pOnShoulder!=none && AllianceLevel(XIII.LHand.pOnShoulder)==1 && enemy==xiii && VSize(pawn.location-enemy.location) < 250)
04618	            {
04619	                if (CHARGE_LES_LOGS) log(pawn$"me colle trop je tir");
04620	                NbCoupsRiposte=(2+bases.agressivite)*1.5;
04621	                NbCoupsRiposte=Min(4,NbCoupsRiposte);
04622	                NbCoupsRiposte=Max(1,NbCoupsRiposte);
04623	            }
04624	            Temps_Ref=Level.timeseconds;
04625	        }
04626	    }
04627	    event Timer2()
04628	    {
04629	        if (btire)
04630	        {
04631	            bfire=0;
04632	            settimer(0.6,false);
04633	        }
04634	    }
04635	    event Timer3()
04636	    {
04637	        EnemyTargetPos=enemy.location;
04638	        EnemyTargetVelocity=enemy.velocity;
04639	    }
04640	    event Trigger(actor Other, pawn EventInstigator)
04641	    {
04642	    }
04643	    event SeeDeadPawn(pawn other)
04644	    {
04645			 if (ChercheBonMatos(other))		//CadavreWithPickup affecte a other dans Cherchebonmatos
04646	        {
04647	                    HalteAufeu();
04648	            bDisableEventSeeDeadPawn=true;
04649	            CadavreWithPickup.bDejaFouille=true;
04650	            gotostate('tacticalmove','chercheobjet');
04651	        }
04652	    }
04653	    event EnemyNotVisible()
04654	    {
04655	        if (LigneVisee(enemy.location, LastSeeingPos))
04656	        {
04657	            GotoState('TacticalMove','RecoverEnemy');
04658	            return;
04659	        }
04660	        else
04661	        {
04662	            gotostate('temporise');
04663	            return;
04664	        }
04665	    }
04666	    function NotifyFiring()
04667	    {
04668			  if (enemy==none)
04669					return;
04670	        DirectionTir=DirectionDuTir(); //recupere direction du tir avant dispersion
04671	        //decalage par rapport a l'arme
04672	        CheckLineOfFire();
04673	    }
04674	    function DamageAttitudeto(pawn Other, float Damage)
04675	    {
04676	        //son
04677	        bases.PlaySndPNJOno(pnjono'Onomatopees.hPNJHurt',bases.CodeMesh,bases.NumeroTimbre);
04678	
04679	        if (bDisableDamageattitudeto)
04680	            return;
04681	        If (xiii.bPrisonner && XIII.LHand.pOnShoulder!=none && AllianceLevel(XIII.LHand.pOnShoulder)==1 && other==xiii)
04682	        {
04683	            if (CHARGE_LES_LOGS) log(pawn$"je riposte");
04684	            NbCoupsRiposte=(2+bases.agressivite)*1.9;
04685	            NbCoupsRiposte=Min(5,NbCoupsRiposte);
04686	            NbCoupsRiposte=Max(1,NbCoupsRiposte);
04687	        }
04688	    }
04689	    function bool StrafeDestination()  //test both right and left
04690	    {
04691	        local vector pick, pickdir;
04692	        local bool success;
04693	        local float MoveDist;
04694	
04695	        pickdir=(Enemy.location-pawn.location) cross vect(0,0,1);
04696	        pickdir.Z = 0;
04697	        pickdir=normal(pickdir);
04698	        if (Frand()>0.5)
04699	            pickdir *= -1;
04700	
04701	        MoveDist = 150+50* FRand();
04702	        success = TestDirection(100,MoveDist,pickdir, pick);
04703	        if (!success)
04704	        {
04705	            MoveDist = 270;
04706	            success = TestDirection(100,MoveDist,-1*pickdir, pick);
04707	            if (!success)
04708	                return false;
04709	        }
04710	        Destination = pick;
04711	        return success;
04712	    }
04713	
04714	    function bool TestDirectionAvoidingAlly(vector pickdir, out vector pick,basesoldier PoteAEviter)
04715	    {
04716	        local float MoveDist;
04717	
04718	        if (Vsize(PoteAEviter.location - pawn.location)>160)
04719	            pickdir += 0.99*normal(Enemy.location-pawn.location); // pour partir a 45 degres si charge
04720	        else
04721	            pickdir +=0.3*normal(Enemy.location-pawn.location); // pour partir a 80 degres si charge
04722	
04723	        MoveDist=200;
04724	        return TestDirection(110,MoveDist,pickdir, pick);
04725	    }
04726	    function bool TestPasSurLaGauche(basesoldier PoteAEviter)
04727	    {
04728	        local vector pick, pickdir;
04729	
04730	        pickdir=(Enemy.location-pawn.location) cross vect(0,0,1);
04731	        pickdir.Z = 0;
04732	        pickdir=normal(pickdir);
04733	
04734	        if (TestDirectionAvoidingAlly(pickdir, pick,PoteAEviter))
04735	        {
04736	            Destination = pick;
04737	            return true;
04738	        }
04739	        return false;
04740	    }
04741	
04742	    function bool TestPasSurLaDroite(basesoldier PoteAEviter)
04743	    {
04744	        local vector pick, pickdir;
04745	
04746	
04747	        pickdir=(Enemy.location-pawn.location) cross vect(0,0,-1);
04748	        pickdir.Z = 0;
04749	        pickdir=normal(pickdir);
04750	
04751	        if (TestDirectionAvoidingAlly(pickdir, pick,PoteAEviter))
04752	        {
04753	            Destination = pick;
04754	            return true;
04755	        }
04756	        return false;
04757	    }
04758	    function BeginState()
04759	    {
04760	        if (CHARGE_LES_LOGS) log(pawn@"Tactical Move");
04761	        if (NiveauAlerte==0)
04762	        {
04763	            s_decAttente();
04764	            s_incAttaque();
04765	        }
04766	        else if (NiveauAlerte==1)
04767	        {
04768	            s_decAlerte();
04769	            s_incAttaque();
04770	        }
04771	        NiveauAlerte=2;
04772	        bDisableDamageattitudeto=false;
04773	        Temps_Ref=Level.timeseconds-2;
04774	        settimer3(Temps_RefreshEnemyPos,true);
04775	    }
04776	
04777	    function EndState()
04778	    {
04779	        Settimer2(0,false);
04780	        settimer3(0,false);
04781	    }
04782	
04783	begin:
04784	    if (enemy==none)
04785	    {
04786	        log(pawn@"ENEMY==none ** ENEMY==none ** ENEMY==none ** ENEMY==none ** ENEMY==none **");
04787	        //enemy=xiii;
04788	    }
04789	    if ((enemy==none) || enemy.bisdead)
04790	        ChangeEtat();
04791	Strafe:
04792	    if (CHARGE_LES_LOGS) log(pawn@"Tactical Move STRAFE");
04793	    If (StrafeDestination())
04794	    {
04795	        HalteAuFeu();
04796	        MoveTo(Destination,enemy,VitesseDeplacements);
04797	    }
04798	    gotostate('attaque');
04799	PositionTirSurGauche:
04800	    if (CHARGE_LES_LOGS) log(pawn$"Pas sur la gauche");
04801	    CompteurRecalage=15;
04802	    If (pote!=none && !pote.bisdead && TestPasSurLaGauche(pote))
04803	    {
04804	        MoveTo(Destination,enemy,VitesseDeplacements);
04805	    }
04806	    else
04807	    {
04808	        focus=enemy;
04809	        sleep(2);
04810	
04811	    }
04812	    gotostate('attaque');
04813	PositionTirSurDroite:
04814	    if (CHARGE_LES_LOGS) log(pawn$"Pas sur la droite");
04815	    CompteurRecalage=15;
04816	    If (pote!=none && !pote.bisdead && TestPasSurLaDroite(pote))
04817	    {
04818	        MoveTo(Destination,enemy,VitesseDeplacements);
04819	    }
04820	    else
04821	    {
04822	        focus=enemy;
04823	        sleep(2);
04824	    }
04825	    gotostate('attaque');
04826	ChercheObjet_ContourneObstacle:
04827	    MoveTo(destination,none,1.0);
04828	ChercheObjet:
04829	    if (CadavreWithPickup==none || CadavreWithPickup.weapon==none) //blindage
04830	        gotostate('attaque');
04831	    if (CHARGE_LES_LOGS) log(pawn@"Tactical Move CHERCHE OBJET");
04832	    settimer2(0,false);
04833	    bDisableDamageattitudeto=true;
04834	    focus=none;
04835	    focalpoint=CadavreWithPickup.location;
04836	    MoveTo(CadavreWithPickup.location,none);
04837	    pawn.acceleration=vect(0,0,0);
04838	    pawn.velocity=vect(0,0,0);
04839		 sleep(0.2);
04840	    bases.PlaySearchGround();
04841	    sleep(0.8); //temps attente accroupi
04842	    bases.ReleaseAnimControl();
04843		 if (CadavreWithPickup==none || CadavreWithPickup.weapon==none || !CadavreWithPickup.weapon.hasammo())
04844	    		gotostate('attaque');
04845	    PlaySound(class<WeaponPickup>(CadavreWithPickup.weapon.pickupclass).Default.PickupSound);
04846		 CadavreWithPickup.weapon.DetachFromPawn(CadavreWithPickup);
04847		 WeaponOnGround=CadavreWithPickup.weapon;
04848		 if (CadavreWithPickup.Shadow != none )
04849	    {
04850	      CadavreWithPickup.Shadow.bShadowIsStatic = false;
04851	      CadavreWithPickup.SetTimer2(0.2, false);
04852	    }
04853		 WeaponOnGround.Transfer(pawn);
04854	    focus=enemy;
04855	    ChangetoBestWeapon();
04856	    sleep(1.2);
04857	    bDisableEventSeeDeadPawn=false;
04858	    gotostate('attaque');
04859	RecoverEnemy:
04860	    if (CHARGE_LES_LOGS) log(pawn$"recover enemy");
04861	    if ((enemy==none) || enemy.bisdead)
04862	    {
04863	        changeEtat();
04864	    }
04865	    HidingSpot = Pawn.Location;
04866	    Destination = LastSeeingPos + 1 * Pawn.CollisionRadius * Normal(LastSeeingPos -Pawn.Location);
04867	    MoveTo(Destination, Enemy,1.0);
04868	    if (!Pawn.Weapon.bMeleeWeapon && LigneVisee(Enemy.location,pawn.location) && (vsize(enemy.location-pawn.location)<(bases.DistanceAttaque-200)))
04869	    {
04870	        focus=enemy;
04871	        FireEnemy();
04872	        pawn.velocity=vect(0,0,0);
04873	        Pawn.Acceleration = vect(0,0,0);
04874	        if (Frand()<0.2)
04875	            Sleep(Fmax(4.0,XIIIWeapon(pawn.weapon).shottime*(2.25+Rand(2))));
04876	        else
04877	            Sleep(Fmax(4.0,XIIIWeapon(pawn.weapon).shottime*1.25));
04878	        if (FRand() > (1+bases.agressivite-0.1)*0.5 && Vsize(HidingSpot-pawn.location)<300)
04879	        {
04880	            Destination = HidingSpot + 2*Pawn.CollisionRadius * Normal(HidingSpot - Pawn.Location);
04881	            HalteAuFeu();
04882	            MoveTo(Destination,enemy,VitesseDeplacements);
04883	        }
04884	    }
04885	    if ((Enemy != None) && !LigneVisee(Enemy.location,pawn.location) && FastTrace(Enemy.Location, LastSeeingPos) )
04886	    {
04887	        sleep(1+1.5*Frand());
04888	        goto('recoverenemy');
04889	    }
04890	    else
04891	    {
04892	        gotostate('attaque');
04893	    }
04894	}
04895	
04896	// ----------------------------------------------------------------------
04897	//  Chasse         (enemy!=none)
04898	//
04899	//
04900	// ----------------------------------------------------------------------
04901	state Chasse
04902	{
04903	    ignores EnemyNotVisible,hearnoise;
04904	
04905	    event Seeplayer(pawn other)
04906	    {
04907	        if (enemy!=none && enemy==other)
04908	            	SeeEnemy();
04909	    }
04910	    event SeeMonster(pawn other)
04911	    {
04912	        if (enemy!=none && enemy==other)
04913	            	SeeEnemy();
04914	    }
04915	    event SeeDeadPawn(pawn other)
04916	    {
04917			  if (ChercheBonMatos(other))		//CadavreWithPickup affecte a other dans Cherchebonmatos
04918	        {
04919	            HalteAufeu();
04920	            bDisableEventSeeDeadPawn=true;
04921	            CadavreWithPickup.bDejaFouille=true;
04922	            gotostate('tacticalmove','chercheobjet');
04923	        }
04924	    }
04925	    event Trigger(actor Other, pawn EventInstigator)
04926	    {
04927	    }
04928	    event EnemyAcquired()
04929	    {
04930	        //if (NewEnemy==XIII) TriggerEvent('XIIIVu', Self, pawn);  //trigger vu
04931	        focus=enemy;
04932	        gotostate('attaque');
04933	    }
04934	    function PickDestination()
04935	    {
04936	        local NavigationPoint path;
04937	        local actor HitActor;
04938	        local vector HitNormal, HitLocation, nextSpot, ViewSpot;
04939	        local float posZ;
04940	        local bool bCanSeeLastSeen;
04941	        local int i;
04942	
04943	        // If no enemy, or I should see him but don't, then give up
04944	        if ((Level.TimeSeconds-LastSeenTime)>20)
04945			  {
04946					if (CHARGE_LES_LOGS) log(pawn@"plus de 20 s de recheche je repasse en patrouille");
04947	            Enemy = None;
04948			  }
04949	        if (Enemy == None || enemy.bisdead)
04950	        {
04951	            ChangeEtat();
04952	            return;
04953	        }
04954	        if (ActorReachable(Enemy))
04955	        {
04956	            if ( (numHuntPaths < 8) || (Level.TimeSeconds - LastSeenTime < 15)
04957	                || ((Normal(Enemy.Location - Pawn.Location) Dot vector(Pawn.Rotation)) > -0.5) )
04958	            {
04959	                Destination = Enemy.Location;
04960	                MoveTarget = None;
04961	                numHuntPaths++;
04962	            }
04963	            else
04964	            {
04965	                ChangeEtat();
04966	            }
04967	            return;
04968	        }
04969	        numHuntPaths++;
04970	
04971	        ViewSpot = Pawn.Location + Pawn.eyeposition();
04972	        bCanSeeLastSeen = false;
04973	        //[***] probleme de chasse sur etage different
04974	        bCanSeeLastSeen=(FastTrace(LastSeenPos, ViewSpot) && (abs(Lastseenpos.z-viewspot.z)<400));
04975	
04976	        MoveTarget = None;
04977	        if (FindBestPathToward(Enemy))
04978	        {
04979	            if (CHARGE_LES_LOGS) log(pawn@"trouvereseau de chasse"@movetarget@enemy);
04980	            return;
04981	        }
04982	        if (NumHuntPaths > 10)
04983	        {
04984					if (CHARGE_LES_LOGS) log(pawn@"plus de 10 points de chasse je repasse en patrouille");
04985	            ChangeEtat();
04986	            return;
04987	        }
04988	        if (!bTemp_bool)
04989	        {
04990	            Destination = LastSeeingPos;
04991	            bTemp_bool=true;
04992	            if (FastTrace(Enemy.Location, LastSeeingPos))//essaye derniere position vu
04993	                return;
04994	        }
04995	        posZ = LastSeenPos.Z + Pawn.CollisionHeight - Enemy.CollisionHeight;
04996	        nextSpot = LastSeenPos - Normal(Enemy.Velocity) * Pawn.CollisionRadius;
04997	        nextSpot.Z = posZ;
04998	        hitactor=Trace(HitLocation, HitNormal, nextSpot, ViewSpot, false);
04999	        if ((( HitActor==none ) || (XIIIporte(hitactor)!=none)) && (abs(nextspot.z - viewspot.z) < 400))
05000	        {
05001	            Destination = nextSpot;
05002	        }
05003	        else if (bCanSeeLastSeen)
05004			  {
05005	            Destination = LastSeenPos;
05006			  }
05007	        else
05008	        {
05009	            Destination = LastSeenPos;
05010	            if (!FastTrace(LastSeenPos, ViewSpot))
05011	            {
05012	                // check if could adjust and see it
05013	                if (PickWallAdjust(Normal(LastSeenPos - ViewSpot)) || FindViewSpot())
05014	                {
05015	                    GotoState('chasse', 'AdjustFromWall');
05016	                    return;
05017	                }
05018	                /*else if ((VSize(Enemy.Location - Pawn.Location) < 1200  || abs(Lastseenpos.z-viewspot.z) > 400))
05019	                {
05020	                log("llllllllllllllllllllllllllllllllllll");
05021	                GotoState('temporise');
05022	                return;
05023	            }    */
05024	                else
05025	                {
05026	                    if (CHARGE_LES_LOGS) log (pawn@"je n'arrive pas à le chopper je vais me planquer ou repasser en patrouille");
05027	                    if (!cherchePointPourCamper())
05028							  {
05029									gotostate('chasse','WaitToSeenIt');
05030							  }
05031							  return;
05032	                 }
05033	            }
05034	        }
05035	        LastSeenPos = Enemy.Location;
05036	    }
05037	
05038	    function bool FindViewSpot()
05039	    {
05040	        local vector X,Y,Z;
05041	        local bool bAlwaysTry;
05042	
05043	        GetAxes(Rotation,X,Y,Z);
05044	
05045	        // try left and right
05046	        // if frustrated, always move if possible
05047	        //bAlwaysTry = bFrustrated;
05048	        //bFrustrated = false;
05049	
05050	        if ( FastTrace(Enemy.Location, Pawn.Location + 2 * Y * Pawn.CollisionRadius) )
05051	        {
05052	            Destination = Pawn.Location + 2.5 * Y * Pawn.CollisionRadius;
05053	            return true;
05054	        }
05055	        if ( FastTrace(Enemy.Location, Pawn.Location - 2 * Y * Pawn.CollisionRadius) )
05056	        {
05057	            Destination = Pawn.Location - 2.5 * Y * Pawn.CollisionRadius;
05058	            return true;
05059	        }
05060	        return false;
05061	    }
05062	
05063	    function BeginState()
05064	    {
05065	        if (NiveauAlerte==0)
05066	        {
05067	            s_decAttente();
05068	            s_incAttaque();
05069	        }
05070	        else if (NiveauAlerte==1)
05071	        {
05072	            s_decAlerte();
05073	            s_incAttaque();
05074	        }
05075	        NiveauAlerte=2;
05076	        //bTemp_bool=false; pas utilise
05077	        if (CHARGE_LES_LOGS) log(pawn@"ETAT  hunting");
05078	    }
05079	    function EndState()
05080	    {
05081	    }
05082	
05083	AdjustFromWall:
05084	    if (CHARGE_LES_LOGS) log(pawn@"adjustfromwall");
05085	    MoveTo(Destination, MoveTarget);
05086	    Goto('suivre');
05087	
05088	Begin:
05089	    if (enemy==none)
05090	    {
05091	        log(pawn@"ENEMY==none ** ENEMY==none ** ENEMY==none ** ENEMY==none ** ENEMY==none **");
05092	        //enemy=xiii;
05093	    }
05094	    numHuntPaths = 0;
05095	suivre:
05096	    PickDestination();
05097	SpecialNavig:
05098	    if (MoveTarget == None)
05099	    {
05100	        focus=none;
05101	        focalpoint=destination;
05102	        MoveTo(destination,none);
05103	    }
05104	    else
05105	    {
05106	        focus=none;
05107	        focalpoint=MoveTarget.location;
05108	        MoveToward(MoveTarget,none);
05109	    }
05110	    Goto('suivre');
05111	WaitToSeenIt:
05112		focus=xiii;
05113		sleep(4+2*frand());
05114		Changeetat();
05115	}
05116	
05117	// ----------------------------------------------------------------------
05118	//Etat temporise        (enemy!=none)
05119	//
05120	//  si l'ennemi s'est planque je vais essayer d'attendre pour le shooter
05121	// ----------------------------------------------------------------------
05122	state temporise
05123	{
05124	    ignores EnemyNotVisible,hearnoise;
05125	
05126	    event Seeplayer(pawn other)
05127	    {
05128	        if (enemy!=none && enemy==other)
05129	            	SeeEnemy();
05130	    }
05131	    event SeeMonster(pawn other)
05132	    {
05133	        if (enemy!=none && enemy==other)
05134	            	SeeEnemy();
05135	    }
05136	    event SeeDeadPawn(pawn other)
05137	    {
05138			  if (ChercheBonMatos(other))		//CadavreWithPickup affecte a other dans Cherchebonmatos
05139	        {
05140	            HalteAufeu();
05141	            bDisableEventSeeDeadPawn=true;
05142	            CadavreWithPickup.bDejaFouille=true;
05143	            gotostate('tacticalmove','chercheobjet');
05144	        }
05145	    }
05146	    event Trigger(actor Other, pawn EventInstigator)
05147	    {
05148	    }
05149	    event EnemyAcquired()
05150	    {
05151	        gotostate('attaque');
05152	    }
05153	    function bool ContinueStakeOut()
05154	    {
05155	        local float relstr;
05156	
05157	        relstr = RelativeStrength(Enemy);
05158	        if ((VSize(Enemy.Location - Pawn.Location) > 450+150*(3+fclamp((relstr-3*bases.agressivite) +frand(),-3,5)))
05159	            || (Level.TimeSeconds - LastSeenTime > 2.5 + FMax(-1.5,0.5+1.5*(FRand()+(relstr-bases.agressivite)))) || (!LigneVisee(LastSeenPos,pawn.location)))
05160	            return false;
05161	        else if (CanStakeOut())
05162	            return true;
05163	        else
05164	            return false;
05165	    }
05166	    function bool CanStakeOut() // CanStakeout : teste si Pawn ET ENEMMI peuvent voir LastSeenPos
05167	    {
05168	        if ( VSize(Enemy.Location - LastSeenPos) > 800 )
05169	            return false;
05170	        return ( FastTrace(LastSeenPos, Pawn.Location + Pawn.Eyeposition())
05171	            && FastTrace(LastSeenPos , Enemy.Location + enemy.Eyeposition()));
05172	    }
05173	
05174	    function BeginState()
05175	    {
05176	         if (enemy==none || enemy.bisdead)
05177				{
05178	 				return;
05179				}
05180	        if (NiveauAlerte==0)
05181	        {
05182	            s_decAttente();
05183	            s_incAttaque();
05184	        }
05185	        else if (NiveauAlerte==1)
05186	        {
05187	            s_decAlerte();
05188	            s_incAttaque();
05189	        }
05190	        NiveauAlerte=2;
05191	        //Var Temp
05192	        btemp_bool = LigneVisee(LastSeenPos,pawn.location);
05193	        if (!btemp_bool || ((Level.TimeSeconds - LastSeenTime > 6) && (FRand() < 0.5)) )
05194	            FindNewStakeOutDir();
05195	    }
05196	    function EndState()
05197	    {
05198	    }
05199	recalporte:
05200	    if (CHARGE_LES_LOGS) log(pawn$"TEMPORISE recalporte");
05201	    MoveTo(LastSeenPos,none);
05202	Begin:
05203	    if (CHARGE_LES_LOGS) log(pawn@"ETAT  temporise");
05204	    if (enemy==none)
05205	    {
05206	        log(pawn@"ENEMY==none ** ENEMY==none ** ENEMY==none ** ENEMY==none ** ENEMY==none **");
05207	        //enemy=xiii;
05208	    }
05209	    pawn.velocity=vect(0,0,0);
05210	    Pawn.Acceleration = vect(0,0,0);
05211	    HalteAuFeu();
05212	Campe:
05213	    if (enemy==none || enemy.bisdead)
05214	    {
05215	        ChangeEtat();
05216	    }
05217	    // Recharge arme auto
05218	    if (XIIIWeapon(pawn.weapon).default.reloadcount!=0 && float(XIIIWeapon(pawn.weapon).reloadcount)/float(XIIIWeapon(pawn.weapon).default.reloadcount)<0.15 && pawn.weapon.HasAmmo())
05219	    {
05220	        pawn.weapon.GotoState('Reloading');
05221	    }
05222	    Focus = None;
05223	    FocalPoint = LastSeenPos;
05224	    FinishRotation();
05225	    if (bases.order=='garder')
05226	    {
05227	        sleep(6);
05228	        changeetat();
05229	    }
05230	    if (ContinueStakeOut())
05231	    {
05232	        Sleep(1+FRand());
05233	        if ((FRand() < 0.3) || !FastTrace(LastSeenPos+vect(0,0,0.9)*Enemy.CollisionHeight, Pawn.Location + vect(0,0,0.8) * Pawn.CollisionHeight))
05234	            FindNewStakeOutDir();
05235	        Goto('campe');
05236	    }
05237	    else
05238	    {
05239	        GotoState('chasse');
05240	    }
05241	}
05242	
05243	
05244	// ----------------------------------------------------------------------
05245	// Fuite             (enemy!=none)
05246	//
05247	//
05248	// ----------------------------------------------------------------------
05249	state Fuite
05250	{
05251	    ignores seeplayer,seemonster,hearnoise;
05252	    event SeeDeadPawn(pawn other)
05253	    {
05254	    	  if (ChercheBonMatos(other))		//CadavreWithPickup affecte a other dans Cherchebonmatos
05255	        {
05256	            HalteAufeu();
05257	            bDisableEventSeeDeadPawn=true;
05258	            CadavreWithPickup.bDejaFouille=true;
05259	            gotostate('tacticalmove','chercheobjet');
05260	        }
05261	    }
05262	    event timer2()
05263	    {
05264	        //actualisation attitude
05265	        if (AttitudeToNMI(enemy)>ATTITUDE_FEAR)
05266	        {
05267	            gotostate('attaque');
05268	            return;
05269	        }
05270	        if (ChangeToBestWeapon())
05271	        {
05272	            gotostate('attaque');
05273	        }
05274	    }
05275	    event Trigger(actor Other, pawn EventInstigator)
05276	    {
05277	    }
05278	    function PickDestination()
05279	    {
05280	        local vector pick, pickdir;
05281	        local bool success;
05282	        local float MoveDist;
05283	
05284	        pickdir = pawn.location-enemy.location;
05285	        if (Pawn.Physics != PHYS_Walking)
05286	        {
05287	            pickdir.Z = 2 * FRand() - 1;
05288	        }
05289	        else
05290	        {
05291	            pickdir.Z = 0;
05292	        }
05293	        pickdir = Normal(pickdir);
05294	
05295	        //chtite combi aleatoire pour fuire dans un cone de 45 deg
05296	        Temp_vect= pickdir cross (vect(0,0,1)); //normale au vecteur direction
05297	        if (Frand() < 0.5)
05298	            pickdir += FRand()*Temp_Vect;
05299	        else
05300	            pickdir -= FRand()*Temp_Vect;
05301	        pickdir = Normal(pickdir);
05302	        MoveDist = 150+DistanceDeplacement*(0.4+0.6*Frand());
05303	        success = TestDirection(150,MoveDist,pickdir, pick);
05304	        if (!success)
05305	        {
05306	            temp_vect=(enemy.location-pawn.location) ;
05307	            pickdir = temp_vect cross (vect(0,0,1));
05308	            if (((vector(pawn.rotation) dot pickdir)*(vector(pawn.rotation) dot temp_vect) < 0) && Frand() > 0.2)
05309	                pickdir *=-1;
05310	            pickdir = Normal(pickdir);
05311	            //chtite combi aleatoire pour fuire dans un cone de 45 deg
05312	            Temp_vect= pickdir cross (vect(0,0,1)); //normale au vecteur direction
05313	            if (Frand() < 0.5)
05314	                pickdir += FRand()*Temp_Vect;
05315	            else
05316	                pickdir -= FRand()*Temp_Vect;
05317	            pickdir = Normal(pickdir);
05318	            MoveDist = 150+DistanceDeplacement*(0.4+0.6*Frand());
05319	            success = TestDirection(150,MoveDist,pickdir, pick);
05320	
05321	        }
05322	        if (success)
05323	        {
05324	            DistNearWall=min(200,DistNearWall+5);
05325	            DistanceDeplacement=min(600,DistanceDeplacement+45);
05326	            Destination = pick;
05327	        }
05328	        else
05329	        {
05330	            DistNearWall=fmax(4*pawn.collisionradius,DistNearWall-40);
05331	            DistanceDeplacement=max(10,DistanceDeplacement-35);
05332	            GotoState('Fuite', 'Bloque');
05333	        }
05334	    }
05335	    event Timer() //appelee une fois dans beginstate
05336	    {
05337	        if (!bTemp_bool)
05338	        {
05339	            CherchePointSafe();
05340	        }
05341	    }
05342	    event enemynotvisible()
05343	    {
05344	        Temps_Ref = level.timeseconds;
05345	        gotostate('fuite','pausing');
05346	    }
05347	
05348	    function BeginState()
05349	    {
05350	        if (NiveauAlerte==0)
05351	        {
05352	            s_decAttente();
05353	            s_incAlerte();
05354	        }
05355	        else if (NiveauAlerte==2)
05356	        {
05357	            s_incAlerte();
05358	            s_decAttaque();
05359	        }
05360	        NiveauAlerte=1;
05361	        Temps_Ref = level.timeseconds;
05362	        MinHitWall += 0.15;
05363	        timer();
05364	        settimer2(5,true);
05365	        //Var Temp
05366	        btemp_bool=false; //utilise pour detection safepoint
05367	    }
05368	
05369	    function EndState()
05370	    {
05371	        MinHitWall -= 0.15;
05372	        settimer2(0,false);
05373	    }
05374	
05375	Begin:
05376	    if (CHARGE_LES_LOGS) log(pawn$"ETAT Fuite."@"enemy"$enemy);
05377	    if (enemy==none)
05378	    {
05379	        log(pawn@"ENEMY==none ** ENEMY==none ** ENEMY==none ** ENEMY==none ** ENEMY==none **");
05380	        //enemy=xiii;
05381	    }
05382	    setTimer(3,true);
05383	Fuite:
05384	    if (enemy==none || enemy.bisdead)
05385	        ChangeEtat();
05386	    enable('enemynotvisible');
05387	    PickDestination();
05388	Moving:
05389	    focalpoint=destination*vect(100,100,0);
05390	    focus=none;
05391	    MoveTo(Destination,None,1.0);
05392	    if (NearWall(DistNearWall))
05393	    {
05394	        DistanceDeplacement=max(10,DistanceDeplacement-10);
05395	        DistNearWall=fmax(2*pawn.collisionradius,DistNearWall-5);
05396	        FinishRotation();
05397	    }
05398	    goto('fuite');
05399	Pausing:
05400	    disable('enemynotvisible');
05401	    pawn.velocity=vect(0,0,0);
05402	    Pawn.Acceleration = vect(0,0,0);
05403	    Sleep(1.0);
05404	    if (enemy.controller.cansee(pawn))
05405	    {
05406	        if ((level.timeseconds - Temps_Ref) > 0.8)
05407	        {
05408	            Temps_Ref = level.timeseconds;
05409	            goto ('fuite');
05410	        }
05411	    }
05412	    else if ((level.timeseconds - Temps_Ref) >6)
05413	        ChangeEtat();
05414	    goto('pausing');
05415	Bloque:
05416	    pawn.velocity=vect(0,0,0);
05417	    Pawn.Acceleration = vect(0,0,0);
05418	    if (VSize(pawn.location-enemy.location) < 300)
05419	    {
05420	        Temps_Ref = level.timeseconds;
05421	        gotostate('attaque');
05422	    }
05423	    Focus = None;
05424	    FocalPoint = Location + 20 * VRand();
05425	    FinishRotation();
05426	    Goto('fuite');
05427	}
05428	// ----------------------------------------------------------------------
05429	// Fuite grenade
05430	//
05431	// Fuit qu'une grenade a la fois et refuis la plus proche quand l'autre a pete
05432	//
05433	// ----------------------------------------------------------------------
05434	state FuiteGrenade
05435	{
05436	    ignores hearnoise;
05437	
05438		 Function CheckNearestGrenad()
05439		 {
05440			local int i;
05441	
05442			for (i=0; i<genalerte.GrenadeList.length; i++)
05443			{
05444				if (genalerte.GrenadeList[i]==none || genalerte.GrenadeList[i].bdeleteme)
05445					continue;
05446				if (Vsize(genalerte.GrenadeList[i].location-pawn.location)<1200 && Fasttrace(genalerte.GrenadeList[i].location,pawn.location))
05447				{
05448					grenade=genalerte.GrenadeList[i];
05449					CherchePlanqueGrenade();
05450					//log("une grenade est tojuourts mecnacnate je recherche safepoint");
05451					return;
05452				}
05453			}
05454		}
05455		 event EnemyNotVisible()
05456	    {
05457	        enable('seemonster');
05458	        enable('seeplayer');
05459	        disable('enemynotvisible');
05460	        halteaufeu();
05461	    }
05462	    event Seeplayer(pawn other)
05463	    {
05464	        if (enemy==other &&  bTemp_bool)
05465	        {
05466	            fireenemy();
05467	            disable('seemonster');
05468	            disable('seeplayer');
05469	            enable('enemynotvisible');
05470	        }
05471			  else
05472			  	  SetEnemy(other);
05473	    }
05474	    event SeeMonster(pawn other)
05475	    {
05476	       if (enemy==other &&  bTemp_bool)
05477	       {
05478	            fireenemy();
05479	            disable('seemonster');
05480	            disable('seeplayer');
05481	            enable('enemynotvisible');
05482	       }
05483			 else
05484			  	SetEnemy(other);
05485	    }
05486	    event EnemyAcquired()
05487	    {
05488	       Interrogation=Spawn(class'exclamation',self,,bases.location+(vector(bases.rotation) cross vect(0,0,1))*6 + 120*vect(0,0,1));
05489	       interrogation.setbase(pawn);
05490	       interrogation.settimer(0.8,false);
05491	        bDejaVu=true;
05492	        disable('seemonster');
05493	        disable('seeplayer');
05494	        enable('enemynotvisible');
05495	        bEtatAlerte=true;
05496	    }
05497	    event timer3()
05498	    {
05499	        if (grenade==none || grenade.bdeleteme)
05500	        {
05501	            grenade=none;
05502	            bTemp_bool=false;
05503				   if (bControlAnimations) bases.ReleaseAnimControl();
05504	            gotostate('fuitegrenade','elleapete');
05505	        }
05506	     /*   else if (Fasttrace(grenade.location,pawn.LOCATION))
05507				{
05508					log("la grenade est toujours en visu je me casse");
05509	            CherchePlanqueGrenade();
05510				}  */
05511	    }
05512	    event updatetactics()
05513	    {
05514	        if (Vsize(grenade.location-pawn.location)>1200)
05515	        {
05516	            gotostate('fuitegrenade','AttendQuellePete');
05517	        }
05518	    }
05519	    event Trigger(actor Other, pawn EventInstigator)
05520	    {
05521	    }
05522	    function PickDestination()
05523	    {
05524	        local vector pick, pickdir;
05525	        local bool success;
05526	        local float MoveDist;
05527	
05528	        pickdir = pawn.location-grenade.location;
05529	  /*      if (Pawn.Physics != PHYS_Walking)
05530	        {
05531	            pickdir.Z = 2 * FRand() - 1;
05532	        }
05533	        else
05534	        {  */
05535	            pickdir.Z = 0;
05536	        //}
05537	        pickdir = Normal(pickdir);
05538	
05539	        //chtite combi aleatoire pour fuire dans un cone de 45 deg
05540	        Temp_vect= pickdir cross (vect(0,0,1)); //normale au vecteur direction
05541	        if (Frand() < 0.5)
05542	            pickdir += FRand()*Temp_Vect;
05543	        else
05544	            pickdir -= FRand()*Temp_Vect;
05545	        pickdir = Normal(pickdir);
05546	        MoveDist = 150+DistanceDeplacement*(0.4+0.6*Frand());
05547	        success = TestDirection(150,MoveDist,pickdir, pick);
05548	        if (!success)
05549	        {
05550	            temp_vect=(grenade.location-pawn.location) ;
05551	            pickdir = temp_vect cross (vect(0,0,1));
05552	            if (((vector(pawn.rotation) dot pickdir)*(vector(pawn.rotation) dot temp_vect) < 0) && Frand() > 0.2)
05553	                pickdir *=-1;
05554	            pickdir = Normal(pickdir);
05555	            //chtite combi aleatoire pour fuire dans un cone de 45 deg
05556	            Temp_vect= pickdir cross (vect(0,0,1)); //normale au vecteur direction
05557	            if (Frand() < 0.5)
05558	                pickdir += FRand()*Temp_Vect;
05559	            else
05560	                pickdir -= FRand()*Temp_Vect;
05561	            pickdir = Normal(pickdir);
05562	            MoveDist = 150+DistanceDeplacement*(0.4+0.6*Frand());
05563	            success = TestDirection(150,MoveDist,pickdir, pick);
05564	
05565	        }
05566	        if (success)
05567	        {
05568	            DistNearWall=min(200,DistNearWall+5);
05569	            DistanceDeplacement=min(600,DistanceDeplacement+45);
05570	            Destination = pick;
05571	        }
05572	        else
05573	        {
05574	            DistNearWall=max(4*pawn.collisionradius,DistNearWall-40);
05575	            DistanceDeplacement=max(10,DistanceDeplacement-35);
05576	            GotoState('FuiteGrenade','Bloque');
05577	        }
05578	    }
05579	
05580	    function BeginState()
05581	    {
05582	        if (CHARGE_LES_LOGS) log(pawn$"ETAT fuiteGrenade"@grenade@enemy@bdejavu);
05583	        if (enemy!=none && !bdejavu)     //cheat si il n'a pas vu ca cible il n'a plus de cible
05584	        {
05585	            enemy=none;
05586	        }
05587	        if (enemy!=none) //deja vu
05588	        {
05589	            disable('seemonster');
05590	            disable('seeplayer');
05591	        }
05592	        disable('enemynotvisible');
05593	        if (NiveauAlerte==0)  //passe en alerte
05594	        {
05595	            s_decAttente();
05596	            s_incAlerte();
05597	            NiveauAlerte=1;
05598	        }
05599			  else if (enemy==none)
05600	        {
05601	            if (NiveauAlerte==2)
05602	            {
05603	                s_decAttaque();
05604	                s_incAlerte();
05605	                NiveauAlerte=1;
05606	            }
05607	        }
05608	        else
05609	        {
05610	            if (NiveauAlerte==1)
05611	            {
05612	                s_incAttaque();
05613	                s_decAlerte();
05614	                NiveauAlerte=2;
05615	            }
05616	        }
05617	        Temps_Ref=level.timeseconds;
05618	        bTemp_bool=false;
05619	        //MinHitWall += 0.15;
05620	        settimer3(0.5,true);
05621				bARienVu=false;
05622	        //--------  Var Temp ------------
05623	        //temp_bool=false //gren,ade lancee par xiii
05624	        //bDisableEventSeeDeadPawn=true;
05625	    }
05626	
05627	    function EndState()
05628	    {
05629			if (bControlAnimations) bases.ReleaseAnimControl();
05630				Halteaufeu();
05631				grenade=none;
05632	        //MinHitWall -= 0.15;
05633	        Pawn.ShouldCrouch(false);
05634	    }
05635	acquisition:
05636	    focus=grenade;
05637	    FinishRotation();
05638	    sleep(0.3);
05639	
05640	Begin:
05641	    CherchePlanqueGrenade();
05642	    //cherche safepoint
05643	Fuite:
05644	    PickDestination();
05645	Moving:
05646	    badvancedtactics=true;
05647	    MoveTo(destination,none, 1.0);
05648	    if (NearWall(DistNearWall))
05649	    {
05650	        DistanceDeplacement=max(10,DistanceDeplacement-10);
05651	        DistNearWall=max(2*pawn.collisionradius,DistNearWall-5);
05652	        FinishRotation();
05653	    }
05654	    sleep(0.04);
05655	    goto('fuite');
05656	
05657	Bloque:
05658	    pawn.velocity=vect(0,0,0);
05659	    Pawn.Acceleration = vect(0,0,0);
05660	    Focus = None;
05661	    FocalPoint = Location + 20 * VRand();
05662	    FinishRotation();
05663	    Goto('fuite');
05664	VaVersSafePoint:
05665	    if (bControlAnimations) bases.ReleaseAnimControl();
05666	    badvancedtactics=true;
05667	    If (MoveActor.bReachable)
05668		 {
05669	         MoveToward(MoveActor.MoveActor,MoveActor.MoveActor);
05670		  	   CheckNearestGrenad();
05671		 }
05672	    else
05673	    {
05674	        for (iCompteur=0;iCompteur<NbPointChemin;iCompteur++)
05675	        {
05676	            focus=none;
05677	            focalpoint=10000*normal(PointChemin[iCompteur].location-pawn.location)+pawn.location;
05678	            Movetoward(PointChemin[iCompteur],none);
05679					CheckNearestGrenad();
05680	        }
05681	    }
05682	    if (SAFEPOINT(MoveActor.MoveActor).baccroupi)
05683	    {
05684	        pawn.shouldcrouch(true);
05685	    }
05686	AttendQuellePete:
05687	    badvancedtactics=false;
05688	    pawn.velocity=vect(0,0,0);
05689	    Pawn.Acceleration = vect(0,0,0);
05690	    if (CHARGE_LES_LOGS) log(pawn@"attend explosion");
05691	    if (enemy!=none && cansee(enemy))
05692	    {
05693	        focus=enemy;
05694	    }
05695	    else
05696	    {
05697	        if (MoveActor.MoveActor!=none)
05698				 focalpoint=1000*vector(MoveActor.MoveActor.rotation)+pawn.location;
05699	        bases.PlayWaitGrenade();
05700	    }
05701	    bTemp_bool=true;
05702	    sleep(4);
05703		 if (bControlAnimations) bases.ReleaseAnimControl();
05704	    bTemp_bool=false;
05705	ElleAPete:
05706	    if (CHARGE_LES_LOGS) log("elle a pete");
05707		 settimer3(0,false);
05708	    if (pawn.biscrouched)
05709	        pawn.shouldcrouch(false);
05710	    if (enemy!=none) //enemy vu donc refight
05711	    {
05712	        if (!genalerte.bAllAlarmsActivated)    ChercheAlarme();  //ALARMEChercheAlarme();  //ALARME
05713	        if (badvancedtactics)    //'jetais en train de me deplacer
05714	        {
05715	            pawn.velocity=vect(0,0,0);
05716	            Pawn.Acceleration = vect(0,0,0);
05717	            focus=enemy;
05718	            finishrotation();
05719	        }
05720				if (SafePointOccupe!=none)
05721				{
05722					SafePointOccupe.timer();
05723					SafePointOccupe=none;
05724				}
05725	        gotostate('attaque');
05726	    }
05727	    else
05728	        gotostate('restesurplace');
05729	}
05730	
05731	// ----------------------------------------------------------------------
05732	//     Investigation    (enemy!=none)
05733	//
05734	//      Se deplace vers enemy pendnat tempsrecherchenmi
05735	//
05736	// ----------------------------------------------------------------------
05737	state Investigation    //temps d'investigation depend du comportement ???
05738	{
05739	    ignores enemynotvisible;
05740	
05741	    event SeePlayer(pawn other)
05742	    {
05743	        if (enemy!=none && enemy==other)
05744	            	SeeEnemy();
05745	    }
05746	    event SeeMonster(pawn other)
05747	    {
05748	        if (enemy!=none && enemy==other)
05749	            	SeeEnemy();
05750	    }
05751	    event hearnoise(float loudness,actor NoiseMaker)
05752	    {
05753		 	  if (NoiseMaker.instigator!=none && NoiseMaker.instigator.controller!=none && NoiseMaker.instigator.controller.isa('CineController2'))
05754			     return;
05755	        if ((weapon(NoiseMaker)!=none || XIIIProjectile(NoiseMaker)!=none) && NoiseMaker.instigator==enemy)
05756	        {
05757	            Gotostate('Investigation','ChercheSurPlace');
05758	        }
05759	    }
05760	    event EnemyAcquired()
05761	    {
05762	        if (enemy==XIII) TriggerEvent('XIIIVu', Self, pawn);  //trigger vu
05763	        bDejaVu=true;
05764	        bWeaponNoise=false;
05765	        bImpactNoise=false;
05766	        bStepNoise=false;
05767	        bCadavreVu=false;
05768	        bPaffe=false;
05769	        disable('seeplayer');
05770	        disable('seemonster');
05771	        Gotostate('Investigation','ContinueUnPeuEtAttaque');
05772	    }
05773	    event timer2()
05774	    {
05775	        changeetat();
05776	    }
05777	    event Trigger(actor Other, pawn EventInstigator)
05778	    {
05779	    }
05780	    event UpdateTactics()
05781	    {
05782	    }
05783	    function bool EnregistrePointsVersEnemy()
05784	    {
05785	        local int NbPoints,i;
05786	
05787	        if (!findbestpathtoward(enemy))
05788	        {
05789	            //log("ne trouve pas de chemin");
05790	            return false;
05791	        }
05792	        NbPoints=0;
05793	        for (i=0;i<3;i++)
05794	        {
05795	            PointsInvestigation[i]=none;
05796	        }
05797	        for (i=0;i<16;i++)
05798	        {
05799	            if (routeCache[i]==none)
05800	                break;
05801	        }
05802	        NbPoints=i;
05803	        if (NbPoints==0)
05804	        {
05805	            //log("pas de point d'investigation");
05806	            return false;
05807	        }
05808	        else if (NbPoints==1)
05809	        {
05810	            PointsInvestigation[0]=routeCache[0];
05811	            return true;
05812	        }
05813	        else if (NbPoints==2)
05814	        {
05815	            PointsInvestigation[0]=routeCache[0];
05816	            PointsInvestigation[1]=routeCache[1];
05817	            return true;
05818	        }
05819	        else if (NbPoints==3)
05820	        {
05821	            PointsInvestigation[0]=routeCache[0];
05822	            PointsInvestigation[1]=routeCache[1];
05823	            PointsInvestigation[2]=routeCache[2];
05824	            return true;
05825	        }
05826	        else
05827	        {
05828	            PointsInvestigation[0]=routeCache[int(NbPoints*0.5)-1];
05829	            PointsInvestigation[1]=routeCache[NbPoints-int(NbPoints*0.25)-1];
05830	            PointsInvestigation[2]=routeCache[NbPoints-int(NbPoints*0.125)-1];
05831	            return true;
05832	        }
05833	    }
05834	    function beginstate()
05835	    {
05836	        //bruit d'impact et cadavre pas gere
05837	        if (NiveauAlerte==0)
05838	        {
05839	            s_decAttente();
05840	            s_incAlerte();
05841	        }
05842	        else if (NiveauAlerte==2)
05843	        {
05844	            s_incAlerte();
05845	            s_decAttaque();
05846	        }
05847	        NiveauAlerte=1;
05848	        pawn.SpineYawControl(true,3000+rand(1000),1.2+1*frand());
05849	        settimer2(bases.TempsRechercheNMI,false);
05850	        if (bDejaVu || bweaponnoise)
05851	            disable('hearnoise');
05852	        //temp_vect utilise pour calcul de position
05853	        //btemp_bool pour savoir si y va en courant
05854	    }
05855	    function endstate()
05856	    {
05857	        pawn.SpineYawControl(false,0,0);
05858	    }
05859	begin:
05860	    if (CHARGE_LES_LOGS) log(pawn@"ETAT Investigation"@enemy);
05861	    if (enemy==none)
05862	    {
05863	        log(pawn@"ENEMY==none ** ENEMY==none ** ENEMY==none ** ENEMY==none ** ENEMY==none **");
05864			  ChangeEtat();
05865	        //enemy=xiii;
05866	    }
05867	
05868	investigation:
05869	    if (fasttrace(enemy.location-vect(0,0,30),pawn.location-vect(0,0,30)))
05870	    {
05871	        // log("je vais directement vers perso");
05872	        temp_vect=enemy.location-pawn.location;
05873	        temp_vect=(vsize(temp_vect)*0.5)*normal(temp_vect)+pawn.location;
05874	        if (fasttrace(temp_vect))
05875	        {
05876	            focus=none;
05877	            focalpoint= 10000*(temp_vect-pawn.location)+pawn.location;
05878	            if (vsize(temp_vect)>800)
05879	            {
05880	                Moveto(temp_vect,none);
05881	            }
05882	            else
05883	            {
05884	                Moveto(temp_vect,none,bases.walkingspeed);
05885	            }
05886	            stop;
05887	        }
05888	    }
05889	    else if (EnregistrePointsVersEnemy())
05890	    {
05891	        // log("je prend les points d'investigation");
05892	        NombreDePointsSkippes=0;
05893	        for (NumeroProchainPoint=0;NumeroProchainPoint<3;NumeroProchainPoint++)
05894	        {
05895	            if (PointsInvestigation[NumeroProchainPoint]==none)
05896	                break;
05897	            temp_vect=enemy.location-PointsInvestigation[NumeroProchainPoint].location;
05898	            if (vsize(temp_vect)>800)      //y va en courant
05899	                btemp_bool=true;
05900	            else
05901	                btemp_bool=false;
05902	            for (temp_int=NombreDePointsSkippes;temp_int<16;temp_int++)
05903	            {
05904	                if (btemp_bool)
05905	                {
05906	                    focalpoint=10000*(routecache[temp_int].location-pawn.location)+pawn.location;
05907	                    Movetoward(routecache[temp_int],none);
05908	                }
05909	                else
05910	                {
05911	                    focalpoint=10000*(routecache[temp_int].location-pawn.location)+pawn.location;
05912	                    Movetoward(routecache[temp_int],none,bases.walkingspeed);
05913	                }
05914	                sleep(1.5+frand());
05915	                if (routecache[temp_int]==PointsInvestigation[NumeroProchainPoint])
05916	                {
05917	                    NombreDePointsSkippes=temp_int+1;
05918	                    break;
05919	                }
05920	            }
05921	        }
05922	        stop;
05923	    }
05924	    else
05925	    {
05926	        if (CHARGE_LES_LOGS) log(pawn@"bug trouve pas de ligne d'investigation ni reseau");
05927	        cherchePointPourCamper();
05928	        sleep(0.04);
05929	        if (CHARGE_LES_LOGS) log(pawn@"n'a pas trouve de safepoint");
05930	        bCampeversSafePoint=true;
05931	        if (!pawn.biscrouched)
05932	            pawn.shouldcrouch(true);
05933	        else
05934	        {
05935	            focus=none;
05936	            focalpoint=10000*vector(pawn.rotation)+pawn.location;
05937	            moveto(pawn.location-200*vector(pawn.rotation),none);
05938	        }
05939	        gotostate('restesurplace');
05940	    }
05941	ChercheSurPlace:
05942	    Focus=enemy;
05943	    sleep(1+frand());
05944	    goto('investigation');
05945	ContinueUnPeuEtAttaque:
05946	    Focus=enemy;
05947	    disable('SeeMonster');
05948	    disable('SeePlayer');
05949	    sleep(0.5);
05950	    gotostate('attaque','initattaque');
05951	}
05952	
05953	// ----------------------------------------------------------------------
05954	//     VaVers
05955	//
05956	//      Se deplace vers MoveActor ou MovePoint
05957	//
05958	// ----------------------------------------------------------------------
05959	
05960	//pas de detection de cadavre
05961	state VaVers
05962	{
05963	    ignores EnemyNotVisible;
05964	
05965	    event Tick(float DeltaTime)
05966	    {
05967	        global.tick(DeltaTime);
05968	        if (bFuitPourreloader && (level.timeseconds-Timer_VaRecharger)>1.5)
05969	        {
05970	            bFuitPourreloader=false;
05971	            gotostate('attaque');
05972	        }
05973	    }
05974		 event Seeplayer(pawn other)
05975	    {
05976				if (!bDejaVu && enemy!=none && enemy==other)
05977	            	SeeEnemy();
05978				else
05979					setenemy(XIII);
05980	    }
05981	    event SeeMonster(pawn other)
05982	    {
05983	        if (!bDejaVu && enemy!=none && enemy==other)
05984	            	SeeEnemy();
05985			  else
05986					setenemy(other);
05987	    }
05988	    event EnemyAcquired()
05989	    {
05990	        bDejaVu=true;
05991	        bVaVersAlarme=false;
05992	        bPotePaffe=false;
05993	        bWeaponNoise=false;
05994	        bFuitPourReloader=false;
05995	        if (enemy==XIII) TriggerEvent('XIIIVu', Self, pawn);  //trigger vu
05996			  if (bAlarmeInstigator && ((pawn.location-enemy.location) dot (MoveActor.MoveActor.location-pawn.location)>0) && Vsize(enemy.location-MoveActor.MoveActor.location)>250)
05997	                return;
05998			  bAdvancedTactics=false;
05999	        Gotostate('Vavers','ContinueUnPeuEtAttaque');
06000	    }
06001	    event Trigger(actor Other, pawn EventInstigator)
06002	    {
06003	    }
06004	    event UpdateTactics()
06005	    {
06006	        // ennemi devant l'alarme donc repasse en attaque
06007	        if (bDejaVu && normal(pawn.location-enemy.location) dot normal(MoveActor.MoveActor.location-enemy.location)<-0.2)
06008	        {
06009	            bAdvancedTactics=false;
06010	            bVaVersAlarme=false;
06011	            genalerte.PoteTargetAlarme(false,MoveActor.MoveActor.tag);
06012	            gotostate('attaque');
06013	            return;
06014	        }
06015	    }
06016	    event hearnoise(float loudness,actor NoiseMaker)
06017	    {
06018	        ActualiseSon(NoiseMaker);
06019	    }
06020	    function ActualiseSon(actor son)
06021	    {
06022			  if (son.instigator!=none && son.instigator.controller!=none && son.instigator.controller.isa('CineController2'))
06023				  return;
06024	        //bruit d'arme prioritaire sur bruitpas
06025	        if (weapon(son)!=none || XIIIProjectile(son)!=none)
06026	        {
06027	            bPotePaffe=false;
06028	            bWeaponNoise=true;
06029	            if (alliancelevel(son.instigator)==1) //pote donc prend son enemy
06030	            {
06031	                enemy=son.instigator.controller.enemy;
06032	                instigator=son.instigator;
06033	            }
06034	            else
06035	            {
06036	                enemy=son.instigator;
06037	                instigator=enemy;
06038	            }
06039	            bFuitPourReloader=false;
06040	            gotostate('acquisition','BruitArme');
06041	        }
06042	    }
06043	    function beginstate()
06044	    {
06045	        //bruit de pas et d'impact pas gere (pas de deplacement)
06046	        //paf et cadavre pas gere (pas de deplacement)
06047	        if (!bPotePaffe)
06048	        {
06049	            disable('hearnoise');
06050	            if (!bWeaponNoise)
06051	            {
06052	                if (bDejaVu)
06053	                {
06054	                    disable('SeeMonster');
06055	                    disable('SeePlayer');
06056	                }
06057	            }
06058	        }
06059			if (CHARGE_LES_LOGS) log(pawn@"ETAT VaVers"@MoveActor.MoveActor@MovePoint.MovePoint@enemy);
06060	        //bpotepaffe ne sont appele que si etat neutre donc
06061	        //a priori bdejavu=false
06062	        //bCampeVersSafePoint declenche que si pas vu donc a priori bdejavu=false
06063	        if (bDejaVu)
06064	        {
06065	            if (NiveauAlerte==0)
06066	            {
06067	                s_decAttente();
06068	                s_incAttaque();
06069	            }
06070	            else if (NiveauAlerte==1)
06071	            {
06072	                s_decAlerte();
06073	                s_incAttaque();
06074	            }
06075	            NiveauAlerte=2;
06076	        }
06077	        else
06078	        {
06079	            if (NiveauAlerte==0)
06080	            {
06081	                s_decAttente();
06082	                s_incAlerte();
06083	            }
06084	            else if (NiveauAlerte==2)
06085	            {
06086	                s_incAlerte();
06087	                s_decAttaque();
06088	            }
06089	            NiveauAlerte=1;
06090	        }
06091	        pawn.rotationrate.yaw=46000;
06092	        //temp_float //utilise pour temps d retournement
06093	        //bDisableEventSeeDeadPawn=true;
06094	    }
06095		function endstate()
06096		{
06097			local int i;
06098			//Pawn.bAvoidLedges = false;
06099			if (EtatNeutre == 'tenir' && bVaVersAlarme)
06100			{
06101			   focalpoint=-1000*vector(pawn.rotation)+pawn.location;
06102			}
06103			if (bAlarmeInstigator && Porteouverte==none)
06104			{
06105				bAlarmeInstigator=false;
06106			   if (triggeralarme(MoveActor.MoveActor)!=none)
06107			      genalerte.PoteTargetAlarme(false,MoveActor.MoveActor.tag);
06108			}
06109			if (bInterruptStateToOpenDoor && icompteur<nbpointchemin)   //remise a jour du reseau avant de passer en ouverture de porte
06110			{
06111				nbpointchemin-=icompteur;
06112				for (i=0;i<nbpointchemin;i++)
06113				{
06114					PointChemin[i]=PointChemin[icompteur+i];
06115				}
06116			}
06117			if (bControlAnimations) bases.ReleaseAnimControl();
06118		}
06119	initalarme:
06120	    //log(pawn@"initalrame");
06121	    if (bAlarmeInstigator)
06122	    {
06123	   	  TriggerEvent('CoursVersAlarme', Self, pawn);  //trigger de debut de course vers alarme
06124	        if (triggeralarme(MoveActor.MoveActor)==none)
06125	            log(pawn@"BUGGGGGGGGGGGGGGGGGGGGG  !!!!!!!!!!!!!!!!!!!!!!!!!!! ALARME");
06126	        focus=xiii;
06127	        sleep(1.8);  //petit temps de latence avant de declencher l'alarme
06128	        badvancedtactics=true;
06129	    }
06130	    //ca de vavers: cadavre, bruit pas, bruit arme, alarme, pote en fight, pote paffe
06131	begin:
06132	
06133	Deplacement:
06134	  // log(pawn@"Deplacement"@MoveActor.MoveActor@MoveActor.bReachable);
06135	    if (MoveActor.MoveActor!=none)
06136	    {
06137	        If (MoveActor.bReachable)
06138	        {
06139	            focus=none;
06140	            focalpoint=10000*(MoveActor.MoveActor.location-pawn.location)+pawn.location;
06141	            Temp_float=normal(MoveActor.MoveActor.location-pawn.location) dot normal(vector(pawn.rotation));
06142	            sleep(8000*(1-Temp_float)/pawn.rotationrate.yaw);
06143	            MoveToward(MoveActor.MoveActor,none);
06144	        }
06145	        else
06146	        {
06147	            for (iCompteur=0;iCompteur<NbPointChemin;iCompteur++)
06148	            {
06149	                focus=none;
06150	                focalpoint=PointChemin[iCompteur].location;
06151	                Movetoward(PointChemin[iCompteur],none);
06152	            }
06153	        }
06154	    }
06155	    else
06156	    {
06157	        If (MovePoint.bTraceable)
06158	        {
06159	            focus=none;
06160	            focalpoint=MovePoint.MovePoint+pawn.location;
06161	            Temp_float=normal(MovePoint.MovePoint-pawn.location) dot normal(vector(pawn.rotation));
06162	            sleep(8000*(1-Temp_float)/pawn.rotationrate.yaw);
06163	            MoveTo(MovePoint.MovePoint,none);
06164	        }
06165	        else
06166	        {
06167	            for (iCompteur=0;iCompteur<NbPointChemin;iCompteur++)
06168	            {
06169	                focus=none;
06170	                focalpoint=10000*(PointChemin[iCompteur].location-pawn.location)+pawn.location;
06171	                Moveto(PointChemin[iCompteur].location,none);
06172	            }
06173	            focus=none;
06174	            focalpoint=10000*(MovePoint.movepoint-pawn.location)+pawn.location;
06175	            Moveto(MovePoint.movepoint,none);
06176	        }
06177	    }
06178	    if (bAlarmeInstigator)
06179	    {
06180	        if (Vsize(MoveActor.MoveActor.location-pawn.location)<4*pawn.collisionradius)
06181			  {
06182					badvancedtactics=false;
06183	        		goto('declenchealarme');
06184				}
06185				else   //crampe
06186				{
06187	            bALarmeInstigator=false;
06188	            bVaVersAlarme=false;
06189	            genalerte.PoteTargetAlarme(false,MoveActor.MoveActor.tag);
06190				}
06191	    }
06192	    //si dernier point safepoint alors on s'oriente
06193	    if (SAFEPOINT(MoveActor.MoveActor)!=none && SAFEPOINT(MoveActor.MoveActor).baccroupi)
06194	    {
06195	        pawn.shouldcrouch(true);
06196	    }
06197	    if (nextstate=='')
06198	        log(pawn@" ALAAAAAAAAAAAAAAAAAAARME GROS BUG");
06199	
06200	    Gotostate(nextstate);
06201	ContinueUnPeuEtAttaque:
06202	    //log(pawn@"ContinueUnPeuEtAttaque");
06203	    Focus=enemy;
06204	    pawn.velocity=vect(0,0,0);
06205	    pawn.acceleration=vect(0,0,0);
06206	    disable('SeeMonster');
06207	    disable('SeePlayer');
06208	    sleep(0.5);
06209	    gotostate('attaque','initattaque');
06210	Declenchealarme:
06211		//log("delcelcnhe alarme");
06212		 Bases.takeanimcontrol(false);
06213		 bases.PlayManip();
06214	    pawn.velocity=vect(0,0,0);
06215	    pawn.acceleration=vect(0,0,0);
06216	    sleep(TempsDeclencheAlarme*0.3);
06217		 Bases.bBlockNextOuahOuah=true;
06218		 pawn.PlaySndPNJOno(pnjono'Onomatopees.hPNJAlert',bases.CodeMesh,bases.NumeroTimbre);
06219		 sleep(TempsDeclencheAlarme*0.7);
06220		 Bases.releaseanimcontrol(false);
06221		 sleep(0.1);
06222		 bcontrolanimations=false; //relache anim quand finie
06223	    TriggerEvent('FinCourseVersAlarme', Self, pawn);  //fin de course vers alarme
06224	    genalerte.PoteDeclencheAlarme(pawn,triggeralarme(MoveActor.MoveActor));
06225	    sleep(0.5);
06226	    /*if (EtatNeutre == 'tenir')
06227	    {
06228	    PointTenirPos=pawn.location;
06229	    PointTenirRot=pawn.rotation;
06230	     } */
06231	    Gotostate(nextstate);
06232	}
06233	
06234	// ----------------------------------------------------------------------
06235	//Etat OuvrePorte
06236	//
06237	// Si a un enemy et le voit repasse direct en attaque
06238	// ----------------------------------------------------------------------
06239	state OuvrePorte
06240	{
06241	    ignores EnemyNotVisible;
06242	
06243		event SeePlayer (pawn other)
06244	   {
06245	      if (enemy!=none && enemy==other)
06246			{
06247				bDejaVu=true;
06248	        	SeeEnemy();
06249			}
06250			else
06251			{
06252				if (setenemy(XIII))
06253					bdejavu=true;
06254			}
06255	   }
06256	   event SeeMonster(pawn other)
06257	   {
06258			if (enemy!=none && enemy==other)
06259			{
06260				bDejaVu=true;
06261	        	SeeEnemy();
06262			}
06263			else
06264			{
06265				if (setenemy(other))
06266					bdejavu=true;
06267			}
06268	    }
06269	    event EnemyAcquired()
06270	    {
06271	        if (niveaualerte<2)
06272	            gotostate('acquisition');
06273	         else if (!balarmeinstigator)
06274			   {
06275					if (prevstate=='attaquescriptee')
06276					{
06277						if (movetarget!=none)  //reprend reseau vers attackpoint
06278						{
06279							NextRouteCachePoint=iCompteur;
06280							gotostate('attaquescriptee','RepriseVaVersAttackPoint');
06281						}
06282						else ///y va directement
06283							gotostate('attaquescriptee','VaVersAttackPoint');
06284					}
06285					else
06286					{
06287				      gotostate('attaque','initattaque');
06288					}
06289				}
06290	    }
06291	    singular event bool notifybump(actor other)
06292	    {
06293	        if (XIIIporte(other)!=none && porteouverte!=other)
06294	        {
06295	            porteouverte=XIIIporte(other);
06296	            gotostate('ouvreporte','opendoor');
06297	            return true;
06298	        }
06299	        else
06300	            return false;
06301	    }
06302	    event HearNoise(float Loudness, Actor NoiseMaker)
06303	    {
06304	        if (TestSonEntendu(NoiseMaker))
06305	            enemyacquired();
06306	    }
06307	
06308	    event Trigger(actor Other, pawn EventInstigator)
06309	    {
06310	    }
06311	
06312	    singular function DamageAttitudeTo(pawn Other, float Damage)
06313	    {
06314	        //son
06315	        bases.PlaySndPNJOno(pnjono'Onomatopees.hPNJHurt',bases.CodeMesh,bases.NumeroTimbre);
06316	        if (setenemy(other))
06317	        {
06318	            //genalerte.potepaffe(pawn);
06319	            bPaffe=true;
06320	        }
06321	    }
06322	    function beginstate()
06323	    {
06324			 if (CHARGE_LES_LOGS) log(pawn@"ETAT ouvre porte"@enemy);
06325	       //NiveauAlerte=0; GARDE NIVEAU PRECEDENT
06326	        if (niveauAlerte>0)
06327	        {
06328	            disable('hearnoise');
06329	        }
06330	        SetTimer(0,false);
06331	        //Var Temp
06332	        result=false; //savoir si pas de recul deja fait
06333	        btemp_bool=false; //utilise pour ne pas lancer 2 fois anim ouverture apre recalage
06334	        DoorP=none; //utilise pour savoir si les doorpoints sont bons
06335	        if (porteouverte.DoorPoint1!=none && porteouverte.doorPoint2!=none) //prend doorpoint1 comme point destination
06336	        {
06337				//	log(porteouverte.DoorPoint1@porteouverte.DoorPoint2);
06338	            DoorP=porteouverte.DoorPoint2;
06339	            if ((porteouverte.DoorPoint2.location-porteouverte.DoorPoint1.location) dot vector(pawn.rotation)>0)
06340	            {
06341	                porteouverte.DoorPoint2=porteouverte.DoorPoint1;
06342	                porteouverte.DoorPoint1=doorpoint(DoorP);
06343	            }
06344				//	log(porteouverte.DoorPoint1@porteouverte.DoorPoint2);
06345	        }
06346	        //bDisableEventSeeDeadPawn=true;
06347	    }
06348	    function Endstate()
06349	    {
06350	        /*if (!bWaitForMover)
06351	            Porteouverte.delaytime-=0.8;*/
06352	        bWaitForMover=false;
06353	        Porteouverte=none;
06354			  if (bControlAnimations) bases.ReleaseAnimControl(true);
06355	    }
06356	begin:
06357	    pawn.velocity=vect(0,0,0);
06358	    pawn.Acceleration = vect(0, 0, 0);
06359	    if (Porteouverte.bAlertIfSeenOpen)
06360	        Porteouverte.bWarnSoldiers=false;
06361	opendoor:
06362	    //log(pawn@"opendoor"@PorteOuverte.bOpened);
06363	    if (!btemp_bool)
06364	    {
06365	        bases.PlayOpenDoor();
06366	        sleep(PorteOuverte.MoveTime+0.02+PorteOuverte.delaytime); //temps anims d'ouverture de porte
06367			  bases.ReleaseAnimControl(true);
06368	    }
06369	    //DBUG    si le animend n'a pas bien ete appele
06370	    if (PorteOuverte.bOpened)
06371	    {
06372	        result=false;
06373	        goto('passagePorte');
06374	    }
06375	    else if (PorteOuverte.bClosed)
06376	    {
06377	        result=false;
06378	        goto('RetourPatrouille');
06379	    }
06380	    //sinon  se recale sur doorpoint precedetn si en cours fermeture ou ouverture
06381	
06382	PasEnArriere:
06383	    //log(pawn@"pas en arriere");
06384	    if (result)
06385	    {
06386			  bases.balerte=true;
06387	        SetVigilant(true);
06388	        bEtatAlerte=true;
06389			  if (enemy==none)
06390			  {
06391				  gotostate('tenir');
06392			  }
06393			  else
06394	        	  gotostate('restesurplace');
06395	    }
06396	    result=true;
06397	    if (DoorP!=none) //seulement si doorpoints existent
06398	    {
06399	       moveto((porteouverte.DoorPoint2.location-pawn.location)+4*collisionradius*normal(porteouverte.DoorPoint2.location-pawn.location)+pawn.location,porteouverte.DoorPoint1,bases.WalkingSpeed);
06400	    }
06401	    else
06402	    {
06403	        focus=none;
06404	        focalpoint=1000*vector(bases.rotation)+pawn.location;
06405	        MoveTo(200*vector(bases.rotation)*vect(-1,0,0) +      pawn.location,none,bases.walkingspeed);
06406	    }
06407	    btemp_bool=true;
06408	    goto('opendoor');
06409	PassagePorte:
06410	   // log(pawn@"passage porte");
06411	    if (DoorP!=none) //seulement si doorpoints existent
06412	    {
06413			 focalpoint=10000*(porteouverte.DoorPoint1.location-pawn.location)+pawn.location;
06414	        if (niveaualerte==0)
06415	            moveto((porteouverte.DoorPoint1.location-pawn.location)+4*collisionradius*normal(porteouverte.DoorPoint1.location-pawn.location)+pawn.location,none,bases.WalkingSpeed);
06416	        else
06417	            moveto((porteouverte.DoorPoint1.location-pawn.location)+4*collisionradius*normal(porteouverte.DoorPoint1.location-pawn.location)+pawn.location,none);
06418	        if (vsize(pawn.location-porteouverte.DoorPoint1.location)>78)
06419	        {
06420	            //log("bloque dans la porte");
06421	            goto('pasenarriere');
06422	        }
06423	    }
06424	    else
06425	    {
06426	        focus=none;
06427	        focalpoint=1000*vector(bases.rotation)+pawn.location;
06428	        moveto(230*vector(pawn.rotation)+pawn.location,none,bases.WalkingSpeed);
06429	    }
06430	FermeturePorte:
06431	  //  log(pawn@"fermeture porte");
06432	    if (NiveauAlerte==0  && PorteOuverte.bOpened && porteouverte.bCloseDoor)
06433	    {
06434	        bases.PlayOpenDoor();
06435	        focus=none;
06436	        focalpoint=Porteouverte.location + 100*vector(pawn.rotation);
06437	        finishrotation();
06438			//	log("la porte est ouverte je la ferme");
06439	        porteouverte.PlayerTrigger(self, Pawn);
06440			//DBUG    si le animend n'a pas bien ete appele
06441			  bases.ReleaseAnimControl();
06442	    }
06443	RetourPatrouille:
06444		if (prevstate=='patrouille')
06445		{
06446			gotostate('patrouille','moving');
06447		}
06448		else if (prevstate=='attaquescriptee')
06449		{
06450			if (movetarget!=none)  //reprend reseau vers attackpoint
06451			{
06452				NextRouteCachePoint=iCompteur;
06453				gotostate('attaquescriptee','RepriseVaVersAttackPoint');
06454			}
06455			else ///y va directement
06456				gotostate('attaquescriptee','VaVersAttackPoint');
06457		}
06458		else
06459		   gotostate(prevstate);
06460	ShiftOnDoorPoint:
06461		disable('seeplayer');
06462		disable('seemonster');
06463		disable('notifybump');
06464		disable('HearNoise');
06465		If (Vsize(porteouverte.doorpoint1.location-pawn.location)>Vsize(porteouverte.doorpoint2.location-pawn.location))
06466			porteouverte.doorpoint1=porteouverte.doorpoint2;
06467		MoveTo(4*pawn.collisionradius*normal(porteouverte.DoorPoint1.location-pawn.location)+pawn.location,enemy);
06468		gotostate(prevstate);
06469	}
06470	
06471	
06472	
06473	// ----------------------------------------------------------------------
06474	// AttaqueScriptee
06475	//
06476	//  attaque reservee a XIII (voit personne d'autre)
06477	// ----------------------------------------------------------------------
06478	state AttaqueScriptee
06479	{
06480	    ignores hearnoise;
06481	    event Tick(float deltaseconds)
06482	    {
06483	        local int i;
06484	        local iacontroller iacontr;
06485	        local vector X,Y,Z;
06486	
06487	        global.tick(deltaseconds);
06488	        if ((enemy==none) || enemy.bisdead)
06489	        {
06490	            ChangeEtat();
06491	            return;
06492	        }
06493	        if (bDeplacementsRoulade)    pawn.velocity=1200*normal(LastAttackPoint.PointSortieEnRoulade.location-LastAttackPoint.location);
06494			  if (bDontSeeAnyMore && !bSwitchMusicInWaitState && NiveauALerteEnAS==2 && (level.timeseconds-fTimerAttackMusic)>10)
06495			  {
06496					bSwitchMusicInWaitState=true;
06497					NiveauALerteEnAS=0;
06498					s_incAttente();
06499	            s_decAttaque();
06500			  }
06501		 }
06502	    event Timer()
06503	    {
06504	        local float ProduitScal;
06505	        local int i;
06506	        local bool bLigneDeVIsee;
06507	
06508	        if (bTire)
06509	        {
06510	            if ((enemy==none) || enemy.bisdead)
06511	            {
06512	                HalteAuFeu();
06513	                return;
06514	            }
06515	            if (pawn.weapon.bmeleeweapon)
06516	            {
06517	                HalteAufeu();
06518	                gotostate('attaqueH2H');
06519	                return;
06520	            }
06521	            if (bTirSurConeMax)
06522						bTirSurConeMax=false;
06523	//		log("AllianceLevel(XIII.LHand.pOnShoulder)"@AllianceLevel(XIII.LHand.pOnShoulder));
06524	            //+++++++++++++++  Gestion otage      +++++++++++++++++++++++++
06525	            if (enemy!=xiii || !(xiii.bPrisonner && XIII.LHand.pOnShoulder!=none && AllianceLevel(XIII.LHand.pOnShoulder)==1))
06526	            {
06527	                if (bPrisonnier)
06528	                {
06529	                    bPrecedentTirBloque=false;
06530	                    bPrisonnier=false;
06531	                }
06532	                //log(pawn@pawn.weapon.Getstatename()@"PAS BLOQUE             !!!!!!!!!!!!");
06533	                bFire=1;
06534	                pawn.weapon.fire(1.0);
06535	            }
06536	            else
06537	            {
06538	                bLigneDeVIsee=false;
06539	                if (!bPrisonnier)
06540	                {
06541	                    bPrecedentTirBloque=false;
06542	                    bPrisonnier=true;
06543	                }
06544	                //tir possible sans toucher pote (skill=2&3)
06545		             ProduitScal=normal(vector(enemy.rotation)) dot normal(pawn.location-enemy.location);
06546		             if (ProduitScal <0.5)
06547		             {
06548		                if (CHARGE_LES_LOGS) log(pawn$"j'ai une ligne de visee, j'allume   *** !!!!! **** ");
06549		                bLigneDeVIsee=true;
06550		             }
06551	                if (NbCoupsRiposte>0 || bLigneDeVIsee)
06552	                {
06553	                    if (bPrecedentTirBloque && bLigneDeVIsee)
06554	                    {
06555	                        if (CHARGE_LES_LOGS) log(pawn$"MAINTENANT LE TIR N'EST PLUS BLOQUE   !!!!!!!!!!!");
06556	                        bPrecedentTirBloque=false;
06557	                        settimer(0.5,false);
06558	                        return;
06559	                    }
06560	                    bFire=1;
06561	                    pawn.weapon.fire(1.0);
06562	                    NbCoupsRiposte--;
06563	                }
06564	                else
06565	                {
06566	                    if (CHARGE_LES_LOGS) log(pawn$"TIR BLOQUE             !!!!!!!!!!!!");
06567	                    bPrecedentTirBloque=true;
06568	                    bfire=0;
06569	                }
06570	            }
06571	            //++++++++++++++++++++++++++++++++++
06572	            if (XIIIWeapon(pawn.weapon).WeaponMode==WM_Auto)
06573	            {
06574						 if (bPremiereRafale)
06575						{
06576							bPremiereRafale=false;
06577					   	if (!pawn.weapon.bmeleeweapon && enemy==xiii && ((pawn.location-xiii.location) dot (vector(XIII.rotation)))<0)
06578					   		bTirSurConeMax=true;
06579	
06580						}
06581	                if (bPrisonnier)
06582	                    settimer(FireTimerRefresh*0.8,false); // refresh de l'otage en ligne de mire
06583	                else
06584	                {
06585							  if (bAccroupiSurAP)
06586	                        settimer2(0.7,false);
06587	                    else
06588	                        settimer(FireTimerRefresh,false); // pour tester si reste muns
06589	
06590	                }
06591	            }
06592	            else
06593	            {
06594	                bfire=0;
06595	                settimer(XIIIWeapon(pawn.weapon).shottime+bases.OffsetTimeBetweenShots,false);
06596	            }
06597	        }
06598	    }
06599	    event Timer2()
06600	    {
06601	        if (btire)
06602	        {
06603	            bfire=0;
06604	            settimer(0.5,false);
06605	        }
06606	    }
06607	    event timer3()
06608	    {
06609	        EnemyTargetPos=enemy.location;
06610	        EnemyTargetVelocity=enemy.velocity;
06611				if (!btemp_bool)    //btemp_bool determine si on est en deplacement
06612					return;
06613	
06614	        if (lastAttackpoint.bTirEntreLes2)
06615	        {
06616					if (CanSee(enemy))
06617					{
06618						Fireenemy();
06619						if (bSwitchMusicInWaitState && NiveauALerteEnAS==0)
06620						{
06621							s_decAttente();
06622				         s_incAttaque();
06623							NiveauALerteEnAS=2;
06624						   bSwitchMusicInWaitState=false;
06625						}
06626						bLookAtEnemy=false;
06627						enable('enemynotvisible');
06628					}
06629					else
06630					{
06631						HalteAuFeu();
06632						bLookAtEnemy=true;
06633						disable('enemynotvisible');
06634					}
06635	        }
06636	        // Passage dans attaque
06637	        if (Vsize(enemy.location-pawn.location)<310 && !LastAttackpoint.bForceDeplacement && Cansee(enemy)) //je vois alors que je ne voyais pas
06638	        {
06639	            HalteAufeu();
06640	            CompteurRecalage=15;
06641	            gotostate('attaque');
06642	        }
06643	    }
06644		function DamageAttitudeto(pawn Other, float Damage)
06645	    {
06646	        if (bases.bisdead)
06647	            return;
06648	        //son
06649	        bases.PlaySndPNJOno(pnjono'Onomatopees.hPNJHurt',bases.CodeMesh,bases.NumeroTimbre);
06650	
06651		     If (xiii.bPrisonner && XIII.LHand.pOnShoulder!=none && AllianceLevel(XIII.LHand.pOnShoulder)==1 && other==xiii)
06652	        {
06653	           if (CHARGE_LES_LOGS) log(pawn$"je riposte");
06654	           NbCoupsRiposte=(2+bases.agressivite)*1.9;
06655	           NbCoupsRiposte=Min(5,NbCoupsRiposte);
06656	           NbCoupsRiposte=Max(1,NbCoupsRiposte);
06657	        }
06658	    }
06659		Function SeeEnemy()
06660		{
06661			bDontSeeAnyMore=false;
06662			if (bSwitchMusicInWaitState && NiveauALerteEnAS==0)
06663			{
06664				s_decAttente();
06665	         s_incAttaque();
06666				NiveauALerteEnAS=2;
06667			   bSwitchMusicInWaitState=false;
06668			}
06669			enable('enemynotvisible');
06670			FireEnemy();
06671		}
06672	    event SeePlayer (pawn other)
06673	    {
06674	        if (bLookAtEnemy && enemy!=none && enemy==other)
06675	            SeeEnemy();
06676			  else
06677			  		SetEnemy(other);
06678	    }
06679	    event SeeMonster(pawn other)
06680	    {
06681				if (bLookAtEnemy && enemy!=none && enemy==other)
06682	            SeeEnemy();
06683			  else
06684					SetEnemy(other);
06685	    }
06686	    event enemynotvisible()
06687	    {
06688	        HalteAuFeu();
06689			  blookAtEnemy=true;
06690			  bDontSeeAnyMore=true;
06691			  fTimerAttackMusic=level.timeseconds;
06692	        disable('enemynotvisible');
06693	    }
06694	    event EnemyAcquired()
06695	    {
06696	        FireEnemy();
06697			  bDontSeeAnyMore=false;
06698			  if (bSwitchMusicInWaitState && NiveauALerteEnAS==0)
06699			  {
06700					s_decAttente();
06701	            s_incAttaque();
06702					NiveauALerteEnAS=2;
06703					bSwitchMusicInWaitState=false;
06704			  }
06705	        enable('enemynotvisible');
06706	    }
06707	    function NotifyFiring()
06708	    {
06709			  if (enemy==none)
06710					return;
06711	        DirectionTir=DirectionDuTir(); //recupere direction du tir avant dispersion
06712	        //decalage par rapport a l'arme
06713	        CheckLineOfFire();
06714	    }
06715	    function rotator AdjustAim(Ammunition FiredAmmunition, vector projStart, int aimerror)
06716	    {
06717	        if (iNumEtat==2) // si vise grenade target
06718	            return rotator(LastAttackPoint.Ciblegrenade.location-projstart);
06719	        else
06720	            return global.adjustaim(FiredAmmunition, projStart,aimerror);
06721	    }
06722		 function PasseEtatAlerteEnAttaque()
06723		 {
06724	        if (NiveauALerteEnAS==0)
06725	        {
06726	            s_decAttente();
06727	            s_incAttaque();
06728	        }
06729	        NiveauALerteEnAS=2;
06730		 }
06731		 function PasseEtatAlerteEnAttente()
06732		 {
06733			  if (NiveauALerteEnAS==2)
06734	        {
06735	            s_incattente();
06736	            s_decAttaque();
06737	        }
06738	        NiveauALerteEnAS=0;
06739		 }
06740	
06741	    function CheckLineOfFire()
06742	    {
06743	        local int TypeObstacle;
06744	
06745	        TypeObstacle=LineOfFireObstacle();
06746	        if (TypeObstacle==0)  //rien devant
06747	        {
06748	
06749	            return;
06750	        }
06751	        else if (TypeObstacle==1)
06752	        {
06753	            bfire=0; //bloc tir car pote devant
06754	            settimer(1.0,true);
06755	            focus=enemy;
06756	        }
06757			  /*else
06758	        {
06759					log("decor devant");
06760					if (fasttrace(enemy.location+enemy.EyePosition(), WeaponStartTrace)) //seehead
06761					{
06762						log("reajuste tir vers tete");
06763						DirectionTir.z+=20;
06764					}
06765			  } */
06766	    }
06767	    function BeginState()
06768	    {
06769			if (lastAttackpoint==none)
06770				return;
06771				Switch (NiveauAlerte)
06772				{
06773					case 0:
06774						if (LastAttackPoint.bMusiqueAttaque || CanSee(enemy))
06775						{
06776							s_incattaque();
06777	            		s_decAttente();
06778							NiveauALerteEnAS=2;
06779						}
06780						else
06781							NiveauALerteEnAS=0;
06782						break;
06783					case 1:
06784						if (LastAttackPoint.bMusiqueAttaque || CanSee(enemy))
06785						{
06786							s_incattaque();
06787	            		s_decAlerte();
06788							NiveauALerteEnAS=2;
06789						}
06790						else
06791						{
06792							s_incattente();
06793	            		s_decAlerte();
06794							NiveauALerteEnAS=0;
06795						}
06796						break;
06797	             case 2:
06798						if (LastAttackPoint.bMusiqueAttaque || CanSee(enemy))
06799						{
06800							NiveauALerteEnAS=2;
06801						}
06802						else
06803						{
06804							NiveauALerteEnAS=0;
06805							s_decattaque();
06806	            		s_incAttente();
06807						}
06808				}
06809			  NiveauAlerte=2;
06810			  bARienVu=false;
06811	        pawn.SetAnimStatus('alert');
06812	        //bDisableEventSeeDeadPawn=true;
06813				bLookAtEnemy=false;
06814	        disable('enemynotvisible');
06815	        SetVigilant(true);
06816	        Temps_ref=level.timeseconds-2;
06817	        settimer3(Temps_RefreshEnemyPos,true);
06818	        //--------  Var Temp ------------
06819	        Temp_float=0.0; //pour stocker temps de pause sur AttackPoint
06820	        VitesseHorizontaleSaut=0.0;
06821	        temp_vect=vect(0,0,0); //utiliser pour calcul du saut
06822	        bSaut=false;
06823	        btemp_bool=false; //sert au test de vision avant deplacement (->tirsurplace)
06824	        //result=false; //utilise pour savoir si a change de branche
06825	        iNumEtat=0;
06826			  bDontSeeAnyMore=false;
06827			  bSwitchMusicInWaitState=false;
06828	        //temp_int=0;//compteur recherche de branche secondaire
06829	        //et sert a savoir si en train de grenader perso 1 ou grenade target 2
06830	    }
06831	    function EndState()
06832	    {
06833	        if (LastAttackPoint!=none && !LastAttackPoint.bReprenable)
06834	        {
06835	            LastAttackPoint.bDejaPasse=true; //notify le passage a l'AP
06836	        }
06837			  if (bControlAnimations) bases.ReleaseAnimControl();
06838	        Pawn.ShouldCrouch(false);
06839	        pawn.bcanjump=false;
06840			  pawn.bIsPafable=true;
06841	        HalteAuFeu();
06842	        settimer3(0,false);
06843			  bBloqueFuiteGrenades=false;
06844			  if (NiveauAlerte!=0 && NiveauALerteEnAS==0)
06845			  {
06846				 	NiveauAlerte=0;
06847				 	bSwitchMusicInWaitState=false;  //inutile
06848			  }
06849			  NiveauALerteEnAS=-1;
06850	    }
06851	
06852	begin:
06853	    if (CHARGE_LES_LOGS) log(pawn@"AttaqueScriptee");
06854	    if (enemy==none)
06855	    {
06856	        log(pawn@"ENEMY==none ** ENEMY==none ** ENEMY==none ** ENEMY==none ** ENEMY==none **");
06857	        //enemy=xiii;
06858	    }
06859	    if (lastAttackpoint==none)  //blindage
06860	    {
06861	        CompteurRecalage=15;
06862	        gotostate('attaque');
06863	    }
06864	    EnemyTargetPos=enemy.location;
06865	    EnemyTargetVelocity=enemy.velocity;
06866	    pawn.velocity=vect(0,0,0);
06867	    pawn.acceleration=vect(0,0,0);
06868	VaVersAttackPoint:
06869	    if (pawn.biscrouched)
06870	        Pawn.ShouldCrouch(false);
06871		 if (LastAttackPoint.bMusiqueAttaque || CanSee(enemy))
06872			 PasseEtatAlerteEnAttaque();
06873		 else
06874	       PasseEtatAlerteEnAttente();
06875		 btemp_bool=true; //sert a savoir qu'on est en mouvement
06876	    //-------------------
06877	    If (movetarget!=none)  //donc pas reachable
06878	    {
06879			 NextRouteCachePoint=0;
06880	RepriseVaVersAttackPoint:
06881	        if (CHARGE_LES_LOGS) log(pawn$"va au Attack point par chemin");
06882	        for (iCompteur=NextRouteCachePoint;iCompteur<NbPointChemin;iCompteur++)
06883	        {
06884	            if (!btire)
06885	            {
06886	                focus=none;
06887	                focalpoint=10000*(PointChemin[iCompteur].location-pawn.location)+pawn.location;
06888	            	MoveToward(PointChemin[iCompteur],none);
06889	        		}
06890					else
06891		            MoveToward(PointChemin[iCompteur],enemy);
06892	        }
06893	    }
06894	    else
06895	    {
06896				if (CHARGE_LES_LOGS) log(pawn$"va au Attack directement");
06897	        if (!btire)
06898	        {
06899	            focus=none;
06900	            focalpoint=10000*(LastAttackPoint.location-pawn.location)+pawn.location;
06901					MoveToward(LastAttackPoint,none);
06902	        }
06903				else
06904					MoveToward(LastAttackPoint,enemy);
06905	    }
06906	    btemp_bool=false; //car detection que pendant deplacement
06907	    bSaut=false;
06908	
06909	    //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
06910	    // +++++++++++++++ GESTION DES PROPRIETES DE L'ATTACK POINT +++++++++++++++++++++
06911	    //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
06912	GetProperties:
06913	    //--------------   PROPRIETES D'ENTREE   -------------------
06914	    GetAttackPointProperties(LastAttackPoint,temp_float);
06915	UseProperties:
06916	    //Si il y a une ciblegrenade ben prend grenade
06917	    if (LastAttackPoint.bTenteGrenadage && enemy.base!=none)
06918	    {
06919	        if (pawn.weapon.isa('grenad'))
06920	            pawn.pendingweapon=pawn.weapon;
06921	        else
06922	        {
06923	          // ELR Remove Class reference
06924	//          pawn.pendingweapon=XIIIWeapon(pawn.FindInventoryType(class'grenad'));
06925	          Pawn.PendingWeapon = Pawn.Inventory.WeaponChange(4);
06926	          if ( Pawn.PendingWeapon == none )
06927	            Pawn.PendingWeapon = Pawn.Inventory.WeaponChange(20); // Try Frag Grenad
06928	          // ELR End
06929	        }
06930	        if (pawn.pendingweapon!= none && pawn.pendingweapon.HasAmmo())
06931	        {
06932					result=btire;
06933	            if (LastAttackpoint.CibleGrenade!=none && LastAttackpoint.CibleGrenade.bactive && FastTrace(LastAttackpoint.ciblegrenade.location,pawn.location))
06934	            {
06935	                //log("cible grenade!!=none"@Pawn.PendingWeapon);
06936	                if (result) //tire deja
06937	                    HalteAufeu();
06938	                if (Pawn.Weapon!=Pawn.PendingWeapon)
06939	                    Pawn.Weapon.PutDown();
06940	                else
06941	                    pawn.pendingweapon=none;
06942	                iNumEtat=2;
06943	                temp_float=fmax(4.5,temp_float);
06944						 sleep(1.2);
06945						 if (LastAttackpoint.CibleGrenade.bactive)
06946	                {
06947	WaitGrenadReady:
06948		                sleep(0.2);
06949							 if (!pawn.weapon.isa('grenad') || pawn.weapon.isinstate('active'))
06950								goto('WaitGrenadReady');
06951		                if (!bases.bDontCallFriends) pawn.PlaySndPNJOno(pnjono'Onomatopees.hPNJGrenade',bases.CodeMesh,bases.NumeroTimbre);
06952							 if (bSwitchMusicInWaitState && NiveauALerteEnAS==0)
06953							 {
06954								s_decAttente();
06955					         s_incAttaque();
06956								NiveauALerteEnAS=2;
06957							   bSwitchMusicInWaitState=false;
06958							 }
06959		                fireenemy();
06960		                sleep(1);
06961						 }
06962	                ChangetoBestWeapon();
06963	                if (!result) //tire deja
06964	                    HalteAufeu();
06965	                iNumEtat=0;
06966	            }
06967	            else if (Vsize(enemy.location-pawn.location)<1200 && Vsize(enemy.location-pawn.location)>300)
06968	            {
06969	                //log("bonne distance de hgrenaage"@pawn.pendingweapon@pawn.weapon);
06970	                if (FastTrace(enemy.location+vect(0,0,80),enemy.location) && FastTrace(enemy.location+vect(0,0,80),pawn.eyeposition()+pawn.location))
06971	                {
06972	                    if (result) //tire deja
06973	                        HalteAufeu();
06974	                    if (Pawn.Weapon!=Pawn.PendingWeapon)
06975	                    {
06976	                        Pawn.Weapon.PutDown();
06977	                    }
06978	                    else
06979	                        pawn.pendingweapon=none;
06980	                    iNumEtat=1;
06981						 	  sleep(1.2);
06982	WaitGrenadReadySansGrenadTarget:
06983		                 sleep(0.2);
06984							  if (!pawn.weapon.isa('grenad') || pawn.weapon.isinstate('active'))
06985								goto('WaitGrenadReadySansGrenadTarget');
06986	                    if (!bases.bDontCallFriends) pawn.PlaySndPNJOno(pnjono'Onomatopees.hPNJGrenade',bases.CodeMesh,bases.NumeroTimbre);
06987							  if (bSwitchMusicInWaitState && NiveauALerteEnAS==0)
06988							  {
06989									s_decAttente();
06990						         s_incAttaque();
06991									NiveauALerteEnAS=2;
06992								   bSwitchMusicInWaitState=false;
06993							  }
06994	                    fireenemy();
06995	                    sleep(1);  //temps de lancer une grenade
06996	                    //log("bonne distance de hgrenaage et fasttrace");
06997	                    ChangetoBestWeapon();
06998	                    if (!result) //tire deja
06999	                        HalteAufeu();
07000	                    iNumEtat=0;
07001	                }
07002	            }
07003	        }
07004	        else
07005	        {
07006	            pawn.pendingweapon=none;
07007	            //log(pawn@"jai pas grenades");
07008	        }
07009	    }
07010	    //ONOMATOPEE CRIE
07011	    if (LastAttackPoint.bAlerteAmisEnCriant /*&& !bADejaCrie */&& bases.bAlerteAmisEnCriant)
07012	    {
07013	        //bADejaCrie=true;
07014	        Interrogation=Spawn(class'XIIIalerteEmitter',self,,pawn.location+vect(0,0,70));
07015	        interrogation.setbase(pawn);
07016	        //son
07017	        pawn.PlaySndPNJOno(pnjono'Onomatopees.hPNJAlert',bases.CodeMesh,bases.NumeroTimbre);
07018	        genalerte.PoteBeugle(pawn);
07019	    }
07020	    //SAUT
07021	    if (bSaut)
07022	    {
07023	        if (CHARGE_LES_LOGS) log(pawn$"commence saut dans attaque scriptee");
07024			  pawn.bIsPafable=false;
07025			  bBloqueFuiteGrenades=true;
07026	        focalpoint=20000*LastAttackPoint.lookdir + pawn.location;
07027	        focus=none;
07028			  bases.PlayJumpInAir();
07029	        pawn.bcanjump=true;
07030	        finishrotation();
07031	        pawn.velocity=temp_vect;
07032	        pawn.jumpz=VitesseHorizontaleSaut;
07033	        pawn.Dojump(true);
07034	        pawn.jumpz=420;
07035			  FinishAnim(bases.firingChannel+1);
07036			  //pawn.shouldcrouch(true);
07037			  //bases.SetCollisionSize(bases.CrouchRadius, bases.CrouchHeight);
07038			  bases.PlayJumpInFlight();
07039	        waitforlanding();
07040			  pawn.bcanjump=false;
07041			  bases.PlayJumpLanding();
07042			  FinishAnim(bases.firingChannel+1);
07043			  bases.releaseanimcontrol();
07044	        if (btire)        //retabli visee
07045	            focus=enemy;
07046			  pawn.rotationrate.yaw=25000;
07047			  sleep(0.2);
07048			  finishrotation();
07049	        pawn.rotationrate.yaw=46000;
07050			  bBloqueFuiteGrenades=false;
07051			 // bases.SetCollisionSize(bases.collisionRadius, bases.collisionHeight);
07052		  	  //pawn.shouldcrouch(false);
07053				pawn.bIsPafable=true;
07054	        if (CHARGE_LES_LOGS) log(pawn$"fini saut dans attaque scriptee");
07055	    }
07056	    else
07057	    {
07058	        if (temp_float>=0.02)
07059	        {
07060	            if (!btire)
07061	            {
07062	                focus=none;
07063	                FocalPoint = pawn.Location + Lastattackpoint.lookdir;
07064	            }
07065	            sleep(temp_float);
07066	        }
07067	        if (bAccroupiSurAP)
07068	            bAccroupiSurAP=false;
07069	    }
07070	    //--------------   PROPRIETES DE SORTIE   ------------------
07071	    //Boucle sur dernier WP uniquement si la propriete le permet (bTemp_bool=true)
07072	    if (lastAttackpoint.bBoucleSurDernier)
07073	    {
07074	        if (lastAttackpoint.bAccroupi)
07075	            Pawn.ShouldCrouch(true);
07076				if (lastAttackpoint.bTirSurPlace)
07077	         {
07078	            if (Cansee(enemy))
07079	            {
07080						if (bSwitchMusicInWaitState && NiveauALerteEnAS==0)
07081						{
07082							s_decAttente();
07083				         s_incAttaque();
07084							NiveauALerteEnAS=2;
07085						   bSwitchMusicInWaitState=false;
07086						}
07087	                enable('enemynotvisible');
07088	                bLookAtEnemy=false;
07089	                FireEnemy();
07090	            }
07091	            else
07092	            {
07093	                HalteAuFeu();
07094	                bLookAtEnemy=true;
07095	                disable('enemynotvisible');
07096	            }
07097	          }
07098	          else
07099	          {
07100	            HalteAuFeu();
07101	            bLookAtEnemy=false;
07102	            disable('enemynotvisible');
07103	          }
07104	        //gotostate('restesurplace');
07105				stop;
07106	    }
07107	    else
07108	    {
07109	        //sortie en roulade
07110	        if (lastAttackpoint.PointSortieEnRoulade!=none && LastAttackPoint.NextAttackP!=none)
07111	        {
07112					pawn.bIsPafable=false;
07113	            if (!pawn.biscrouched)
07114	                pawn.shouldcrouch(true);
07115	            //log("debut roulade");
07116	            pawn.velocity=vect(0,0,0);
07117	            pawn.acceleration=vect(0,0,0);
07118	            halteaufeu();
07119					disable('seemonster');
07120	            disable('seeplayer');
07121	            disable('enemynotvisible');
07122	            sleep(0.2);
07123					if (abs(normal(enemy.location-pawn.location) dot normal(LastAttackPoint.PointSortieEnRoulade.location-LastAttackPoint.location))>0.9 || Vsize(enemy.location-pawn.location)<500)
07124					{
07125	              	if (!lastAttackpoint.bAccroupi)
07126							pawn.shouldcrouch(false);
07127						enable('seemonster');
07128	            	enable('seeplayer');
07129						if (Cansee(enemy))
07130		            {
07131							 if (bSwitchMusicInWaitState && NiveauALerteEnAS==0)
07132							{
07133								s_decAttente();
07134					         s_incAttaque();
07135								NiveauALerteEnAS=2;
07136							   bSwitchMusicInWaitState=false;
07137							}
07138		                bLookAtEnemy=false;
07139		                enable('enemynotvisible');
07140		                FireEnemy();
07141		            }
07142		            else
07143		            {
07144		                disable('enemynotvisible');
07145		                bLookAtEnemy=true;
07146		                HalteAuFeu();
07147		            }
07148						goto('PointSuivant');
07149					}
07150				   bBloqueFuiteGrenades=true;
07151	            //log("lance roulade");
07152	            focalpoint=LastAttackPoint.NextAttackP.location;
07153	            bases.playroulade();
07154	            bDeplacementsRoulade=true;
07155	            focus=enemy;
07156	            pawn.groundspeed=1200;
07157	            sleep(0.55);
07158	            bDeplacementsRoulade=false;
07159	            sleep(0.1);
07160	            pawn.playanim('waitaccroupi',1,0.2,bases.FiringChannel+1);
07161	            pawn.groundspeed=472;
07162	            sleep(0.08);
07163					enable('seemonster');
07164	            enable('seeplayer');
07165	            sleep(0.13);
07166	            if (Cansee(enemy))
07167	            {
07168						 if (bSwitchMusicInWaitState && NiveauALerteEnAS==0)
07169						{
07170							s_decAttente();
07171				         s_incAttaque();
07172							NiveauALerteEnAS=2;
07173						   bSwitchMusicInWaitState=false;
07174						}
07175	                bLookAtEnemy=false;
07176	                enable('enemynotvisible');
07177	                FireEnemy();
07178	            }
07179	            else
07180	            {
07181	                disable('enemynotvisible');
07182	                bLookAtEnemy=true;
07183	                HalteAuFeu();
07184	            }
07185	            bases.AnimBlendToAlpha(bases.FIRINGCHANNEL+1,0.5,0);
07186	            sleep(0.04);
07187	            bases.AnimBlendToAlpha(bases.FIRINGCHANNEL+1,0,0);
07188	            //log("commence a tirer");
07189	            bases.ReleaseAnimControl();
07190	            sleep(2);
07191	            //log("fin roulade");
07192	            //pawn.bspinecontrol=true;
07193					pawn.bIsPafable=true;
07194					bBloqueFuiteGrenades=false;
07195	        }
07196	        if (lastAttackpoint.bTirEntreLes2)
07197	        {
07198	            if (Cansee(enemy))
07199	            {
07200						if (bSwitchMusicInWaitState && NiveauALerteEnAS==0)
07201						{
07202							s_decAttente();
07203				         s_incAttaque();
07204							NiveauALerteEnAS=2;
07205						   bSwitchMusicInWaitState=false;
07206						}
07207	                bLookAtEnemy=false;
07208	                enable('enemynotvisible');
07209	                FireEnemy();
07210	            }
07211	            else
07212	            {
07213	                disable('enemynotvisible');
07214	                bLookAtEnemy=true;
07215	                HalteAuFeu();
07216	            }
07217	        }
07218	        else
07219	        {
07220	            disable('enemynotvisible');
07221					bLookAtEnemy=false;
07222	            HalteAuFeu();
07223	        }
07224	    }
07225	
07226	    //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
07227	PointSuivant:
07228	    if (!LastAttackPoint.bReprenable)
07229	    {
07230	        LastAttackPoint.bDejaPasse=true; //notify le passage a l'AP
07231	    }
07232	    result=false;
07233	    If (LastAttackPoint.PointDuSecondChemin!=none)
07234	    {
07235	        if (FindBestPathToward(XIII))
07236	        {
07237	            if (movetarget==LastAttackPoint)
07238	            {
07239	                if(RouteCache[1]!=none)
07240	                    movetarget=RouteCache[1];
07241	                else
07242	                    movetarget=none;
07243	            }
07244	            if (attackpoint(movetarget)!=none && attackpoint(movetarget)==LastAttackPoint.PointDuSecondChemin)
07245	            {
07246	                result=true;
07247	                OldAttackPoint=lastAttackpoint;
07248	                LastAttackPoint=LastAttackPoint.PointDuSecondChemin;
07249	            }
07250	        }
07251	        if (!result)
07252	        {
07253	            //vire l'utilisation de l'autre branche (Oldattackpoint est utilise en var temp)
07254	            OldAttackPoint=LastAttackPoint.PointDuSecondChemin;
07255	            While (OldAttackPoint!=none && !OldAttackPoint.bDejaPasse)
07256	            {
07257	                OldAttackPoint.bDejaPasse=true; //notify le passage a l'AP
07258	                OldAttackPoint=OldAttackPoint.NextAttackP;
07259	            }
07260	        }
07261	    }
07262	
07263	    if (!result)  // si pas change de branche
07264	    {
07265	        OldAttackPoint=lastAttackpoint; //sauv dernier
07266	        if (LastAttackPoint.NbPointsSkipables>0)     //passage aleatoire a un autre
07267	        {
07268	            NombreDePointsSkippes=LastAttackPoint.NbPointsSkipables-1;
07269	            NumeroProchainPoint=rand(NombreDePointsSkippes+1);
07270	            //log("NumeroProchainPoint"@NumeroProchainPoint@NombreDePointsSkippes);
07271	            for (temp_int=0;temp_int<=NumeroProchainPoint;temp_int++)
07272	            {
07273	                LastAttackPoint=LastAttackPoint.NextAttackP;
07274	                if (temp_int<NumeroProchainPoint && !LastAttackPoint.bReprenable)
07275	                    LastAttackPoint.bDejaPasse=true; //notify le passage a l'AP
07276	            }
07277	            NumeroProchainPoint=NombreDePointsSkippes-NumeroProchainPoint;
07278	            for (temp_int=0;temp_int<NumeroProchainPoint;temp_int++)
07279	            {
07280	                if (temp_int<NumeroProchainPoint && !LastAttackPoint.NextAttackP.bReprenable)
07281	                    LastAttackPoint.NextAttackP.bDejaPasse=true; //notify le passage a l'AP
07282	                LastAttackPoint.NextAttackP=LastAttackPoint.NextAttackP.NextAttackP;
07283	            }
07284	        }
07285	        else
07286	        {
07287	            LastAttackPoint=LastAttackPoint.NextAttackP;  //passe suivant
07288	        }
07289	    }
07290	    if (lastAttackpoint!=none) //on sera au Attackpoint avant NMI
07291	    {
07292	        movetarget=none;
07293	        if (ActorReachable(LastAttackpoint))
07294	        {
07295	            goto('VaVersAttackPoint');
07296	        }
07297	        else if (FindBestPathToward(LastAttackPoint))
07298	        {
07299	            for (iCompteur=0;iCompteur<16;iCompteur++)
07300	            {
07301	                if (routecache[iCompteur]==none)
07302	                    break;
07303	                PointChemin[iCompteur]=routecache[iCompteur];
07304	            }
07305	            NbPointChemin=iCompteur;
07306	            goto('VaVersAttackPoint');
07307	        }
07308	    }
07309	FinAttaque:
07310	    //Dernier attack point = position de tenir
07311	    if (EtatNeutre == 'tenir')
07312	    {
07313	        PointTenirPos=pawn.location;
07314	        PointTenirRot=pawn.rotation;
07315	    }
07316	    HalteAuFeu();
07317	    if (CHARGE_LES_LOGS) log(pawn@"Sort de son resau d'attaqueScriptee");
07318	    /*if (bdejavu)
07319	    { */
07320	    if (CanSee(enemy))
07321	    {
07322				if (bSwitchMusicInWaitState && NiveauALerteEnAS==0)
07323				{
07324					s_decAttente();
07325		         s_incAttaque();
07326					NiveauALerteEnAS=2;
07327				   bSwitchMusicInWaitState=false;
07328				}
07329	        CompteurRecalage=15;
07330	        gotostate('attaque');
07331	    }
07332	    else
07333	        gotostate('temporise');
07334	        /* }
07335	        else
07336	    gotostate('tenir'); */
07337	
07338	}
07339	
07340	
07341	Function GetAttackPointProperties (AttackPoint PointAttaque, out float TempsSurAP)
07342	{
07343	    local bool ResteSurPlace;
07344	    local float X,Y,Z;
07345	    local float rating;
07346	    local XIIIWeapon Arme,ancienearme;
07347	
07348	    //PROPRIETES
07349	        switch(PointAttaque.Proprietes.Propriete)
07350	        {
07351	        case Rester:
07352	            if (CHARGE_LES_LOGS) log(pawn$"Propriete reste");
07353	            ResteSurPlace=true;
07354					if (PointAttaque.Proprietes.arguments.length>0)
07355		            TempsSurAP=float(PointAttaque.Proprietes.arguments[0]);
07356					else
07357						TempsSurAP=0;
07358	            if (PointAttaque.Proprietes.arguments.Length>1)
07359	            {
07360	                if (frand()>0.5)
07361	                    TempsSurAP+=frand()*float(PointAttaque.Proprietes.arguments[1]);
07362	                else
07363	                    TempsSurAP-=frand()*float(PointAttaque.Proprietes.arguments[1]);
07364	            }
07365	            if (PointAttaque.Proprietes.arguments.Length>2)
07366	            {
07367	                bases.TakeAnimControl(false);
07368	                bases.PlayAnim(name(PointAttaque.Proprietes.arguments[2]),,,bases.FIRINGCHANNEL+1);
07369	                bases.AnimBlendToAlpha(bases.FIRINGCHANNEL+1,1,0.4);
07370	            }
07371	            TempsSurAP=fmax(0.02,TempsSurAP);
07372	            break;
07373	
07374	        case sauter:
07375	            if (CHARGE_LES_LOGS) log(pawn$"Propriete saute");
07376	            bSaut=true;
07377	            if (PointAttaque.Proprietes.arguments.Length>1)
07378	            {
07379	                temp_vect=vector(PointAttaque.rotation)*float(PointAttaque.Proprietes.arguments[0]);
07380	                VitesseHorizontaleSaut=float(PointAttaque.Proprietes.arguments[1]);
07381	            }
07382	            break;
07383	
07384	            //case "Trigger":
07385	            //     PointAttaque.TriggerEvent();
07386	            //     break;
07387	
07388	        default:
07389	            if (CHARGE_LES_LOGS) log(pawn$"  ********* UNKNOW ARGUMENT *******"$PointAttaque.Proprietes.Propriete);
07390	        }
07391	
07392	    //TRIGGER
07393	    if (PointAttaque.bTriggerEvent)
07394	    {
07395	        PointAttaque.TriggerEvent(PointAttaque.event,PointAttaque,pawn);
07396	    }
07397	
07398	    if (ResteSurPlace) //Que pour rester et switcherArme
07399	    {
07400	        //ACCROUPI
07401	        if (PointAttaque.bAccroupi)
07402	        {
07403	            Pawn.ShouldCrouch(true);
07404	            TempsSurAP+=0.1;  //temps de l'anim de crouch
07405	            bAccroupiSurAP=true;
07406	        }
07407	        // TIR SUR PLACE
07408	        if (PointAttaque.bTirSurPlace)
07409	        {
07410	            if (Cansee(enemy))
07411	            {
07412						 if (bSwitchMusicInWaitState && NiveauALerteEnAS==0)
07413						{
07414							s_decAttente();
07415				         s_incAttaque();
07416							NiveauALerteEnAS=2;
07417						   bSwitchMusicInWaitState=false;
07418						}
07419	                if (LastAttackPoint.CibleGrenade==none || !LastAttackPoint.CibleGrenade.bActive)
07420	                    enable('enemynotvisible');
07421	                else
07422	                    disable('enemynotvisible');
07423	                bLookAtEnemy=false;
07424	                FireEnemy();
07425	            }
07426	            else
07427	            {
07428	                HalteAuFeu();
07429	                bLookAtEnemy=true;
07430	                disable('enemynotvisible');
07431	            }
07432	        }
07433	        else
07434	        {
07435	            HalteAuFeu();
07436	            bLookAtEnemy=false;
07437	            disable('enemynotvisible');
07438	        }
07439	    }
07440	    else
07441	    {
07442	        HalteAuFeu();
07443	        bLookAtEnemy=false;
07444	        disable('enemynotvisible');
07445	    }
07446	}
07447	
07448	/*
07449	NiveauAlerte    (niv0 = trannnnnnquille, niv1= j'ai vu quelque chose mais je ne suis pas en attaque, niv2= je suis en plein fight)
07450	
07451	  Niv 0                             Niv 1                               Niv 2
07452	
07453	    Init                                Acquisition                 attaque
07454	    Otage                             Fuite                               Chasse
07455	    Faction                                                           Temporise
07456	    Patrouille                                                          AttaqueScriptée
07457	    Errance                                                           TacticalMove
07458	
07459	
07460	
07461	
07462	            */
07463			 //					bAdjustFromWalls=false
07464	
07465	
07466	defaultproperties
07467	{
07468	     TempsDeclencheAlarme=1.700000
07469	     NiveauALerteEnAS=-1
07470	     bAdjustFromWalls=False
07471	}

End Source Code