Четверг, 28.03.2024, 11:50

logo

Пользовательский поиск

Меню сайта
Категории раздела
Разное [15]
Tutorials
Создание карт [13]
Создание моделей [2]
Кодинг [14]
Создание карт CS [197]
Учебник cs-mapper
Свойства entity HL-CS [117]
Форма входа
Логин:
Пароль:
Наш сервер CS 1.6
Поиск
Наш опрос
Оцените мой сайт
Всего ответов: 167
Друзья сайта


Главная » Статьи » HL Development » Кодинг


Делаем Displacer а-ля Opposing Force

Делаем Displacer а-ля Opposing Force

Beta 0.8
Делаем Displacer а-ля Opposing Force
Ну чтоже, соскучились вы по нашим туторам ? Если да то для вас приятная новость - сейчас туторы будут добавляться на сайт, поэтому следите ;)

Итак, я уверен 99.9% всех халферов ирали в Opposing Force и пользовались оружием-телепортером. С каждым годом все больше и больше увеличиваеться количество людей, желающих создать свой супер пупер мод под Халфу и довольно многие хотят видеть в своем моде это оружие. Однако жадные Gearbox не спешат поделиться кодом этого орудия( ровно как и всего остального добавочного оружия, монтсров и эффектов из OF) то модерам приходиться огорчаться и перекраивать свои планы...

Так было раньше, пока не был создан данный тутор с полным кодом данного орудия, так что со всех тех кто это читает причитается :Р Вообщем перед вами и есть тот самый дисплейсер со всеми функциями и поностью рабочий, поэтому если у вас что то не работает то проблема уже в вас :)

Опытным програмерам вставить недостающие строки не составит никакого труда. новичкам придется немного помучиться, но оно и к лучшему - научаться не только нажимать ctrl+c -> ctrl+v но и немного думать и причем головой, и что самое главное - своей ;)

Итак - добавляем дефайн в weapons.h
Добавляем файл displacer.cpp в проект
Добавляем строчку прекеша в weapons.cpp
Регаем эвент как на клиенте, так и на сервере (хотя кажись нужно тока на клиенте - не помню) - если не помните(или не знаете) как это делать смотрите тутор по созданию нового оружия.

Вот код эвента (спаисбо xwiderу за функцию доступа к аттачментам)

