Barnacle Grapple

Barnacle Grapple 1.1

Нет прав для скачивания
Код:
/* AMX Mod X
*    Barnacle Grapple.
*
* http://aghl.ru/forum/ - Russian Half-Life and Adrenaline Gamer Community
*
* This file is provided as is (no warranties)
*/

#pragma semicolon 1
#pragma ctrlchar '\'

#include <amxmodx>
#include <beams>
#include <hamsandwich>
#include <hl_wpnmod>
#include <xs>


#define PLUGIN "Barnacle Grapple"
#define VERSION "1.1"
#define AUTHOR "KORD_12.7"
 

// Weapon settings
#define WEAPON_NAME             "weapon_grapple"
#define WEAPON_SLOT            1
#define WEAPON_POSITION            5
#define WEAPON_PRIMARY_AMMO        "" // NULL
#define WEAPON_PRIMARY_AMMO_MAX        -1
#define WEAPON_SECONDARY_AMMO        "" // NULL
#define WEAPON_SECONDARY_AMMO_MAX    -1
#define WEAPON_MAX_CLIP            -1
#define WEAPON_DEFAULT_AMMO        -1
#define WEAPON_FLAGS            0
#define WEAPON_WEIGHT            21

// Grapple settings
#define GRAPPLE_FLY_VELOCITY        1500
#define GRAPPLE_PULL_VELOCITY        400.0

// Hud
#define WEAPON_HUD_TXT            "sprites/weapon_grapple.txt"
#define WEAPON_HUD_SPR            "sprites/weapon_grapple.spr"

// Models
#define MODEL_VIEW            "models/v_bgrap_koshak.mdl"
#define MODEL_WORLD            "models/w_bgrap.mdl"
#define MODEL_PLAYER            "models/p_bgrap.mdl"
#define MODEL_TONGUE_TIP        "models/shock_effect.mdl"

// Sprites
#define SPRITE_TONGUE            "sprites/tongue.spr"

// Sounds
#define SOUND_DRAW            "weapons/alienweap_draw.wav"
#define SOUND_WAIT            "weapons/bgrapple_wait.wav"
#define SOUND_PULL            "weapons/bgrapple_pull.wav"
#define SOUND_FIRE            "weapons/bgrapple_fire.wav"
#define SOUND_COUGH            "weapons/bgrapple_cough.wav"
#define SOUND_CHEW_1            "barnacle/bcl_chew1.wav"
#define SOUND_CHEW_2            "barnacle/bcl_chew2.wav"
#define SOUND_CHEW_3            "barnacle/bcl_chew3.wav"
#define SOUND_IMPACT            "weapons/bgrapple_impact.wav"
#define SOUND_RELEASE            "weapons/bgrapple_release.wav"

// Animation
#define ANIM_EXTENSION            "gauss"

enum _:GrappleAnim
{
    ANIM_BREATHE = 0,
    ANIM_LONGIDLE,
    ANIM_SHORTIDLE,
    ANIM_COUGH,
    ANIM_DOWN,
    ANIM_UP,
    ANIM_FIRE,
    ANIM_FIREWAITING,
    ANIM_FIREREACHED,
    ANIM_FIRETRAVEL,
    ANIM_FIRERELEASE
};

#define SET_SIZE(%0,%1,%2) engfunc(EngFunc_SetSize,%0,%1,%2)
#define SET_ORIGIN(%0,%1) engfunc(EngFunc_SetOrigin,%0,%1)

enum
{
    FIRE_OFF,
    FIRE_CHARGE
}

#define Offset_iTip    Offset_iuser1
#define Offset_iBeam    Offset_iuser2

#define Offset_iPull    Offset_iuser1
#define Offset_iTarget    Offset_iuser2

//**********************************************
//* Precache resources                         *
//**********************************************

