///

// Template file v5.12 (07/27/01)

////////////////////////////////////////////////////////////////////////

// File: war.wdl "Modified by the Mad Dog on 10/1/01"

//                      WDL prefabs for hostile entities

////////////////////////////////////////////////////////////////////////

// Mod Date: 05/18/01 DCP

//                                              Fixed "double shots" (the cause of robot1's self hits)

//

// Mod Date: 06/05/01 DCP

//                      attack_approach(), avoid_walls(): Replaced TO_ANGLE with vec_to_angle()

//

// Mod Date: 06/21/01 DCP

//                                              Replaced SYNONYMs with pointers

//

// Mod: 07/19/01 MWS

//                      state_wait(): Use specified cowardice value instead of universal 30.

//                                              Use specified alertness instead of universal 1000.

//                                              Also now skips the player scan entirely if alertness is zero.

//

//                      attack_fire(): MY_ANGLE used in shooting at player now varies by a random

//                                              amount between -MY._I_ACCURACY to +MY._I_ACCURACY

//

// Mod Date: 7/26/01 MWS

//                      attack_transitions(): Made "escape" branch test for MY._I_COWARDICE

//                                              instead of default 30.

////////////////////////////////////////////////////////////////////////

//

////////////////////////////////////////////////////////////////////////

 

 

//DEFINE WAR_CHAT_ON;     // display 'thought' actions for the AIs

IFDEF WAR_CHAT_ON;

            STRING war_wait_str,"Waiting...";

            STRING war_attack_str,"Attacking!!!";

            STRING war_hunt_str,"Searching...";

            STRING war_escape_str,"Retreat!!!";

            STRING war_dead_str,"I have been undone!";

ENDIF;

//////////////////////////////////////////////////////////////////////

// WAR.WDL - fighting behaviour

///////////////////////////////////////////////////////////////////////

IFNDEF WAR_DEFS;

 DEFINE ACTOR_EXPLO,<explo+7.pcx>;

 DEFINE ACTOR_EXPLO_FRAMES,7;

ENDIF;

 

///////////////////////////////////////////////////////////////////////

var freeze_actors = 0;      // 1,2 for testing purposes

///////////////////////////////////////////////////////////////

///Add different attack gun sounds for a killer bot (enemy)

////////////

SOUND bigax,<pickax.wav>; // replace with your sounds

sound gunmy,<snd1.wav>;   //ex. "sound NAME,<name.wav>;"

 

///////////////////////////////////////////////////////////////////////

DEFINE _STATE_WAIT,1;

DEFINE _STATE_ATTACK,2;

DEFINE _STATE_ESCAPE,3;

DEFINE _STATE_DIE,4;

DEFINE _STATE_FREEZE,5;       // 05/15/01 DCP: Changed from 4->5

DEFINE _STATE_HUNT,6;

////////////////////////////////////////////////

// For different enemy gun sounds and or sword

////////

DEFINE MELEE,1;  // assign this in enemy action script example

DEFINE RANGED,2; // "my._attackmode = Melee;

DEFINE MYGUN,3;  // the gun sounds for these are controlled

                 // in "function attack_fire"

DEFINE _ATTACKMODE,SKILL48;//attackmode definition for enemy gun sound

// End of my different gun sounds

//////////////////////////////////////////////

 

DEFINE _MUZZLE_VERT,SKILL32;

DEFINE _I_ACCURACY,SKILL33;                 // 07/19/01 MWS: Added

DEFINE _I_COWARDICE,SKILL34;              // 07/19/01 MWS: Added

DEFINE _I_ALERTNESS,SKILL35;               // 07/19/01 MWS: Added

 

// DEFINE USER INPUT SKILLs

// These skill will be inputted from WED and work with entities that use the actions:

//    "player_walk_fight" and "actor_walk_fight"

DEFINE            _WALKSWIM_DIST, SKILL1;   // Walk Distance . Swim Distance

DEFINE            _RUNCRAWL_DIST, SKILL2;   // Run Distance . Crawl Distance

DEFINE            _STANDJUMP_TIME, SKILL3;  // Stand Time . Jump Time

DEFINE            _ATTACKDUCK_TIME, SKILL4; // Attack Time . Duck Time

DEFINE            _RUNTHRESHOLD, SKILL14;            // Run Threshold

//DEFINE            _FORCE, SKILL5;                           // Force

//DEFINE            _BANKING, SKILL6;                                  // Banking amount (player only)

//DEFINE            _HITMODE, SKILL6;                         // Hitmode (actor only)

//DEFINE            _MOVEMODE, SKILL7;                      // Starting movemode

//DEFINE            _FIREMODE, SKILL8;                      // Firemode

//DEFINE            _HEALTH, SKILL9;                         // Heath

//DEFINE            _ARMOR, SKILL10;                         // Armor

DEFINE            _ALERTNESS, SKILL11;    // Alertness

DEFINE            _ACCURACY, SKILL12;                    // Accuracy

DEFINE            _COWARDICE, SKILL13;                    // Cowardice

DEFINE            _MUZZLEATTACH, SKILL15;            // Muzzle vertex . Attach vertex

 

///////////////////////////////////////////////////////////////////////

entity* test_actor;            // test actor entity pointer. Used in robot_test

 

entity* ent_marker;            // marker entity, used in hunting

 

 

STRING            robot_attack_str, "attack";            // attack frame names used by robot

 

ACTION robot_test

{

IFNDEF test;

            remove(ME);

            return;

ENDIF;

 

            test_actor = ME;

            MY._WALKFRAMES = 8.030;

            MY._RUNFRAMES = 4.050;

            MY._ATTACKFRAMES = 6;

            MY._DIEFRAMES = 1;

            MY._FORCE = 2;

            MY._FIREMODE = DAMAGE_SHOOT+FIRE_PARTICLE+HIT_FLASH+0.05;

            MY._HITMODE = HIT_GIB;//HIT_EXPLO;

            MY._WALKSOUND = _SOUND_ROBOT;

            drop_shadow();

            anim_init();

            actor_fight();

}

 

// Desc: Action for robot #1

//                                  Init values and call actor_fight

ACTION robot1

{

            MY._FORCE = 0.7;

            MY._FIREMODE = DAMAGE_EXPLODE+FIRE_BALL+HIT_EXPLO+BULLET_SMOKETRAIL+0.20;

            MY._HITMODE = 0;

            MY._WALKSOUND = _SOUND_ROBOT;

             anim_init();

            drop_shadow();            // attach shadow to robot

            actor_fight();

//            if(MY.FLAG4 == ON) { CALL patrol; }

}

 

 

// Desc: Action for robot #2

//                                  Init values and call actor_fight

