## 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