public plugin_precache()
{
    PRECACHE_MODEL(MODEL_VIEW);
    PRECACHE_MODEL(MODEL_WORLD);
    PRECACHE_MODEL(MODEL_PLAYER);
    PRECACHE_MODEL(SPRITE_TONGUE);
    PRECACHE_MODEL(MODEL_TONGUE_TIP);
    
    PRECACHE_SOUND(SOUND_DRAW);
    PRECACHE_SOUND(SOUND_WAIT);
    PRECACHE_SOUND(SOUND_PULL);
    PRECACHE_SOUND(SOUND_FIRE);
    PRECACHE_SOUND(SOUND_COUGH);
    PRECACHE_SOUND(SOUND_CHEW_1);
    PRECACHE_SOUND(SOUND_CHEW_2);
    PRECACHE_SOUND(SOUND_CHEW_3);
    PRECACHE_SOUND(SOUND_IMPACT);
    PRECACHE_SOUND(SOUND_RELEASE);
    
    PRECACHE_GENERIC(WEAPON_HUD_TXT);
    PRECACHE_GENERIC(WEAPON_HUD_SPR);
}

//**********************************************
//* Register weapon.                           *
//**********************************************

public plugin_init()
{
    register_plugin(PLUGIN, VERSION, AUTHOR);
    
    new iGrapple = wpnmod_register_weapon
    
    (
        WEAPON_NAME,
        WEAPON_SLOT,
        WEAPON_POSITION,
        WEAPON_PRIMARY_AMMO,
        WEAPON_PRIMARY_AMMO_MAX,
        WEAPON_SECONDARY_AMMO,
        WEAPON_SECONDARY_AMMO_MAX,
        WEAPON_MAX_CLIP,
        WEAPON_FLAGS,
        WEAPON_WEIGHT
    );
    
    wpnmod_register_weapon_forward(iGrapple, Fwd_Wpn_Spawn, "Grapple_Spawn");
    wpnmod_register_weapon_forward(iGrapple, Fwd_Wpn_Deploy, "Grapple_Deploy");
    wpnmod_register_weapon_forward(iGrapple, Fwd_Wpn_PrimaryAttack, "Grapple_PrimaryAttack");
    wpnmod_register_weapon_forward(iGrapple, Fwd_Wpn_SecondaryAttack, "Grapple_SecondaryAttack");
    wpnmod_register_weapon_forward(iGrapple, Fwd_Wpn_Idle, "Grapple_Idle");
    wpnmod_register_weapon_forward(iGrapple, Fwd_Wpn_Holster, "Grapple_Holster");
}

//**********************************************
//* Weapon spawn.                              *
//**********************************************

public Grapple_Spawn(const iItem)
{
    // Setting world model
    SET_MODEL(iItem, MODEL_WORLD);
}

//**********************************************
//* Deploys the weapon.                        *
//**********************************************

public Grapple_Deploy(const iItem)
{
    wpnmod_set_offset_int(iItem, Offset_iFireState, FIRE_OFF);
    
    return wpnmod_default_deploy(iItem, MODEL_VIEW, MODEL_PLAYER, ANIM_UP, ANIM_EXTENSION);
}

//**********************************************
//* Called when the weapon is holster.         *
//**********************************************

public Grapple_Holster(const iItem)
{
    Grapple_DestroyEffect(iItem);
}

//**********************************************
//* Displays the idle animation for the weapon.*
//**********************************************

public Grapple_Idle(const iItem, const iPlayer)
{
    if (wpnmod_get_offset_float(iItem, Offset_flTimeWeaponIdle) > 0.0)
    {
        return;
    }
    
    if (wpnmod_get_offset_int(iItem, Offset_iFireState) != FIRE_OFF)
    {
         Grapple_EndAttack(iItem, iPlayer);
         return;
    }
    
    new iAnim;
    new Float: flRand;
    new Float: flNextIdle;
        
    if ((flRand = random_float(0.0, 1.0)) > 0.5)
    {
        if (flRand > 0.95)
        {
            iAnim = ANIM_COUGH;
            flNextIdle = 4.63;
        }
        else
        {
            iAnim = ANIM_BREATHE;
            flNextIdle = 2.6;
        }
    }
    else
    {
        iAnim = ANIM_LONGIDLE;
        flNextIdle = 10.03;
    }
    
    wpnmod_send_weapon_anim(iItem, iAnim);
    wpnmod_set_offset_float(iItem, Offset_flTimeWeaponIdle, flNextIdle);
}