ACTION robot2

{

            MY._FORCE = 2;

            MY._FIREMODE = DAMAGE_SHOOT+FIRE_PARTICLE+HIT_FLASH+0.05;

            MY._HITMODE = HIT_GIB;//HIT_EXPLO;

            MY._WALKSOUND = _SOUND_ROBOT;

            anim_init();

            drop_shadow(); // attach shadow to robot

            actor_fight();

//            if(MY.FLAG4 == ON) { patrol(); }

            create(<arrow.pcx>,MY.POS,_ROBOT_TEST_WATCHER);  // used to activate watcher drone

}

 

 

// Desc: Action for robot #3

//                                  Init values and call actor_fight

//

// NOTE: robot #3 removes itself from the game!

ACTION robot3

{

            remove(ME);

            return;

 

            MY._FORCE = 0.7;

            MY._FIREMODE = DAMAGE_EXPLODE+FIRE_BALL+HIT_EXPLO+BULLET_SMOKETRAIL+0.20;

            anim_init();

            drop_shadow();

            actor_fight();

//            if(MY.FLAG4 == ON) { patrol(); }

}

 

 

// Desc: Debugging utility, watches a ROBOT and sets flags using its values

//

entity* ent_test_watcher;                    // marker entity, used in hunting

function _ROBOT_TEST_WATCHER()

{

            MY.PASSABLE = ON;

//            MY.INVISIBLE = ON;

            MY.ENTITY1 = YOU;

 

            WHILE(MY.ENTITY1 != 0)

            {

                        ent_test_watcher = MY.ENTITY1;

 //                     tst_value_1 =  ent_test_watcher._STATE;

                        wait(1);

 

            }

 //            tst_value_1 =  -1;

 

            remove(ME);

}

///////////////////////////////////////////////////////////////////////

// Desc: the wait state

//

// Mod: 07/19/01 MWS

//                                  Use specified cowardice value instead of universal 30.

//                                  Use specified alertness instead of universal 1000.

//                                  Also now skips the player scan entirely if alertness is zero.

function state_wait()

{

IFDEF WAR_CHAT_ON;

msg.STRING = war_wait_str;

show_message();

ENDIF;

 

            // init values here for backwards compatibility

            if(MY._I_COWARDICE == 0)

            { MY._I_COWARDICE = 30; }                      // use default cowardice

            if(MY._I_ALERTNESS == 0)

            { MY._I_ALERTNESS = 1000; }            // use default alertness

 

 

            MY._STATE = _STATE_WAIT;

            while(MY._STATE == _STATE_WAIT)

            {

 

                        if(MY._HEALTH <= 0)      // no health? Die

                        {

                                    EXCLUSIVE_ENTITY;

                                    wait(1);

                                    state_die();

                                    return;

                        }

 

                        // Note: changed, negative cowardice means never retreat

                        if(MY._HEALTH <= MY._I_COWARDICE  &&  MY._I_COWARDICE >= 0)     // low health? Escape

                        {

                                    EXCLUSIVE_ENTITY;

                                    wait(1);

                                    state_escape();

                                    return;

                        }

 

 

                        if (MY._I_ALERTNESS > 0)            // dont be alert if negative alertness

                        {

                                    // scan for the player coming near

                                    temp.PAN = 180;

                                    temp.TILT = 180;

                                    temp.Z = MY._I_ALERTNESS;

                                    indicator = _WATCH;

                                    scan(MY.POS,MY.ANGLE,temp);

 

                                    // if the player has been detected...

                                    if(MY._SIGNAL == _DETECTED)

                                    {

                                                MY._SIGNAL = 0;

                                                state_attack();  // ATTACK!

                                                return;

                                    }

                        }

 

                        force = 0;     // no force from this actor

                        actor_move();            // react to outside forces (gravity, etc) even while waiting

                        waitt(1);

            }

}

 

// Desc: The attack state

//

function state_attack()

{

            MY._STATE = _STATE_ATTACK;

IFDEF WAR_CHAT_ON;

msg.STRING = war_attack_str;

show_message();

ENDIF;

            MY._MOVEMODE = _MODE_ATTACK;   // stop patrolling etc.

            attack_transitions();      // branch to other states depending on values

 

 

            // fire and close distance

            while(MY._STATE == _STATE_ATTACK)

            {

 

                        // fire two or three times

                        MY._COUNTER = 1; //            MY._COUNTER = 1.5 + RANDOM(1);

 

                        // check to see if player is shootable,

                        if((attack_fire()) == -1)

                        {

                                    // cannot see player

                                      EXCLUSIVE_ENTITY;

                                    wait(1);

                                    state_hunt();

                                    return;

                        }

                        while(MY._COUNTER > 0) { waitt(1); }            // don't continue until attack_fire is finished

 

                        // walk towards player for one to three seconds

                        MY._COUNTER = 16 + RANDOM(32);

                        attack_approach();

                        while(MY._COUNTER > 0) { waitt(1); } // don't continue until attack_approach is finished

            }

 

 

}

 

// Desc: Use internal and external values to branch to other states

//

// Mod Date: 7/26/01 MWS

//                                              Made "escape" branch test for MY._I_COWARDICE instead of default 30

function attack_transitions()

{

            while(MY._STATE == _STATE_ATTACK)

            {

                        if(MY._HEALTH <= 0)    // goto die state

                        {

                                    EXCLUSIVE_ENTITY;

                                    wait(1);

                                    state_die();

                                    return;

                        }

                        if(MY._HEALTH <= MY._I_COWARDICE  &&  MY._I_COWARDICE >= 0)     // low health? Escape

                        {

                                    EXCLUSIVE_ENTITY;

                                    wait(1);

                                    state_escape();

                                    return;

                        }

                        if(freeze_actors > 0)   // goto freeze state

                        {

                                    EXCLUSIVE_ENTITY;

                                    wait(1);

                                    state_freeze();

                                    return;

                        }

                        wait(1);

            }

}

 

 

 

//          Desc: attack the player:

//                                              -turn towards player

//                                              -check if entity can see the player

//                                              -play fire animation

//                                              -fire shot

//

// Mod Date: 05/18/01 DCP

//                                              Fixed "double shots" (the cause of robot1's self hits)

//

// Mod Date: 07/19/01 MWS

//                                              MY_ANGLE used in shooting at player now varies by a random

//                                              amount between -MY._I_ACCURACY to +MY._I_ACCURACY

//

// Mod Date: 08/22/01 DCP

//                                  Added "Advanced" Animation for firing

///////////////////////////////////////////////////

/////////////////////////////////////////

//

function attack_fire()