void EV_SpinDisplacer(event_args_t *args)//Original code idea by Xwider
{
if (EV_IsLocal(args->entindex))
{
gEngfuncs.pEventAPI->EV_WeaponAnimation(DISPLACER_SPINUP, 2);
cl_entity_t *view = gEngfuncs.GetViewModel();
if (view != NULL)
{
float life = 1.14;

gEngfuncs.pEfxAPI->R_BeamEnts(view->index | 0x1000, view->index | 0x2000, args->iparam2, life, 0.8, 0.5, 0.5, 0.6, 0, 10, 2, 10, 0);
gEngfuncs.pEfxAPI->R_BeamEnts(view->index | 0x1000, view->index | 0x3000, args->iparam2, life, 0.8, 0.5, 0.5, 0.6, 0, 10, 2, 10, 0);
gEngfuncs.pEfxAPI->R_BeamEnts(view->index | 0x1000, view->index | 0x4000, args->iparam2, life, 0.8, 0.5, 0.5, 0.6, 0, 10, 2, 10, 0);
        }
    }

    if (args->bparam2 == 0)// sound mode
gEngfuncs.pEventAPI->EV_PlaySound(args->entindex, args->origin, CHAN_WEAPON, "weapons/displacer_spin.wav", 1.0, ATTN_NORM, 0, PITCH_NORM);
    else
gEngfuncs.pEventAPI->EV_PlaySound(args->entindex, args->origin, CHAN_WEAPON, "weapons/displacer_spin2.wav", 1.0, ATTN_NORM, 0, PITCH_NORM);
 


пихаем его в ev_hldm.cpp и еще вот эту хрень в ev_hldm.h

enum displacer_e
{
    DISPLACER_IDLE1 = 0,
    DISPLACER_IDLE2,
    DISPLACER_SPINUP,
    DISPLACER_SPIN,
    DISPLACER_FIRE,
    DISPLACER_DRAW,
    DISPLACER_HOLSTER,
};
 


называйте эвент как хотите, но на сервере он называется displacer.sc и точка! (ессно можете изменить имя если хоцца)

Bот код displacer.cpp

/***
*
*    Copyright (c) 2004 Shambler Team. All rights reserved.
*   
****/

#include "extdll.h"
#include "util.h"
#include "cbase.h"
#include "monsters.h"
#include "weapons.h"
#include "nodes.h"
#include "player.h"
#include "gamerules.h"
#include "shake.h"
#include "effects.h"

enum displacer_e
{
    DISPLACER_IDLE1 = 0,
    DISPLACER_IDLE2,
    DISPLACER_SPINUP,
    DISPLACER_SPIN,
    DISPLACER_FIRE,
    DISPLACER_DRAW,
    DISPLACER_HOLSTER,
};

class CDisplacer : public CBasePlayerWeapon
{
public:
    int        Save( CSave &save );
    int        Restore( CRestore &restore );
    static    TYPEDESCRIPTION m_SaveData[];

    void Spawn( void );
    void Precache( void );
    int iItemSlot( void ) { return 4; }
    int GetItemInfo(ItemInfo *p);
    int AddToPlayer( CBasePlayer *pPlayer );

    BOOL Deploy( void );
    void Holster( int skiplocal = 0 );

    void PrimaryAttack( void );
    void SecondaryAttack (void);
    void EXPORT SpinUp( void );
    void EXPORT Teleport( void );
    void EXPORT Fire( void );
    void WeaponIdle( void );

    int m_iAttackMode;//    no need save/restore this. g-cont
private:
    unsigned short m_usDisplacer;
    int m_iBeam;
    int m_iPlace;
};

LINK_ENTITY_TO_CLASS( weapon_displacer, CDisplacer );

//===========================
//
//    TeleBall code
//
//===========================

//class CDispBall : public CGrenade
class CDispBall : public CBaseEntity//Special for Ghoul [BB] :devil:
{
public:
    void Spawn( void );
    void Precache( void );
    void Explode( TraceResult *pTrace );
    void RemoveBall (void);
    void EXPORT ExplodeTouch( CBaseEntity *pOther );

    void EXPORT BallThink( void );
    static CDispBall *CreateDispBall( Vector vecOrigin, Vector vecAngles, CBaseEntity *pOwner, CDisplacer *pLauncher );

    int m_iDispRing;
    BOOL LockRing;
};

LINK_ENTITY_TO_CLASS( dispball, CDispBall );

CDispBall *CDispBall::CreateDispBall( Vector vecOrigin, Vector vecAngles, CBaseEntity *pOwner, CDisplacer *pLauncher )
{
    CDispBall *pDispBall = GetClassPtr( (CDispBall *)NULL );

    UTIL_SetOrigin( pDispBall->pev, vecOrigin );
    pDispBall->pev->angles = vecAngles;
    pDispBall->Spawn();
    pDispBall->SetTouch( CDispBall::ExplodeTouch );
    pDispBall->pev->owner = pOwner->edict();

    return pDispBall;
}

void CDispBall :: Spawn( void )
{
    Precache( );
    pev->movetype = MOVETYPE_FLY;
    pev->solid = SOLID_BBOX;

    SET_MODEL(ENT(pev), "sprites/exit1.spr");
    pev->scale = .5;

    UTIL_SetSize(pev, Vector ( 0, 0, 0 ), Vector ( 0, 0, 0 ) );
    UTIL_SetOrigin( pev, pev->origin );
    pev->rendermode = kRenderTransAdd;
    pev->renderamt = 255;

    pev->classname = MAKE_STRING("dispball");

    SetThink( BallThink );
    SetTouch( ExplodeTouch );

    pev->angles.x -= 0;
    UTIL_MakeVectors( pev->angles );
    pev->angles.x = -(pev->angles.x + 0);
    pev->velocity = gpGlobals->v_forward * 500;
    pev->nextthink = 0.5;

    pev->dmg = 1000;
}

void CDispBall :: Precache( void )
{
    PRECACHE_MODEL("sprites/exit1.spr");
    PRECACHE_MODEL ("sprites/plasma.spr");

    PRECACHE_SOUND("weapons/displacer_teleport.wav");
    m_iDispRing = PRECACHE_MODEL ("sprites/displacer_ring.spr");
}

void CDispBall :: BallThink( void )
{
    CBeam *pBeam;
    TraceResult tr;
    Vector vecDest;
    float flDist = 1.0;

    for (int i = 0; i < 10; i++)
    {
        Vector vecDir = Vector( RANDOM_FLOAT( -1.0, 1.0 ), RANDOM_FLOAT( -1.0, 1.0 ),RANDOM_FLOAT( -1.0, 1.0 ) );
        vecDir = vecDir.Normalize();
        TraceResult         tr1;
        UTIL_TraceLine( pev->origin, pev->origin + vecDir * 1024, ignore_monsters, ENT(pev), &tr1 );
        if (flDist > tr1.flFraction)
        {
            tr = tr1;
            flDist = tr.flFraction;
        }
    }

    if ( flDist == 1.0 ) return;

    pBeam = CBeam::BeamCreate("sprites/plasma.spr",200);
    pBeam->PointEntInit( tr.vecEndPos, entindex() );
    pBeam->SetStartPos( tr.vecEndPos );
    pBeam->SetEndEntity( entindex() );
    pBeam->SetColor( 90, 170, 16 );
    pBeam->SetNoise( 65 );
    pBeam->SetBrightness( 255 );
    pBeam->SetWidth( 30 );
    pBeam->SetScrollRate( 35 );
    pBeam->LiveForTime( 1 );

    pev->frame += 1; //animate teleball
    if(pev->frame > 24)
        pev->frame = fmod( pev->frame, 24 );

    pev->nextthink = gpGlobals->time + 0.1;
}

void CDispBall::ExplodeTouch( CBaseEntity *pOther )
{
    TraceResult tr;
    Vector        vecSpot;// trace starts here!

    pev->enemy = pOther->edict();

    vecSpot = pev->origin - pev->velocity.Normalize() * 32;
    UTIL_TraceLine( vecSpot, vecSpot + pev->velocity.Normalize() * 64, dont_ignore_monsters, ENT(pev), &tr );

    Explode( &tr );
}

void CDispBall::Explode( TraceResult *pTrace )
{
    if(!LockRing)//for partially fix strange bug in HL engine (for full fix teleball MUST be moved to client side). g-cont
    {
        MESSAGE_BEGIN( MSG_PVS, SVC_TEMPENTITY, pev->origin );
        WRITE_BYTE( TE_BEAMCYLINDER );
        WRITE_COORD( pev->origin.x);
        WRITE_COORD( pev->origin.y);
        WRITE_COORD( pev->origin.z);
        WRITE_COORD( pev->origin.x);
        WRITE_COORD( pev->origin.y);
        WRITE_COORD( pev->origin.z + 800);
        WRITE_SHORT( m_iDispRing );
        WRITE_BYTE( 0 ); // startframe
        WRITE_BYTE( 10 ); // framerate
        WRITE_BYTE( 3 ); // life
        WRITE_BYTE( 20 );  // width
        WRITE_BYTE( 0 );   // noise
        WRITE_BYTE( 255 );   // r, g, b
        WRITE_BYTE( 255 );   // r, g, b
        WRITE_BYTE( 255 );   // r, g, b
        WRITE_BYTE( 255 ); //brightness
        WRITE_BYTE( 0 );        // speed
        MESSAGE_END();
    }

    LockRing = TRUE;
    pev->velocity = g_vecZero;

    SetThink (RemoveBall);
    pev->nextthink = gpGlobals->time + 0.6;

}

void CDispBall::RemoveBall( void )
{
    EMIT_SOUND(ENT(pev), CHAN_VOICE, "weapons/displacer_teleport.wav", 0.9, ATTN_NORM);
    pev->effects |= EF_NODRAW;

    entvars_t *pevOwner;
    if ( pev->owner )
        pevOwner = VARS( pev->owner );
    else
        pevOwner = NULL;
    pev->owner = NULL;

    UTIL_Remove( this );
    ::RadiusDamage( pev->origin, pev, pevOwner, pev->dmg, 200, CLASS_NONE, DMG_ENERGYBEAM );
}

//===========================
//
//    Displacer code
//
//===========================

void CDisplacer::Spawn( )
{
    Precache( );
    m_iId = WEAPON_DISPLACER;
    SET_MODEL(ENT(pev), "models/w_displacer.mdl");

    m_iDefaultAmmo = 60;
    FallInit();// get ready to fall down.
}

TYPEDESCRIPTION    CDisplacer::m_SaveData[] =
{
    DEFINE_FIELD( CDisplacer, m_iPlace, FIELD_INTEGER ),//Remember last teleportation point. g-cont
};
IMPLEMENT_SAVERESTORE( CDisplacer, CBasePlayerWeapon );

int CDisplacer::AddToPlayer( CBasePlayer *pPlayer )
{
    if ( CBasePlayerWeapon::AddToPlayer( pPlayer ) )
    {
        MESSAGE_BEGIN( MSG_ONE, gmsgWeapPickup, NULL, pPlayer->pev );
        WRITE_BYTE( m_iId );
        MESSAGE_END();
        return TRUE;
    }
    return FALSE;
}

BOOL CDisplacer::Deploy( void )
{
    return DefaultDeploy( "models/v_displacer.mdl", "models/p_displacer.mdl", DISPLACER_DRAW, "gauss" );
}

void CDisplacer::Holster( int skiplocal )
{
    m_pPlayer->m_flNextAttack = UTIL_WeaponTimeBase() + 1.5;
    SendWeaponAnim( DISPLACER_HOLSTER );
}

int CDisplacer::GetItemInfo(ItemInfo *p)
{
    p->pszName = STRING(pev->classname);
    p->pszAmmo1 = "uranium";
    p->iMaxAmmo1 = URANIUM_MAX_CARRY;
    p->pszAmmo2 = NULL;
    p->iMaxAmmo2 = -1;
    p->iMaxClip = WEAPON_NOCLIP;
    p->iSlot = 3;
    p->iPosition = 4;
    p->iId = m_iId = WEAPON_DISPLACER;
    p->iFlags = 0;
    p->iWeight = DISPLACER_WEIGHT;

    return 1;
}

void CDisplacer::Precache( void )
{
    PRECACHE_MODEL("models/w_displacer.mdl");
    PRECACHE_MODEL("models/v_displacer.mdl");
    PRECACHE_MODEL("models/p_displacer.mdl");

    PRECACHE_SOUND("weapons/displacer_fire.wav");
    PRECACHE_SOUND ("buttons/button10.wav");
    PRECACHE_SOUND ("weapons/displacer_self.wav");

    UTIL_PrecacheOther( "dispball" );

    m_iBeam = PRECACHE_MODEL("sprites/plasma.spr");
    m_usDisplacer = PRECACHE_EVENT( 1, "events/displacer.sc" );
}

void CDisplacer::SpinUp ( void )
{
    int flags;
    flags = 0;

    if (!m_iAttackMode) SetThink (CDisplacer::Fire);
    else SetThink (CDisplacer::Teleport);

    //spinup event
    PLAYBACK_EVENT_FULL( flags, m_pPlayer->edict(), m_usDisplacer, 0.0, (float *)&g_vecZero, (float *)&g_vecZero, 0.0, 0.0, 0, m_iBeam, 0, m_iAttackMode);   
   
    pev->nextthink = gpGlobals->time + 1.1;
    m_flTimeWeaponIdle = gpGlobals->time + 1.15;
}

void CDisplacer::PrimaryAttack( void )
{
    if (m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] < 20)//Check for ammo
    {
        EMIT_SOUND( edict(), CHAN_BODY, "buttons/button10.wav", 1, ATTN_NORM );
        m_pPlayer->m_flNextAttack = UTIL_WeaponTimeBase() + 1.0;
        return;
    }

    m_iAttackMode = FALSE; //We set attack mode in first mode

    SetThink (CDisplacer::SpinUp);

    m_flNextPrimaryAttack = gpGlobals->time + 2.0;
    m_flTimeWeaponIdle = gpGlobals->time + 1.5;
    pev->nextthink = gpGlobals->time + 0.1;
}