//**********************************************
//* The main attack of a weapon is triggered.  *
//**********************************************

public Grapple_PrimaryAttack(const iItem, const iPlayer)
{
    Grapple_StartAttack(iItem, iPlayer, true);
}

//**********************************************
//* Secondary attack of a weapon is triggered. *
//**********************************************

public Grapple_SecondaryAttack(const iItem, const iPlayer)
{
    Grapple_StartAttack(iItem, iPlayer, false);
}

//**********************************************
//* Start Grapple attack.                      *
//**********************************************

Grapple_StartAttack(const iItem, const iPlayer, const bool: bPull)
{
    static iFireState;
    static iGrappleTip;
    
    static Float: flGameTime;
    
    flGameTime = get_gametime();
    iFireState = wpnmod_get_offset_int(iItem, Offset_iFireState);
    iGrappleTip = wpnmod_get_offset_int(iItem, Offset_iTip);
    
    wpnmod_set_offset_float(iItem, Offset_flReleaseThrow, bPull ? 0.0 : 1.0);
    
    if (iFireState == FIRE_OFF)
    {
        set_pev(iPlayer, pev_punchangle, Float: {-2.0, 0.0, 0.0});
        
        wpnmod_send_weapon_anim(iItem, ANIM_FIRE);
        wpnmod_set_player_anim(iPlayer, PLAYER_ATTACK1);
            
        wpnmod_set_offset_int(iItem, Offset_iFireState, FIRE_CHARGE);
        wpnmod_set_offset_float(iItem, Offset_flTimeWeaponIdle, 0.1);
        wpnmod_set_offset_float(iItem, Offset_flPumpTime, flGameTime + 0.5);
        wpnmod_set_offset_float(iItem, Offset_flStartThrow, flGameTime + 0.5);
    
        emit_sound(iPlayer, CHAN_WEAPON, SOUND_FIRE, 0.9, ATTN_NORM, 0, PITCH_NORM);
    }
    else if (iFireState == FIRE_CHARGE && pev_valid(iGrappleTip))
    {
        if (wpnmod_get_offset_float(iItem, Offset_flStartThrow) < flGameTime)
        {
            if (wpnmod_get_offset_int(iGrappleTip, Offset_iPull))
            {
                wpnmod_send_weapon_anim(iItem, ANIM_FIRETRAVEL);
                wpnmod_set_offset_float(iItem, Offset_flStartThrow, flGameTime + 0.68);
            }
            else
            {
                wpnmod_send_weapon_anim(iItem, ANIM_FIREWAITING);
                wpnmod_set_offset_float(iItem, Offset_flStartThrow, flGameTime + 0.24);
            }
        }   
                    
        if (wpnmod_get_offset_float(iItem, Offset_flPumpTime) < flGameTime)
        {
            emit_sound(iPlayer, CHAN_WEAPON, SOUND_PULL, 0.9, ATTN_NORM, 0, PITCH_NORM);
            wpnmod_set_offset_float(iItem, Offset_flPumpTime, flGameTime + 0.68);
        }
            
        if (bPull)
        {
            Grapple_Stab(iItem, iPlayer);
        }
    }
    
    Grapple_UpdateEffect(iItem, iPlayer);
}

//**********************************************
//* End Grapple attack.                        *
//**********************************************