{

            while((MY._STATE == _STATE_ATTACK) && (MY._COUNTER > 0))

            {

                        // turn towards player

                        temp.X = player.X - MY.X;

                        temp.Y = player.Y - MY.Y;

                        temp.Z = player.Z - MY.Z;

                        vec_to_angle(MY_ANGLE,temp);

                        force = MY._FORCE * 2;

                        actor_turn();

 

                        // watch out if player visible. If yes, then shoot at him

                        indicator = _WATCH;

                        //SHOOT MY.POS,player.POS;

                        trace_mode = IGNORE_ME + IGNORE_PASSABLE + IGNORE_PASSENTS;

                        trace(MY.POS,player.POS);

 

                        if((RESULT > 0) && (YOU == player))            // spotted him!

                        {

                                    // fire at player

                                    // 1) PLAY ATTACK ANIMATION

                                    // check for *ADVANCED ANIMATION* (frame names and entity tick/dist values)

                                    if(int(MY._WALKFRAMES) < 0)

                                    {

                                                // reset entity's animation time to zero

                                                MY._ANIMDIST = 0;

 

                                                while(MY._ANIMDIST < 50)

                                                {

                                                            // if you have more than one attacking animation, here's where you would test for it...

                                                            // calculate a percentage out of the animation time

                                                            MY._ANIMDIST +=  100*(TIME / (INT(((-MY._ADVANIM_TICK)&MASK_ANIM_ATTACK_TICKS)>>10)));

                                                            // set the frame from the percentage

                                                            ent_frame(robot_attack_str,MY._ANIMDIST);

                                                            wait(1);

                                                }

                                    }

                                    else

                                    {

                                                // decide whether it's a frame number (old) or frame name (new) animation

                                                if(frc(MY._WALKFRAMES) > 0)// OLD STYLE ATTACK ANIMATION

                                                {

                                                            // play attack animation

                                                            MY.FRAME = 1 + MY._WALKFRAMES + MY._RUNFRAMES + 1;   // set frame to start

                                                            MY.NEXT_FRAME = 0;      // inbetween to the real next frame

                                                            while(MY.FRAME > 1 + MY._WALKFRAMES + MY._RUNFRAMES + MY._ATTACKFRAMES)

                                                            {

                                                                        wait(1);

                                                                        MY.FRAME += 0.4 * TIME;

                                                            }

                                                            MY.FRAME = 1 + MY._WALKFRAMES + MY._RUNFRAMES + 1;  // end at start frame

                                                }// END OLD STYLE ATTACK ANIMATION

                                                else // new animation format    (frc(MY._WALKFRAMES) == 0)

                                                {

                                                            // reset entity's animation time to zero

                                                            MY._ANIMDIST = 0;

 

                                                            while(MY._ANIMDIST < 50)

                                                            {

                                                                        wait(1);

                                                                        // calculate a percentage out of the animation time

                                                                        MY._ANIMDIST += 8.0 * TIME;   // attack in ~1 second

                                                                        // set the frame from the percentage

                                                                        // -old- SET_FRAME            ME,robot_attack_str,MY._ANIMDIST;

                                                                        ent_frame(robot_attack_str,MY._ANIMDIST);

                                                            }

                                                }// END NEW STYLE ATTACK ANIMATION

                                    } // END NOT ADVANCED

 

                                    // 2) fire shot

                                    damage = frc(MY._FIREMODE) * 100;

                                    fire_mode = MY._FIREMODE;

                                    if((fire_mode & MODE_DAMAGE) == DAMAGE_SHOOT)

                                    {

                                                shot_speed.X = 500;

                                    }

                                    else

                                    {

                                                shot_speed.X = 100;

                                    }

                                    shot_speed.Y = 0;

                                    shot_speed.Z = 0;

                                    MY_ANGLE.PAN = MY.PAN;            // TILT is already set from TO_ANGLE

 

                                    // Add in a random amount according to MY._I_ACCURACY

                                    if (MY._I_ACCURACY != 0)

                                    {

                                                 MY_ANGLE.PAN  += random(MY._I_ACCURACY*2) - MY._I_ACCURACY;

                                                  MY_ANGLE.TILT += random(MY._I_ACCURACY*2) - MY._I_ACCURACY;

                                    }

 

                                    vec_rotate(shot_speed,MY_ANGLE);

                                    // now shot_speed points ahead

 

                                    // check to see if the model is using a muzzle vertice

/////////////////////////////////////////////////////////////////

 

                                    if(MY._MUZZLE_VERT == 0)

                                    {

                                                // default gun muzzle

                                                vec_set(gun_muzzle.X,MY.X);

                                    }

                                    else

                                    {

                                                ent_vertex(gun_muzzle.X,MY._MUZZLE_VERT);

                                    }

///////////////////////////////////////////////////////////////

///////////////////// Add the new play entsound here /////////////////

///////////////////////////////////////////////////////////////

 IF(MY._ATTACKMODE == MELEE)

                                    {

                                    play_entsound(ME,bigax,150);   // change these sounds to your

                                    }

            IF(MY._ATTACKMODE == RANGED)     // own gun sound.. (Me,YOUR SOUND,150);

                                    {

                                    play_entsound(ME,gun_wham,150);

                                    }

            IF(MY._ATTACKMODE == MYGUN)

                                    {

                                    play_entsound(ME,gunmy,150);

                                    }

                                    gun_shot();

                                    //MY._COUNTER -= 1;// don't use this

                                    //if(frc(MY._WALKFRAMES) == 0)// don't use this

                                    {

 

/////////////////////////////////////////////////////////////

// check for *ADVANCED ANIMATION* (frame names and entity tick/dist values)

                                    if(int(MY._WALKFRAMES) < 0)

                                    {

                                                // set entity's animation to halfway

                                                MY._ANIMDIST = 50;

 

                                                while(MY._ANIMDIST < 100)

                                                {

                                                            // if you have more than one attacking animation, here's where you would test for it...

                                                            // calculate a percentage out of the animation time

                                                            MY._ANIMDIST +=  100 * (TIME / (INT(((-MY._ADVANIM_TICK)&MASK_ANIM_ATTACK_TICKS)>>10)));

                                                            // set the frame from the percentage

                                                            ent_frame(robot_attack_str,MY._ANIMDIST);

                                                            wait(1);

                                                }

                                    }

                                    else

                                    {

                                                if(frc(MY._WALKFRAMES) == 0)

                                                {

                                                            // play the second half of the animation

                                                            while(MY._ANIMDIST < 100)

                                                            {

                                                                        wait(1);

                                                                        // calculate a percentage out of the animation time

                                                                        MY._ANIMDIST += 8.0 * TIME;   // attack in ~1 second

                                                                        // set the frame from the percentage

                                                                        // -old- SET_FRAME            ME,robot_attack_str,MY._ANIMDIST;

                                                                        ent_frame(robot_attack_str,MY._ANIMDIST);

                                                            }

                                                }// END NEW STYLE ATTACK ANIMATION

                                    }

                        }// END if((RESULT > 0) && (YOU == player))

                        else

                        {

                                    MY._COUNTER = 0;

                                    return(-1);        // can not see player

                        }

                        waitt(2);          // space shots appart (so they don't hit each other!

                        MY._COUNTER -= 1;

            }// END  while((MY._STATE == _STATE_ATTACK) && (MY._COUNTER > 0))

}

 

// Desc: approach the player with random deviation

//                                  do not approach any closer then 50 units

//

//          Note: only rotates by PANning

//

//          Calls: actor_turn()

//                                  actor_move()

//

// Mod Date: 06/05/01 DCP

//                                  Replaced TO_ANGLE with vec_to_angle()

function attack_approach()

{

            // calculate a direction to walk into

            temp.X = player.X - MY.X;

            temp.Y = player.Y - MY.Y;

            temp.Z = 0;

//---            TO_ANGLE MY_ANGLE,temp;

            vec_to_angle(MY_ANGLE,temp);

            // ADD random deviation angle

            MY._TARGET_PAN = MY_ANGLE.PAN - 15 + RANDOM(30);

 

            while((MY._STATE == _STATE_ATTACK) && (MY._COUNTER > 0))

            {

            // turn towards player

                        MY_ANGLE.PAN = MY._TARGET_PAN;

                        MY_ANGLE.TILT = 0;

                        MY_ANGLE.ROLL = 0;

                        force = MY._FORCE * 2;

                        actor_turn();

 

                        // walk towards him if not too close

                        temp = (player.X - MY.X)*(player.X - MY.X)+(player.Y - MY.Y)*(player.Y - MY.Y);

                        if(temp > 10000)  // 100^2

                        {

                                    force = MY._FORCE;

                                    MY._MOVEMODE = _MODE_WALKING;

                                    actor_move();

                        }

 

                        wait(1);

                        MY._COUNTER -= TIME;

            }

}

 

// low on health => try to run away

function state_escape()

{

IFDEF WAR_CHAT_ON;

msg.STRING = war_escape_str;

show_message();

ENDIF;

            MY._STATE = _STATE_ESCAPE;

            while(MY._STATE == _STATE_ESCAPE)

            {

                        if(MY._HEALTH <= 0)

                        {

                                    EXCLUSIVE_ENTITY;

                                    wait(1);

                                    state_die();

                                    return;

                        }

 

                        // turn away from player

                        temp.X = MY.X - player.X;

                        temp.Y = MY.Y - player.Y;

                        temp.Z = MY.Z - player.Z;

                        vec_to_angle(MY_ANGLE,temp);

                        force = MY._FORCE * 6;

                        actor_turn();

 

                        force = MY._FORCE * 4;

                        MY._MOVEMODE = _MODE_WALKING;

                        actor_move();

 

                        wait(1);

            }

}

 

 

// Desc: Die:

//                                              -stop moving

//                                              -stop scanning and shooting

//                                              -null out my.event

//                                              -play death animation

//                                              -become passable

//

//

//          Mod Date: 08/22/01 DCP

//                      Use advanced animation for death (twice attack ticks).

//          Notes: Uses entity's _AMIMDIST value as a 'percent death' value (0 start, 100 end)

function state_die()

{

IFDEF WAR_CHAT_ON;

msg.STRING = war_dead_str;

show_message();

ENDIF;

            MY._MOVEMODE = 0;                  // don't move anymore

            MY._STATE = _STATE_DIE;

            MY.ENABLE_SCAN = OFF;                     // get deaf and blind

            MY.ENABLE_SHOOT = OFF;

            MY.EVENT = NULL;                         // and don't react anymore

 

            // check if we have a marker...

            if(MY.ENTITY1 != 0)

            {

                        // if so, remove it.

                        remove(MY.ENTITY1);

            }

 

            // check for *ADVANCED ANIMATION* (frame names and entity tick/dist values)

            if(int(MY._WALKFRAMES) < 0)

            {

                        // reset entity's animation time to zero

                        MY._ANIMDIST = 0;

 

                        while(MY._ANIMDIST < 100)

                        {

                                    // if you have more than one attacking animation, here's where you would test for it...

                                    // calculate a percentage out of the animation time

                                    MY._ANIMDIST +=  100*(TIME / (INT(((-MY._ADVANIM_TICK)&MASK_ANIM_ATTACK_TICKS)>>9))); // (x>>10) * 2

                                    // set the frame from the percentage

                                    ent_frame(anim_death_str,MY._ANIMDIST);

                                    wait(1);

                        }

            }

            else

            {

                        // decide whether it's a frame number (old) or frame name (new) animation

                        if(frc(MY._WALKFRAMES) > 0)// OLD STYLE ATTACK ANIMATION

                        {

                                    MY.FRAME = 1 + MY._WALKFRAMES + MY._RUNFRAMES + MY._ATTACKFRAMES + 1;

                                    MY.NEXT_FRAME = 0;      // inbetween to the real next frame

                                    while(MY.FRAME <= (1 + MY._WALKFRAMES + MY._RUNFRAMES + MY._ATTACKFRAMES + MY._DIEFRAMES))

                                    {

                                                wait(1);

                                                MY.FRAME += 0.7 * TIME;

                                    }

                        }// END OLD STYLE Death ANIMATION

                        else // new animation format    (frc(MY._WALKFRAMES) == 0)

                        {

                                    // reset entity's animation time to zero

                                    MY._ANIMDIST = 0;

 

                                    while(MY._ANIMDIST < 100)

                                    {

                                                wait(1);

                                                // calculate a percentage out of the animation time

                                                MY._ANIMDIST += 5.0 * TIME;   // death in ~1.25 seconds

                                                // set the frame from the percentage

                                                // -old- SET_FRAME            ME,anim_death_str,MY._ANIMDIST;

                                                ent_frame(anim_death_str,MY._ANIMDIST);

                                    }

                        }// END NEW STYLE ATTACK ANIMATION

            } // END NOT ADVANCED

 

 

            // If entity explodes after death

            if((ME != player) && ((MY._HITMODE & MODE_HIT) == HIT_EXPLO))//(MY._HITMODE & HIT_EXPLO))

            {

 

                        morph(ACTOR_EXPLO,ME);

                          MY._DIEFRAMES = ACTOR_EXPLO_FRAMES;

                          actor_explode();       // ends with the removal of this entity

                        return;

            }

 

            // If entity 'gibs' after death

            if((ME != player) && ((MY._HITMODE & MODE_HIT) == HIT_GIB))//(MY._HITMODE & HIT_GIB))

            {

                          _gib(25);                                // use new "gib" function

                          actor_explode();     // ends with the removal of this entity

                        return;

            }

            MY.PASSABLE = ON;   // body remains

}

 

 

 

 

// Desc: used to "tag" the last know target location

//       "CREATE <arrow.pcx>, MY.POS, _last_know_target_loc;"

function _last_know_target_loc()

{

            YOUR.ENTITY1 = ME;

            MY.INVISIBLE = ON;

            MY.PASSABLE = ON;

}

 

// Desc: move to the entity1 location

function hunt_approach()

{

            ent_marker = MY.ENTITY1;

            // calculate a direction to walk into

            temp.X = ent_marker.X - MY.X;

            temp.Y = ent_marker.Y - MY.Y;

            temp.Z = ent_marker.Z - MY.Z;

            vec_to_angle(MY_ANGLE,temp);

            MY._TARGET_PAN = MY_ANGLE.PAN;

 

   // turn towards target

            MY_ANGLE.PAN = MY._TARGET_PAN;

            MY_ANGLE.TILT = 0;

            MY_ANGLE.ROLL = 0;

            force = MY._FORCE * 2;

            actor_turn();

            if(avoid_walls() == 1)                     // avoid hitting walls

            {

                        force = MY._FORCE * 4;

                        actor_turn();

            }

 

 

            temp = (ent_marker.X - MY.X)*(ent_marker.X - MY.X)+(ent_marker.Y - MY.Y)*(ent_marker.Y - MY.Y);

            // walk towards target only if not too close

            if(temp < 100) // 10^2

            {

                        remove(MY.ENTITY1);        // remove marker

                        EXCLUSIVE_ENTITY;

                        wait(1);

                        state_wait(); // branch to wait mode

                        return;

            }

 

            // walk towards ent_marker

            force = MY._FORCE;

            MY._MOVEMODE = _MODE_WALKING;

            actor_move();

 

}

 

 

// Desc: avoid hitting walls

//

// Return: 1 if to close to a wall, o otherwise

function avoid_walls()

{

            // shoot a line between the entity and the target point

            SHOOT MY.POS, ent_marker.POS;

 

            IF((YOU != ent_marker) && (RESULT < 50))  // too close to a wall...

            {

                        // angle away from the wall.

                        temp.X = (TARGET.X + (100 * NORMAL.X)) - MY.X;

                        temp.Y = (TARGET.Y + (100 * NORMAL.Y)) - MY.Y;

                        temp.Z = MY.Z;

                        vec_to_angle(MY_ANGLE,temp);

                        RETURN(1);

            }

            RETURN(0);

}

 

 

// Desc: follow a wall until you reach a corner

//

// NOTE: to-do (pathfind.wdl?)

function follow_wall()

{

            RETURN(0);

}

 

// Desc: Use internal and external values to branch to other states

//

// Mod Date: 7/26/01 MWS

//                                              Escape branch tests for MY._I_COWARDICE instead of constant 30

function hunt_transitions()

{

            while(MY._STATE == _STATE_HUNT)

            {

                        // Check heath

                        IF(MY._HEALTH <= 0)     // goto die state

                        {

                                    EXCLUSIVE_ENTITY;

                                    wait(1);

                                    state_die();

                                    return;

                        }

 

                        if(MY._HEALTH <= MY._I_COWARDICE  &&  MY._I_COWARDICE >= 0)     // low health? Escape

                        {

                                    EXCLUSIVE_ENTITY;

                                    wait(1);

                                    state_escape();

                                    return;

                        }

 

                        // scan for the player coming near

                        temp.PAN = 180;

                        temp.TILT = 180;

                        temp.Z = MY._I_ALERTNESS;

                        indicator = _WATCH;

                        SCAN            MY.POS,MY.ANGLE,temp;

 

                        // if the player has been detected...

                        if(MY._SIGNAL == _DETECTED)

                        {

                                    MY._SIGNAL = 0;

                                    remove(MY.ENTITY1);

                                    EXCLUSIVE_ENTITY;

                                    wait(1);

                                    state_attack();  // ATTACK!

                                    return;

                        }

 

                        // Check debug

                        IF(freeze_actors > 0)  // goto freeze state

                        {

                                    EXCLUSIVE_ENTITY;

                                    wait(1);

                                    state_freeze();

                                    return;

                        }

 

                        waitt(1);

            }

}

 

// Desc: if you lose your target, move towards its last know location while

//                        scanning.

function            state_hunt()

{

            MY._STATE = _STATE_HUNT;

IFDEF WAR_CHAT_ON;

msg.STRING = war_hunt_str;

show_message();

ENDIF;

            // create a "marker" at the last known player location

            create(<arrow.pcx>, PLAYER.POS, _last_know_target_loc);

            MY._MOVEMODE = _MODE_WALKING; // stop patrolling etc.

            hunt_transitions();      // branch to other states depending on values

 

            while(MY._STATE == _STATE_HUNT)

            {

                        // approach the marker

                        hunt_approach();

 

                        wait(1);

            }

}

 

 

// Desc: freeze in place

function state_freeze()

{

            MY._STATE = _STATE_FREEZE;

            MY._MOVEMODE = _MODE_STILL;         // stop patrolling etc.

            while(MY._STATE == _STATE_FREEZE)

            {

                        if(freeze_actors > 1)

                        {

                                    MY.PASSABLE = ON;

                        }

 

                        if(freeze_actors == 0)

                        {

                                    state_wait();

                                    return;

                        }

 

                        wait(1);

            }

}

 

////////////////////////////////////////////////////////////////////////

 

// Desc: take damage and detect player

//

// Mod: 02/06/01 DCP

//                      Added wait before shoot command to remove 'Dangerous instruction error'

//             Replaced SHOOT with trace()

//

// Mod: 05/05/01 DCP

//                      Modified damage from ranged explosion (replaced ABS with MAX)

function fight_event()

{

            if((EVENT_TYPE == EVENT_SCAN && indicator == _EXPLODE)

                        || (EVENT_TYPE == EVENT_SHOOT && indicator == _GUNFIRE))

            {

                        MY._SIGNAL = _DETECTED;            // by shooting, player gives away his position

 

                        if (indicator == _EXPLODE)

                        {            // reduce damage according to distance

 

                                    damage *= max(0,(range - RESULT))/range;

                        }

 

                        if(MY._ARMOR <= 0)

                        {

                                    MY._HEALTH -= damage;

                        }

                        else

                        {

                                    MY._ARMOR -= damage;

                        }

                        return;

            }

 

            if(EVENT_TYPE == EVENT_DETECT && YOU == player)

            {

                        wait(1);           //fix for dangerous instruction

                        indicator = _WATCH;

//---                 SHOOT MY.POS,YOUR.POS;            // can player be seen from here?

                        trace_mode = IGNORE_ME + IGNORE_PASSABLE + ACTIVATE_SHOOT;

                        RESULT = trace(MY.POS,YOUR.POS); // if entity YOU was visible from MY position, its SHOOT event was triggered

                        if((RESULT > 0) && (YOU == player)) // yes

                        {

                                    MY._SIGNAL = _DETECTED;

                        }

                        return;

            }

}

 

// Desc: init actor for fighting and branch to the wait state

function actor_fight()

{

//            if(MY._ARMOR == 0) { MY._ARMOR = 100; }

            if(MY._HEALTH == 0) { MY._HEALTH = 100; }            // default health

            if(MY._FORCE == 0) { MY._FORCE = 1; }       // default force

 

            // Allow player to pass thru actor if frozen

            if(freeze_actors > 1) { MY.PASSABLE = ON; }

 

            MY._SIGNAL = 0;

            MY.ENABLE_SCAN = ON;

            MY.ENABLE_SHOOT = ON;

            MY.ENABLE_DETECT = ON;

            MY.EVENT = fight_event;

 

            state_wait();

}

 

 

// PLAYER ACTIONS

///////////////////////////////////////////////////////////////////////

 

//                      player_walk_fight - player walk and fight action (basic FPS)

 

/////////////////////////////////////////////////////////////////////////

// Desc: player action. Walk and fight (take damage, use gun)

//

//          Used for basic FPS type games.  Set the following skills and flags in

//WED to define the player (note: all skills default to 0, all flags

//default to OFF)

//

//          Flags

//                      Flag1 - ON = *NO damage from falls*

//                                              OFF = Take damage from falls

//                      Flag2 - ON = move as a car (i.e. no turning unless moving),

//                                              OFF = move normally

//                      Flag3 - ON = adapt tilt and roll angle to slops

//                                              OFF = stay upright while walking up and down slops (normal)

//                      Flag4 - ON = *NO JUMPING*

//                                              OFF = Allow jumping

//                      Flag5 - ON = *NO first person view "head-bob" while moving*

//                                              OFF = Enable first person view "head-bob"

//                      Flag6 - ON = *Disable strafe*

//                                              OFF = Allow strafing

//                      Flag7 - ON = *Disable trigger* (open doors automatically)

//                                              OFF = Trigger on

//                      Flag8 - ON = *NO DUCKING*

//                                              OFF = Enable ducking

//          Skills

//            _WALKSWIM_DIST, SKILL1;               // Walk Distance . Swim Distance

//            _RUNCRAWL_DIST, SKILL2;               // Run Distance . Crawl Distance

//            _STANDJUMP_TIME, SKILL3;              // Stand Time . Jump Time

//            _ATTACKDUCK_TIME, SKILL4;             // Attack Time . Duck Time

//            _RUNTHRESHOLD, SKILL14;                    // Run Threshold

//            _FORCE, SKILL5;                                       // Force

//            _BANKING, SKILL6;                                              // Hitmode (actor only)

//            _MOVEMODE, SKILL7;                                  // Starting movemode

//            _HEALTH, SKILL9;                                     // Heath

//            _ARMOR, SKILL10;                                     // Armor

//

// Mod: 6/18/01 DCP

//                      Created

//

// Mod: 8/21/01 DCP

//                      Updated to use new WED skills

//

ACTION player_walk_fight

{

// player

// uses: _WALKSWIM_DIST,_RUNCRAWL_DIST,_STANDJUMP_TIME,_ATTACKDUCK_TIME,

//                      _FORCE,_BANKING,_MOVEMODE,_FIREMODE,_HEALTH,_ARMOR,_RUNTHRESHOLD

            // Flags-------------------------------

            IF(MY.FLAG1 == ON) { MY.__FALL = OFF; }

            ELSE { MY.__FALL = ON; }

            //MY.__WHEELS = MY.FLAG2; // note: redundant

            //MY.__SLOPES = MY.FLAG3; // note: redundant

            IF(MY.FLAG4 == ON) { MY.__JUMP = OFF; }

            ELSE { MY.__JUMP = ON; }

            IF(MY.FLAG5 == ON) { MY.__BOB = OFF; }

            ELSE { MY.__BOB = ON; }

            IF(MY.FLAG6 == ON) { MY.__STRAFE = OFF; }

            ELSE { MY.__STRAFE = ON; }

            IF(MY.FLAG7 == ON) { MY.__TRIGGER = OFF; }

            ELSE { MY.__TRIGGER = ON; }

            IF(MY.FLAG8 == ON) { MY.__DUCK = OFF; }

            ELSE { MY.__DUCK = ON; }

 

            // Skill1------------------------------

            if (MY._HEALTH == 0) {                                // if user didn't enter a value

                        MY._HEALTH = 100;                                                // use default

            }

 

            if (MY._ARMOR < 0) {                                               // if bad value specified somehow

                        MY._ARMOR = 0;                                                     // default to zero

            }

 

            if( MY._FORCE <= 0)

            {

                        MY._FORCE = 0.75;                                     // use default

            }

 

 

            player_anim_pack();           // use SKILLs 1-4 to set up animation

 

            // Other-------------------------------

            MY.NARROW = ON;     // use narrow hull!

            MY.FAT = OFF;

             MY.TRIGGER_RANGE = 5;

            if( MY._MOVEMODE <= 0)

            {

                        MY._MOVEMODE = _MODE_WALKING;

            }

 

            if( MY._BANKING == 0)

            {

                        MY._BANKING = -0.1;

            }

 

            player_move();    // basic player move loop

            player_fight();   // basic player fight loop

            drop_shadow();                      // add a drop shadow (if the player has no 'real' shadow)

            show_panels();    // show heath/armor/ammo panel

 

}

 

 

 

// Desc - An entity action that will make a generic AI player with skill

//                                  settings that can be set as above in WED

////////////////////////////////////////////////////////////

// These skills can be set in WED for the intended effect //

////////////////////////////////////////////////////////////

//            _WALKSWIM_DIST, SKILL1;               // Walk Distance . Swim Distance

//            _RUNCRAWL_DIST, SKILL2;               // Run Distance . Crawl Distance

//            _STANDJUMP_TIME, SKILL3;              // Stand Time . Jump Time

//            _ATTACKDUCK_TIME, SKILL4;             // Attack Time . Duck Time

//            _RUNTHRESHOLD, SKILL14;                    // Run Threshold

//            _FORCE, SKILL5;                                       // Force

//            _HITMODE, SKILL6;                                     // Hitmode (actor only)

//            _MOVEMODE, SKILL7;                                  // Starting movemode

//            _FIREMODE, SKILL8;                                  // Firemode

//            _HEALTH, SKILL9;                                     // Heath

//            _ARMOR, SKILL10;                                     // Armor

//            _ALERTNESS, SKILL11;           // Alertness

//            _ACCURACY, SKILL12;                                // Accuracy

//            _COWARDICE, SKILL13;                                // Cowardice

//            _MUZZLEATTACH, SKILL15;                    // Muzzle vertex . Attach vertex

////////////////////////////////////////////////////////////

// 07/16/01 - MWS - Created

// 07/24/01 - MWS - Overhauled (16 WED skills now!)

//

// Mod: 8/21/01 DCP

//                      Updated to use new WED skills

//

// uses: _WALKSWIM_DIST,_RUNCRAWL_DIST,_STANDJUMP_TIME,_ATTACKDUCK_TIME,

//                      _FORCE,_HITMODE,_MOVEMODE,_FIREMODE,_HEALTH,_ARMOR,_ALERTNESS,

//                      _ACCURACY,_COWARDICE,_RUNTHRESHOLD,_MUZZLEATTACH

//

action actor_walk_fight

{

            // Health-

            if (MY._HEALTH <= 0) { MY._HEALTH = 50; }            // default 50 health

 

            // Armor-

            if (MY._ARMOR <= 0) { MY._ARMOR = 0; }   // default 0 armor

 

            // Force-

            if (MY._FORCE == 0) { MY._FORCE = 1.5; }             // default force

 

            // Alertness-

            MY._I_ALERTNESS = MY._ALERTNESS;

 

            // Cowardice-

            MY._I_COWARDICE = MY._COWARDICE;

 

            // Firemode-

            if (MY._FIREMODE == 0)

            { MY._FIREMODE = DAMAGE_SHOOT+FIRE_PARTICLE+HIT_FLASH+0.10; }      // use default

 

            // Accuracy-

            if (MY._ACCURACY > 0)

            {

                        MY._I_ACCURACY = MY._ACCURACY; // positive value given, use specified accuracy

            }

            else

            {

                        if (MY._ACCURACY < 0)

                        { MY._I_ACCURACY = 0; }            // negative value given, use perfect accuracy

                        else // MY._ACCURACY == 0

                        { MY._I_ACCURACY = 5; }            // no value given, use default accuracy

            }

 

 

 

            // Hitmode-

            //--MY._HITMODE = MY._HITMODE;      // zero is the default, no extra checking needed

 

 

            // Muzzle Vertex-

            MY._MUZZLE_VERT = int(MY._MUZZLEATTACH);

 

 

 

            // uses same advanced animation packing as player (dont let the function name fool you)

            player_anim_pack();

 

            // Other setup

            MY._WALKSOUND = _SOUND_ROBOT;

            anim_init();    // setup animation a bit

            drop_shadow(); // attach shadow to robot

            actor_fight();  // start simple AI state machine

}

 

 

 

/*

 

These skills are set in WED as below - 7/12/01 - MWS

 

_WALKSWIM_DIST Walk Distance . Swim Distance

_RUNCRAWL_DIST Run Distance . Crawl Distance

_STANDJUMP_TIME          Stand Time . Jump Time

_ATTACKDUCK_TIME       Attack Time . Duck Time

_RUNTHRESHOLD             Run Threshold

 

Note: Times and distances after decimal use only TWO decimal places

 

-----------

Default animation values, taken from animate.wdl

-----------

(divide these by 4 for quarter-seconds, as they're 16ths now)

var anim_stand_ticks = 16;            // time for one standing anim cycle

var anim_jump_ticks = 6; // time for one jump animation cycle

var anim_attack_ticks = 16;// time for one attack animation cycle

var anim_duck_ticks = 8; // time for one duck animation cycle

 

(multiply these by 4 for quarter-widths)

var anim_walk_dist = 1; // dist per model width per walk cycle

var anim_swim_dist = 1; // dist per model width per swim cycle

var anim_run_dist = 1.5;   // dist per model width per run cycle

var anim_crawl_dist = 0.8; // dist per model width per crawl cycle

//var anim_wade_dist = 0.8;// dist per model width per crawl cycle (unused)

 

var walk_or_run = 12;       // max quants per tick to switch from walk to run animation

*/

var            pap_pack1; // used to pack SKILL1

var            pap_pack2; // used to pack SKILL2

 

function player_anim_pack()

{

            pap_pack1 = 0;            //reset

            pap_pack2 = 0;            //reset

 

            // Stand Time

            temp = INT(MY._STANDJUMP_TIME);                                                                  // quarter seconds

            if (temp == 0) {                                                                                      // no value entered in WED

                        temp = 4;                                                                                                         // default anim_stand_ticks = 16

            }

             pap_pack1 += temp >> 10;                                                    // fractional 10 bits (2^10 = 1024)

            //pap_pack1 += temp / 1024;                                         // fractional 10 bits (2^10 = 1024)

 

 

            // Jump Time

            temp = INT(FRC(MY._STANDJUMP_TIME) * 100);                // quarter seconds

            if (temp == 0) {                                                                                      // no value entered in WED

                        temp = 2;                                                                                                         // default anim_jump_ticks = 6

            }

            pap_pack1 += temp << 6;                                                               // middle 6 bits (2^6 = 64)

            //pap_pack1 += temp * 64;                                                    // middle 6 bits (2^6 = 64)

 

 

            // Attack Time

            temp = INT(MY._ATTACKDUCK_TIME);                                                            // quarter seconds

            if (temp == 0) {                                                                                      // no value entered in WED

                        temp = 4;                                                                                                         // default anim_attack_ticks = 16

            }

            pap_pack1 += temp << 12;                                                  // upper 9 bits, shift 12 (2^12 = 4096)

            //pap_pack1 += temp * 4096;                                                // upper 9 bits, shift 12 (2^12 = 4096)

 

 

            // Duck Time

            temp = INT(FRC(MY._ATTACKDUCK_TIME) * 100);                // quarter seconds * 4 = game ticks

            if (temp == 0) {                                                                                      // no value entered in WED

                        temp = 2;                                                                                                         // default anim_duck_ticks = 8

            }

            pap_pack1 += temp;                                                                           // lowest 6 bits

 

 

            // Walk Distance

            temp = INT(MY._WALKSWIM_DIST);                   // quarter widths

            if (temp == 0) {                                                                                      // no value entered in WED

                        temp = 4;                                                                                                         // default anim_walk_dist = 1

            }

            pap_pack2 += temp << 10;                                                  // next upper 5 bits (2^10 = 1024)

            //pap_pack2 += temp * 1024;                                                  // next upper 5 bits (2^10 = 1024)

 

 

            // Swim Distance

            temp = INT(FRC(MY._WALKSWIM_DIST) * 100);                // quarter widths

            if (temp == 0) {                                                                                      // no value entered in WED

                        temp = 4;                                                                                                         // default anim_swim_dist = 1

            }

            pap_pack2 += temp;                                                                             // bottom 5 bits

 

 

            // Skill6------------------------------

            // Run Distance

            temp = INT(MY._RUNCRAWL_DIST);                                                     // quarter widths

            if (temp == 0) {                                                                                      // no value entered in WED

                        temp = 6;                                                                                                         // default anim_run_dist = 1.5

            }

            pap_pack2 += temp << 15;                                                   // upper 6 bits (2^15 = 2^10 * 2^5 = 1024 * 32)

            //pap_pack2 += temp * 1024 * 32;                              // upper 6 bits (2^15 = 2^10 * 2^5 = 1024 * 32)

 

 

            // Crawl Distance

            temp = INT(FRC(MY._RUNCRAWL_DIST) * 100);                  // quarter widths

            if (temp == 0) {                                                                                      // no value entered in WED

                        temp = 3;                                                                                                         // default anim_crawl_dist = 0.8

            }

            pap_pack2 += temp << 5;                                                                // upper 5 bits (2^5 = 32)

            //pap_pack2 += temp * 32;                                                    // upper 5 bits (2^5 = 32)

 

 

            // Skill7------------------------------

            // Walk Or Run

            temp = INT(MY._RUNTHRESHOLD);                                                        // whole quants

            if (temp == 0) {                                                                                      // no value entered in WED

                        temp = 12;                                                                                                       // default walk_or_run = 12

            }

            pap_pack2 += temp >> 10;                                                  // fractional 10 bits (2^10 = 1024)

            //pap_pack2 += temp / 1024;                                       // fractional 10 bits (2^10 = 1024)

 

 

            MY._ADVANIM_TICK = -1 * pap_pack1;                  // activate advanced animation

            MY._ADVANIM_DIST  = -1 * pap_pack2;                  // activate advanced animation

}

 

 

 

 

 

 

function player_fight()

{

            if(MY._HEALTH == 0) { MY._HEALTH = 100; }

 

            MY.ENABLE_SCAN = ON;

            MY.ENABLE_SHOOT = ON;

            MY.EVENT = fight_event;

 

            while(MY._HEALTH > 0)

            {

                        if(MY._SIGNAL == _DETECTED) {          // Hit received?

                                    MY._SIGNAL = 0;            // reset the _signal skill

                                    if(person_3rd == 0) {

                                                player_shake(); }

                        }

                        wait(1);

            }

 

// Dead

            MY._HEALTH = 0;

            if(person_3rd == 0)

            {            // 1st person die action

                        MY._MOVEMODE = 0;                  // don't move anymore

                        MY.EVENT = NULL;             // prevent health counting down

                        player_tip();

                        waitt(8);

                        weapon_remove();             // let weapon disappear

            }

            else

            {

                        weapon_remove();            // prevent dead player firing

                        state_die();

                        return;

            }

}

 

 

 

 

 

// Desc: explode into x number of random models

//

// Mod Date: 8/22/00 DCP

//                                              Uses function parameter (numberOfParts) to determine

//                                  how many 'gib' parts to create

function            _gib(numberOfParts)

{

            temp = 0;

            while(temp < numberOfParts)

            {

                        create(<gibbit.mdl>, MY.POS, _gib_action);

                        temp += 1;

            }

 

}

 

// Desc: Init and animate a gib-bit

//

// Mod Date: 6/29/00 Doug Poston

//                                              Added rotation and alpha-fading

// Mod Date: 8/31/00 DCP

//                                              Scale absdist vector by movement_scale

//                                              Scale the gibbits down by the actor_scale

function _gib_action()

{

            // scall the bits down by the actor_scale amount

            vec_scale(MY.SCALE_X,actor_scale);

 

            // Init gib bit

            MY._SPEED_X = 25 * (RANDOM(10) - 5);    // -125 -> +125

            MY._SPEED_Y = 25 * (RANDOM(10) - 5);    // -125 -> +125

            MY._SPEED_Z = RANDOM(35) + 15;          // 15 -> 50

 

            MY._ASPEED_PAN = RANDOM(35) + 35;       // 35 -> 70

            MY._ASPEED_TILT = RANDOM(35) + 35;      // 35 -> 70

            MY._ASPEED_ROLL = RANDOM(35) + 35;      // 35 -> 70

 

            MY.ROLL = RANDOM(180);        // start with a random orientation

            MY.PAN = RANDOM(180);

 

            MY.PUSH = -1;            // allow user/enemys to push thru

 

 

 

            // Animate gib-bit

            MY.SKILL9 = RANDOM(50);

            while(MY.SKILL9 > -75)

            {

                        abspeed[0] = MY._SPEED_X * TIME;

                        abspeed[1] = MY._SPEED_Y * TIME;

                        abspeed[2] = MY._SPEED_Z * TIME;

 

                        MY.PAN += MY._ASPEED_PAN * TIME;

                        MY.TILT += MY._ASPEED_TILT * TIME;

                        MY.ROLL += MY._ASPEED_ROLL * TIME;

 

                        vec_scale(absdist,movement_scale);            // scale absolute distance by movement_scale

                        MOVE  ME,NULLSKILL,abspeed;

 

                        IF(BOUNCE.Z)

                        {

                                    MY._SPEED_Z = -(MY._SPEED_Z/2);

                                    if(MY._SPEED_Z < 0.25)

                                    {

                                                MY._SPEED_X = 0;

                                                MY._SPEED_Y = 0;

                                                MY._SPEED_Z = 0;

                                                MY._ASPEED_PAN = 0;

                                                MY._ASPEED_TILT = 0;

                                                MY._ASPEED_ROLL = 0;

                                    }

                        }

 

                        MY._SPEED_Z -= 2;

                        MY.SKILL9 -= 1;

 

                        wait(1);

            }

 

 

            // Fade out

            MY.transparent = ON;

            MY.alpha = 100;

            while(1)

            {

               MY.alpha -= 5*time;

                        if(MY.alpha <=0)

                        {

                                    // remove

                                    remove(ME);

                                    return;

                        }

 

               wait(1);