void CDisplacer::SecondaryAttack ( void )
{
    if (m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] < 60)
    {
        EMIT_SOUND( edict(), CHAN_BODY, "buttons/button10.wav", 1, ATTN_NORM );
        m_pPlayer->m_flNextAttack = UTIL_WeaponTimeBase() + 1.0;
        return;
    }

    if (m_iAttackMode) return;
    m_iAttackMode = TRUE; //We set attack mode in second mode

    SetThink (CDisplacer::SpinUp);

    m_flNextSecondaryAttack = gpGlobals->time + 2.0;
    m_flTimeWeaponIdle = gpGlobals->time + 1.5;
    pev->nextthink = gpGlobals->time + 0.1;
}

void CDisplacer::Fire (void)
{
    SendWeaponAnim( DISPLACER_FIRE );
    m_pPlayer->SetAnimation( PLAYER_ATTACK1 );

    Vector vecSrc = m_pPlayer->GetGunPosition( ) + gpGlobals->v_forward * 16 + gpGlobals->v_right * 2 + gpGlobals->v_up * -5;
    m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] -= 20;

    EMIT_SOUND(ENT(m_pPlayer->pev), CHAN_WEAPON, "weapons/displacer_fire.wav", 0.9, ATTN_NORM );
    CDispBall *pDispBall = CDispBall::CreateDispBall( vecSrc, m_pPlayer->pev->v_angle, m_pPlayer, this );
}