Grapple_EndAttack(const iItem, const iPlayer)
{
    Grapple_DestroyEffect(iItem);
    wpnmod_send_weapon_anim(iItem, ANIM_FIRERELEASE);
    
    wpnmod_set_offset_int(iItem, Offset_iFireState, FIRE_OFF);
    wpnmod_set_offset_float(iItem, Offset_flNextPrimaryAttack, 1.0);
    wpnmod_set_offset_float(iItem, Offset_flNextSecondaryAttack, 1.0);
    wpnmod_set_offset_float(iItem, Offset_flTimeWeaponIdle, 0.9);
    
    emit_sound(iPlayer, CHAN_WEAPON, SOUND_PULL, 0.0, 0.0, SND_STOP, PITCH_NORM);
    emit_sound(iPlayer, CHAN_WEAPON, SOUND_RELEASE, 0.9, ATTN_NORM, 0, PITCH_NORM);
}

//**********************************************
//* Tongue tip effects.                        *
//**********************************************

Grapple_UpdateEffect(const iItem, const iPlayer)
{
    static iTip, iBeam;
    
    iTip = wpnmod_get_offset_int(iItem, Offset_iTip);
    
    if (!pev_valid(iTip))
    {
        Grapple_CreateEffect(iItem, iPlayer);
    }
    
    iBeam = wpnmod_get_offset_int(iItem, Offset_iBeam);
    
    if (pev_valid(iBeam))
    {
        Beam_RelinkBeam(iBeam);
    }
}

Grapple_DestroyEffect(const iItem)
{
    new iBeam = wpnmod_get_offset_int(iItem, Offset_iBeam);
    
    if (pev_valid(iBeam))
    {
        set_pev(iBeam, pev_flags, FL_KILLME);
        wpnmod_set_offset_int(iItem, Offset_iBeam, FM_NULLENT);
    }
    
    new iTip = wpnmod_get_offset_int(iItem, Offset_iTip);
    
    if (pev_valid(iTip))
    {
        set_pev(iTip, pev_flags, FL_KILLME);
        wpnmod_set_offset_int(iItem, Offset_iTip, FM_NULLENT);
    }
}

Grapple_CreateEffect(const iItem, const iPlayer)
{
    Grapple_DestroyEffect(iItem);
    
    new iTip;
    new iBeam;
    
    new Float: vecOrigin[3];
    new Float: vecAngles[3];
    new Float: vecVelocity[3];
    
    velocity_by_aim(iPlayer, GRAPPLE_FLY_VELOCITY, vecVelocity);
    wpnmod_get_gun_position(iPlayer, vecOrigin, 16.0, 8.0, -8.0);
    
    static iszAllocStringCached;
    if (iszAllocStringCached || (iszAllocStringCached = engfunc(EngFunc_AllocString, "info_target")))
    {
        iTip = engfunc(EngFunc_CreateNamedEntity, iszAllocStringCached);
    }
    
    if (pev_valid(iTip))
    {
        engfunc(EngFunc_VecToAngles, vecVelocity, vecAngles);
    
        set_pev(iTip, pev_classname, "grapple_tip");
        set_pev(iTip, pev_solid, SOLID_BBOX);
        set_pev(iTip, pev_movetype, MOVETYPE_FLY);
        set_pev(iTip, pev_velocity, vecVelocity);
        set_pev(iTip, pev_angles, vecAngles);
        set_pev(iTip, pev_owner, iPlayer);
        set_pev(iTip, pev_iuser4, iItem);
        
        SET_ORIGIN(iTip, vecOrigin);
        SET_MODEL(iTip, MODEL_TONGUE_TIP);
        SET_SIZE(iTip, Float: {0.0, 0.0, 0.0}, Float: {0.0, 0.0, 0.0});
        
        wpnmod_set_offset_int(iItem, Offset_iTip, iTip);
    
        if (pev_valid((iBeam = Beam_Create(SPRITE_TONGUE, 15.0))))
        {
            set_pev(iBeam, pev_classname, "tongue_beam");
            
            Beam_EntsInit(iBeam, iTip, iPlayer);
            Beam_SetFlags(iBeam, BEAM_FSOLID);
            Beam_SetEndAttachment(iBeam, 1);
            Beam_SetBrightness(iBeam, 100.0);

            wpnmod_set_offset_int(iItem, Offset_iBeam, iBeam);
        }
        
        wpnmod_set_think(iTip, "GrappleTip_FlyThink");
        wpnmod_set_touch(iTip, "GrappleTip_TongueTouch");
        
        set_pev(iTip, pev_nextthink, get_gametime() + 0.1);
    }
}