void CDisplacer:: Teleport ( void )
{   
    m_iPlace = !m_iPlace;

    CBaseEntity *pSpot = NULL;
    m_iAttackMode = FALSE;//reset firemode

    if ( m_iPlace )    //Xen and earth target
        pSpot = UTIL_FindEntityByClassname( pSpot, "info_xen" );
    else
        pSpot = UTIL_FindEntityByClassname( pSpot, "info_earth" );

    if (pSpot)
    {
        UTIL_ScreenFade( m_pPlayer, Vector(0, 200, 0), 0.5, 0.5, 255, FFADE_IN );

        m_pPlayer->m_rgAmmo[m_iPrimaryAmmoType] -= 60;
        Vector tmp = pSpot->pev->origin;
        tmp.z -= m_pPlayer->pev->mins.z;
        tmp.z++;
        UTIL_SetOrigin( m_pPlayer->pev, tmp );

        m_pPlayer->pev->angles = pSpot->pev->angles;
        m_pPlayer->pev->velocity = m_pPlayer->pev->basevelocity = g_vecZero;

        EMIT_SOUND( edict(), CHAN_BODY, "weapons/displacer_self.wav", 1, ATTN_NORM );
        SendWeaponAnim( DISPLACER_FIRE );
    }
    else
    {
        SendWeaponAnim( DISPLACER_SPINUP );
        EMIT_SOUND( edict(), CHAN_BODY, "buttons/button10.wav", 1, ATTN_NORM );   
        m_pPlayer->m_flNextAttack = UTIL_WeaponTimeBase() + 0.3;
    }

     m_flNextSecondaryAttack = gpGlobals->time + 2.0;
    m_flTimeWeaponIdle = gpGlobals->time + 1.0;
}