//**********************************************
//* Tongue tip think funcs.                    *
//**********************************************

public GrappleTip_FlyThink(const iGrappleTip)
{
    static iItem;
    static iOwner;
    
    iItem = pev(iGrappleTip, pev_iuser4);
    iOwner = pev(iGrappleTip, pev_owner);
    
    set_pev(iGrappleTip, pev_nextthink, get_gametime() + 0.1);
    
    if (!ExecuteHamB(Ham_IsInWorld, iGrappleTip))
    {
        Grapple_EndAttack(iItem, iOwner);
    }
}

public GrappleTip_PullThink(const iGrappleTip)
{
    static iItem;
    static iOwner;
    static iTarget;
    
    static Float: flDistance;
    static Float: vecVelocity[3];
    static Float: vecPlayerOrigin[3];
    static Float: vecGrappleOrigin[3];
    
    iItem = pev(iGrappleTip, pev_iuser4);
    iOwner = pev(iGrappleTip, pev_owner);
    iTarget = wpnmod_get_offset_int(iGrappleTip, Offset_iTarget);
    
    if (pev_valid(iTarget) && ExecuteHamB(Ham_Classify, iTarget) && !ExecuteHamB(Ham_IsAlive, iTarget))
    {
        Grapple_EndAttack(iItem, iOwner);
        return;
    }
    
    set_pev(iGrappleTip, pev_nextthink, get_gametime() + 0.1);
    
    if (!wpnmod_get_offset_int(iGrappleTip, Offset_iPull) || wpnmod_get_offset_float(iItem, Offset_flReleaseThrow))
    {
        return;
    }
    
    pev(iOwner, pev_origin, vecPlayerOrigin);
    pev(iGrappleTip, pev_origin, vecGrappleOrigin);
    
    flDistance = get_distance_f(vecGrappleOrigin, vecPlayerOrigin);
    
    if (flDistance)
    {
        xs_vec_sub(vecGrappleOrigin, vecPlayerOrigin, vecGrappleOrigin);
        xs_vec_mul_scalar(vecGrappleOrigin, GRAPPLE_PULL_VELOCITY / flDistance, vecVelocity);
        set_pev(iOwner, pev_velocity, vecVelocity);
    }
}

//**********************************************
//* Tongue tip touch func.                     *
//**********************************************

public GrappleTip_TongueTouch(const iGrappleTip, const iOther)
{
    new iHit;
    new iItem;
    new iOwner;
    
    new szClassName[32];
    new szTextureName[13];
    
    new Float: vecOrigin[3];
    new Float: vecVelocity[3];
    
    iItem = pev(iGrappleTip, pev_iuser4);
    iOwner = pev(iGrappleTip, pev_owner);
    
    pev(iGrappleTip, pev_origin, vecOrigin);
    pev(iGrappleTip, pev_velocity, vecVelocity);
    
    if (pev(iOther, pev_flags) & (FL_CLIENT | FL_MONSTER))
    {
        iHit = true;
        
        set_pev(iGrappleTip, pev_movetype, MOVETYPE_FOLLOW);
        set_pev(iGrappleTip, pev_skin, iOther);
        set_pev(iGrappleTip, pev_body, 0);
        set_pev(iGrappleTip, pev_aiment, iOther);
    }
    else
    {
        pev(iOther, pev_classname, szClassName, charsmax(szClassName));
        
        if (equali(szClassName, "ammo_spore"))
        {
            iHit = true;
        }
        else
        {
            xs_vec_normalize(vecVelocity, vecVelocity);
            xs_vec_mul_scalar(vecVelocity, 8.0, vecVelocity);
            xs_vec_add(vecVelocity, vecOrigin, vecVelocity);
            
            engfunc(EngFunc_TraceTexture, iOther, vecOrigin, vecVelocity, szTextureName, charsmax(szTextureName));
            
            if (equali(szTextureName, "xeno_grapple"))
            {
                iHit = true;
            }
        }   
    }
    
    if (!iHit)
    {
        Grapple_EndAttack(iItem, iOwner);
    }
    else
    {
        wpnmod_set_think(iGrappleTip, "GrappleTip_PullThink");
        set_pev(iGrappleTip, pev_nextthink, get_gametime() + 0.1);
        
        emit_sound(iOwner, CHAN_ITEM, SOUND_IMPACT, 0.9, ATTN_NORM, 0, PITCH_NORM);
    }
    
    set_pev(iGrappleTip, pev_solid, SOLID_NOT);
    set_pev(iGrappleTip, pev_velocity, Float: {0.0, 0.0, 0.0});
    
    wpnmod_set_offset_int(iGrappleTip, Offset_iPull, iHit);
    wpnmod_set_offset_int(iGrappleTip, Offset_iTarget, iOther);
}

//**********************************************
//* Make damage to victim.                     *
//**********************************************

public Grapple_Stab(const iItem, const iPlayer)
{
    new Float: flDmgTime;
    new Float: flGameTime = get_gametime();
    
    pev(iItem, pev_dmgtime, flDmgTime);
    
    if (flDmgTime > flGameTime)
    {
        return;
    }
    
    set_pev(iItem, pev_dmgtime, flGameTime + 0.5);
    
    #define Instance(%0) ((%0 == -1) ? 0 : %0)
    
    new iTrace;
    new iTarget;
    new iEntity;
    new iGrappleTip;
    
    new Float: vecSrc[3];
    new Float: vecEnd[3];
    new Float: vecAngle[3];
    new Float: vecForward[3];
    new Float: flFraction;
    
    iTrace = create_tr2();
    iGrappleTip = wpnmod_get_offset_int(iItem, Offset_iTip);
    iTarget = wpnmod_get_offset_int(iGrappleTip, Offset_iTarget);
    
    pev(iPlayer, pev_origin, vecSrc);
    pev(iPlayer, pev_v_angle, vecAngle);
    
    engfunc(EngFunc_MakeVectors, vecAngle);   
    global_get(glb_v_forward, vecForward);
    
    xs_vec_mul_scalar(vecForward, 32.0, vecForward);
    xs_vec_add(vecForward, vecSrc, vecEnd);

    engfunc(EngFunc_TraceLine, vecSrc, vecEnd, DONT_IGNORE_MONSTERS, iPlayer, iTrace);
    get_tr2(iTrace, TR_flFraction, flFraction);
    
    if (flFraction >= 1.0)
    {
        engfunc(EngFunc_TraceHull, vecSrc, vecEnd, DONT_IGNORE_MONSTERS, HULL_HEAD, iPlayer, iTrace);
        get_tr2(iTrace, TR_flFraction, flFraction);
        
        if (flFraction < 1.0)
        {
            new iHit = Instance(get_tr2(iTrace, TR_pHit));
            
            if (!iHit || ExecuteHamB(Ham_IsBSPModel, iHit))
            {
                FindHullIntersection(vecSrc, iTrace, Float: {-16.0, -16.0, -18.0}, Float: {16.0,  16.0,  18.0}, iPlayer);
            }
            
            get_tr2(iTrace, TR_vecEndPos, vecEnd);
        }
    }
    
    get_tr2(iTrace, TR_flFraction, flFraction);
    
    if (flFraction < 1.0)
    {
        iEntity = Instance(get_tr2(iTrace, TR_pHit));
        
        if (iEntity && ExecuteHamB(Ham_Classify, iEntity) != CLASS_NONE && iEntity == iTarget)
        {
            wpnmod_clear_multi_damage();
            
            pev(iPlayer, pev_v_angle, vecAngle);
            engfunc(EngFunc_MakeVectors, vecAngle);   
            
            global_get(glb_v_forward, vecForward);
            ExecuteHamB(Ham_TraceAttack, iEntity, iPlayer, 50.0, vecForward, iTrace, DMG_SLASH | DMG_ALWAYSGIB);
            
            wpnmod_apply_multi_damage(iPlayer, iPlayer);
                
            switch (random_num(0, 1))
            {
                case 0: emit_sound(iPlayer, CHAN_ITEM, SOUND_CHEW_1, 1.0, ATTN_NORM, 0, PITCH_NORM);
                case 1: emit_sound(iPlayer, CHAN_ITEM, SOUND_CHEW_2, 1.0, ATTN_NORM, 0, PITCH_NORM);
                case 2: emit_sound(iPlayer, CHAN_ITEM, SOUND_CHEW_3, 1.0, ATTN_NORM, 0, PITCH_NORM);
            }
        }
    }

    free_tr2(iTrace);
}