void CDisplacer::WeaponIdle( void )
{
    int iAnim;

    m_pPlayer->GetAutoaimVector( AUTOAIM_5DEGREES );

    if ( m_flTimeWeaponIdle > gpGlobals->time )
        return;

    float flRand = RANDOM_FLOAT(0,1);

    if ( flRand <= 0.5 )
    {
        iAnim = DISPLACER_IDLE1;
        m_flTimeWeaponIdle = gpGlobals->time + RANDOM_FLOAT(10,15);
    }
    else
    {
        iAnim = DISPLACER_IDLE2;
        m_flTimeWeaponIdle = gpGlobals->time + 3;
    }

    SendWeaponAnim( iAnim );
}
 


K вящей радости любителей телепортнуться можно еще добавить две строчки в triggers.cpp дабы халфа не ругалась матом, а вела себя тихо и примерно:

LINK_ENTITY_TO_CLASS( info_xen,   CPointEntity );//Two points teleporartion
LINK_ENTITY_TO_CLASS( info_earth, CPointEntity );
 


Xотя какая нафиг разница куда вы впишете эти две строчки ?
Да хоть в h_export.cpp, но тока чур в самый конец, если вам от этого легче.

Внимание! жалобы, типа "у меня не работает" не принимаються

Hа этом все, спасибо за внимание :)

g-cont 
Категория: Кодинг | Добавил: SuperStart (18.10.2010)
Просмотров: 2279 | Рейтинг: 0.0/0 |



Всего комментариев: 0
Добавлять комментарии могут только зарегистрированные пользователи.
[ Регистрация | Вход ]

Copyright www.akksimo.net © 2024