//**********************************************
//* Some usefull stocks.                       *
//**********************************************

stock FindHullIntersection(const Float: vecSrc[3], &iTrace, const Float: vecMins[3], const Float: vecMaxs[3], const iEntity)
{
    new i, j, k;
    new iTempTrace;
    
    new Float: vecEnd[3];
    new Float: vecEndPos[3];
    new Float: vecHullEnd[3];
    new Float: vecMinMaxs[2][3];
    
    new Float: flDistance;
    new Float: flFraction;
    new Float: flThisDistance;
    
    flDistance = 999999.0;
    
    xs_vec_copy(vecMins, vecMinMaxs[0]);
    xs_vec_copy(vecMaxs, vecMinMaxs[1]);
    
    get_tr2(iTrace, TR_vecEndPos, vecHullEnd);
    
    xs_vec_sub(vecHullEnd, vecSrc, vecHullEnd);
    xs_vec_mul_scalar(vecHullEnd, 2.0, vecHullEnd);
    xs_vec_add(vecHullEnd, vecSrc, vecHullEnd);
    
    engfunc(EngFunc_TraceLine, vecSrc, vecHullEnd, DONT_IGNORE_MONSTERS, iEntity, (iTempTrace = create_tr2()));
    get_tr2(iTempTrace, TR_flFraction, flFraction);
    
    if (flFraction < 1.0)
    {
        free_tr2(iTrace);
        
        iTrace = iTempTrace;
        return;
    }
    
    for (i = 0; i < 2; i++)
    {
        for (j = 0; j < 2; j++)
        {
            for (k = 0; k < 2; k++)
            {
                vecEnd[0] = vecHullEnd[0] + vecMinMaxs[i][0];
                vecEnd[1] = vecHullEnd[1] + vecMinMaxs[j][1];
                vecEnd[2] = vecHullEnd[2] + vecMinMaxs[k][2];
                
                engfunc(EngFunc_TraceLine, vecSrc, vecEnd, DONT_IGNORE_MONSTERS, iEntity, iTempTrace);
                get_tr2(iTempTrace, TR_flFraction, flFraction);
                
                if (flFraction < 1.0)
                {
                    get_tr2(iTempTrace, TR_vecEndPos, vecEndPos);
                    xs_vec_sub(vecEndPos, vecSrc, vecEndPos);
                    
                    if ((flThisDistance = xs_vec_len(vecEndPos)) < flDistance)
                    {
                        free_tr2(iTrace);
                        
                        iTrace = iTempTrace;
                        flDistance = flThisDistance;
                    }
                }
            }
        }
    }
}
Назад
Верх