mardi 28 avril 2009

[TUTO]Mettre les mains du joueur comme arme

Je vais donc vous expliquez comment ajouter une nouvelle arme qui s'agit enfaites des mains du joueur, vous pourrez ensuite donné des coups de poings avec ceux là.
Pour commencer je vais vous expliquez quel logiciel est a utiliser.

Ce code a été réalisé pour la Orange Box.


Les logiciels requis sont :

Visual Studio C++ 2008 Express Édition (La version Express Édition est amplement suffisante, elle est en français d'ailleurs)
Notepad++ (Notepad++ est un outil sympa pour l'édition rapide de vos fichiers .cpp et .h)

Réglages :

Maintenant passons au réglage, après avoir mis Visual Studio C++ 2008 Express Édition il faut le régler !
Et oui c'est pas si facile...

Donc ouvrez Visual Studio c++ 2008 Express Édition, ouvrez votre projet game_episodic-2005
En haut à droite se trouve une barre avec 'Debug' 'WIN32', (image ci-dessous), maintenant un clic gauche sur 'Debug' ou 'WIN32' (c'est la même chose), 'Gestionnaire de configurations'.



Faites le nécessaire pour que l'image que j'ai mis en dessous soit la même que dans votre tableau.

C'est à dire :

Configuration de la solution active : Release // Plateforme de la solution active : Win32

client_episodic-2005 // Release // Win32 // une case est ici, elle faut qu'elle soit remplit
server_episodic-2005 // Release // Win32 // une case est ici, elle faut qu'elle soit remplit




Une fois terminé, nous pouvons maintenant fixé un problème du code qui est d'ailleurs très connu.
Le problème est connu pour ne pas compilé les .dll, mais il existe une solution et là voici :

A la ligne 348 du fichier client/c_vguiscreen.cpp, vous devriez avoir ceci :

dist = c_x / tan( M_PI * scaled_fov / 360.0 );


Pour ensuite le remplacé par ceci :

float dist_denom = tan( M_PI * scaled_fov / 360.0f );
dist = c_x / dist_denom;




Sauvegardez ensuite.

Modification des fichiers de votre mod :

Cfg

Maintenant que tout est opérationnelle on passe aux choses sérieuses.
Ouvrez le fichier skill.cfg qui se trouve dans le dossier cfg de votre mod, si il n'est pas crée prenez celui de Half-Life 2 et copiez le dedans pour ensuite l'ouvrir et faire les modifications qui vont suivre.

Une fois dedans, cherchez ceci :

// =================
// WEAPONS
// =================



Ici il vous faudra ajouter ceci :

sk_plr_dmg_hand "5"
sk_npc_dmg_hand "5"



Cela vous donnera a peu près une chose comme ça dans votre fichier skill.cfg :

// =================
// WEAPONS
// =================

sk_plr_dmg_hand "5"
sk_npc_dmg_hand "5"


Sauvegardez.

Ressource

Ouvrez le fichier nom_de_votre_mod_french.txt qui se trouve dans le dossier ressource de votre mod, si il n'est pas crée prenez celui de Half-Life 2 et copiez le dedans pour ensuite l'ouvrir et faire les modifications qui vont suivre.

Une fois dedans, cherchez ceci :

"HL2_GravityGun" "PISTOLET ENERGETIQUE"
"HL2_Crowbar" "PIED DE BICHE"


Ajoutez donc :

"HL2_HAND" "MAIN"


Au bon endroit, qu'il soit placé en bout ou au début devant le gravity gun il n'y a aucune importance.

Sauvegardez.

Script

Dans cette partie, vous devez créer un nouveau fichier texte (.txt), assignez lui comme nom weapon_hand.txt
Ensuite, ouvrez le et copiez ceci :

// Hand

WeaponData
{
// Weapon data is loaded by both the Game and Client DLLs.
"printname" "#HL2_Hand"
"viewmodel" "models/weapons/v_hand.mdl"
//"playermodel" "models/weapons/w_crowbar.mdl"
"anim_prefix" "crowbar"
"bucket" "0"
"bucket_position" "1"

"clip_size" "-1"
"primary_ammo" "None"
"secondary_ammo" "None"

"weight" "0"
"item_flags" "0"

// Sounds for the weapon. There is a max of 16 sounds per category (i.e. max 16 "single_shot" sounds)
SoundData
{
"single_shot" "Weapon_Crowbar.Single"
"melee_hit" "Weapon_Crowbar.Melee_Hit"
"melee_hit_world" "Weapon_Crowbar.Melee_HitWorld"
}

// Weapon Sprite data is loaded by the Client DLL.
TextureData
{

"crosshair"
{
"font" "Crosshairs"
"character" "Q"
}
"autoaim"
{
"file" "sprites/crosshairs"
"x" "0"
"y" "48"
"width" "24"
"height" "24"
}
}
}


Sauvegardez.

Models

Coté models, sans ce que je vais vous donner vous allez ne pouvoir rien faire vu que les mains de Half-Life 2 n'ont pas d'animations de coups de poings.
Donc téléchargez les nouveaux models à cette adresse

Une fois téléchargé, il suffit simplement de mettre les models dans models/weapons

Partie Coding de votre Mod :

c_weapon_stubs_hl2.cpp

Ouvrez dans Visual Studio C++ 2008 Express Édition le fichier c_weapon_stubs_hl2.cpp qui se trouve dans Client\Source Files\HL2 DLL de votre fichier client_episodic-2005 du projet game_episodic-2005

Une fois ouvert, repérez la ligne STUB_WEAPON_CLASS( weapon_crowbar, WeaponCrowbar, C_BaseHLBludgeonWeapon ); pour ensuite ajouter dessous cette ligne :

STUB_WEAPON_CLASS( weapon_hand, WeaponHand, C_BaseHLBludgeonWeapon );


Ce qui vous donnera ce résultat :



Player.cpp

Ouvrez dans Visual Studio C++ 2008 Express Édition le fichier player.cpp qui se trouve dans Server\Source Files\HL2 DLL de votre fichier server_episodic-2005 du projet game_episodic-2005

Une fois ouvert, repérez la ligne case 101, du moins effectuez une recherche avec ctrl + f pour ensuite ajouter dessous cette ligne :

GiveNamedItem( "weapon_hand" );


Ce qui donne ce résultat une fois la ligne ajouté :



Sauvegardez ensuite.

Weapon_hand.h

Cliquez sur le clic droit sur server_episodic-2005, ensuite cliquez sur l'onglet ajouté qui à apparu, Nouvel élément...



Ensuite vous avez un tableau, (l'image le représente ci-dessous) cliquez une fois sur Fichier d'en-tête (.h), pour que après dans Nom : vous écrivez weapon_hand pour ensuite cliquez sur ajouter



Maintenant, ouvrez votre fichier weapon_hand.h dans Visual Studio C++ 2008 Express Édition
Vous remarquez que c'est vide, pour cela j'ai un remède.

Il suffit d'ajouter ceci :

//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//

#ifndef WEAPON_HAND_H
#define WEAPON_HAND_H

#include "basebludgeonweapon.h"

#if defined( _WIN32 )
#pragma once
#endif

#ifdef HL2MP
#error weapon_hand.h must not be included in hl2mp. The windows compiler will use the wrong class elsewhere if it is.
#endif

#define HAND_RANGE 75.0f
#define HAND_REFIRE 0.4f

//-----------------------------------------------------------------------------
// CWeaponHand
//-----------------------------------------------------------------------------

class CWeaponHand : public CBaseHLBludgeonWeapon
{
public:
DECLARE_CLASS( CWeaponHand, CBaseHLBludgeonWeapon );

DECLARE_SERVERCLASS();
DECLARE_ACTTABLE();

CWeaponHand();

float GetRange( void ) { return HAND_RANGE; }
float GetFireRate( void ) { return HAND_REFIRE; }

void AddViewKick( void );
float GetDamageForActivity( Activity hitActivity );

virtual int WeaponMeleeAttack1Condition( float flDot, float flDist );
void SecondaryAttack( void ) { return; }

// Animation event
virtual void Operator_HandleAnimEvent( animevent_t *pEvent, CBaseCombatCharacter *pOperator );

private:
// Animation event handlers
void HandleAnimEventMeleeHit( animevent_t *pEvent, CBaseCombatCharacter *pOperator );
};

#endif // WEAPON_HAND_H


Sauvegardez ensuite.

Weapon_hand.cpp

Cliquez sur le clic droit sur server_episodic-2005, ensuite cliquez sur l'onglet ajouté qui à apparu, Nouvel élément...
Ensuite vous avez un tableau, cliquez une fois sur Fichier C++ (.cpp), pour que après dans Nom : vous écrivez weapon_hand pour ensuite cliquez sur ajouter
Maintenant, ouvrez votre fichier weapon_hand.cpp dans Visual Studio C++ 2008 Express Édition

Et mettez y ceci :

//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose: Hand
//
// $NoKeywords: $
//=============================================================================//

#include "cbase.h"
#include "basehlcombatweapon.h"
#include "player.h"
#include "gamerules.h"
#include "ammodef.h"
#include "mathlib/mathlib.h"
#include "in_buttons.h"
#include "soundent.h"
#include "basebludgeonweapon.h"
#include "vstdlib/random.h"
#include "npcevent.h"
#include "ai_basenpc.h"
#include "weapon_hand.h"

// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"

ConVar sk_plr_dmg_hand ( "sk_plr_dmg_hand","0");
ConVar sk_npc_dmg_hand ( "sk_npc_dmg_hand","0");

//-----------------------------------------------------------------------------
// CWeaponHand
//-----------------------------------------------------------------------------

IMPLEMENT_SERVERCLASS_ST(CWeaponHand, DT_WeaponHand)
END_SEND_TABLE()

#ifndef HL2MP
LINK_ENTITY_TO_CLASS( weapon_hand, CWeaponHand );
PRECACHE_WEAPON_REGISTER( weapon_hand );
#endif

acttable_t CWeaponHand::m_acttable[] =
{
{ ACT_MELEE_ATTACK1, ACT_MELEE_ATTACK_SWING, true },
{ ACT_IDLE, ACT_IDLE_ANGRY_MELEE, false },
{ ACT_IDLE_ANGRY, ACT_IDLE_ANGRY_MELEE, false },
};

IMPLEMENT_ACTTABLE(CWeaponHand);

//-----------------------------------------------------------------------------
// Constructor
//-----------------------------------------------------------------------------
CWeaponHand::CWeaponHand( void )
{
}

//-----------------------------------------------------------------------------
// Purpose: Get the damage amount for the animation we're doing
// Input : hitActivity - currently played activity
// Output : Damage amount
//-----------------------------------------------------------------------------
float CWeaponHand::GetDamageForActivity( Activity hitActivity )
{
if ( ( GetOwner() != NULL ) && ( GetOwner()->IsPlayer() ) )
return sk_plr_dmg_hand.GetFloat();

return sk_npc_dmg_hand.GetFloat();
}

//-----------------------------------------------------------------------------
// Purpose: Add in a view kick for this weapon
//-----------------------------------------------------------------------------
void CWeaponHand::AddViewKick( void )
{
CBasePlayer *pPlayer = ToBasePlayer( GetOwner() );

if ( pPlayer == NULL )
return;

QAngle punchAng;

punchAng.x = random->RandomFloat( 1.0f, 2.0f );
punchAng.y = random->RandomFloat( -2.0f, -1.0f );
punchAng.z = 0.0f;

pPlayer->ViewPunch( punchAng );
}


//-----------------------------------------------------------------------------
// Attempt to lead the target (needed because citizens can't hit manhacks with the hand!)
//-----------------------------------------------------------------------------
ConVar sk_hand_lead_time( "sk_hand_lead_time", "0.9" );

int CWeaponHand::WeaponMeleeAttack1Condition( float flDot, float flDist )
{
// Attempt to lead the target (needed because citizens can't hit manhacks with the hand!)
CAI_BaseNPC *pNPC = GetOwner()->MyNPCPointer();
CBaseEntity *pEnemy = pNPC->GetEnemy();
if (!pEnemy)
return COND_NONE;

Vector vecVelocity;
vecVelocity = pEnemy->GetSmoothedVelocity( );

// Project where the enemy will be in a little while
float dt = sk_hand_lead_time.GetFloat();
dt += random->RandomFloat( -0.3f, 0.2f );
if ( dt < dt =" 0.0f;">WorldSpaceCenter(), dt, vecVelocity, vecExtrapolatedPos );

Vector vecDelta;
VectorSubtract( vecExtrapolatedPos, pNPC->WorldSpaceCenter(), vecDelta );

if ( fabs( vecDelta.z ) > 70 )
{
return COND_TOO_FAR_TO_ATTACK;
}

Vector vecForward = pNPC->BodyDirection2D( );
vecDelta.z = 0.0f;
float flExtrapolatedDist = Vector2DNormalize( vecDelta.AsVector2D() );
if ((flDist > 64) && (flExtrapolatedDist > 64))
{
return COND_TOO_FAR_TO_ATTACK;
}

float flExtrapolatedDot = DotProduct2D( vecDelta.AsVector2D(), vecForward.AsVector2D() );
if ((flDot < penemy =" pOperator-">MyNPCPointer() ? pOperator->MyNPCPointer()->GetEnemy() : NULL;
if ( pEnemy )
{
Vector vecDelta;
VectorSubtract( pEnemy->WorldSpaceCenter(), pOperator->Weapon_ShootPosition(), vecDelta );
VectorNormalize( vecDelta );

Vector2D vecDelta2D = vecDelta.AsVector2D();
Vector2DNormalize( vecDelta2D );
if ( DotProduct2D( vecDelta2D, vecDirection.AsVector2D() ) > 0.8f )
{
vecDirection = vecDelta;
}
}

Vector vecEnd;
VectorMA( pOperator->Weapon_ShootPosition(), 50, vecDirection, vecEnd );
CBaseEntity *pHurt = pOperator->CheckTraceHullAttack( pOperator->Weapon_ShootPosition(), vecEnd,
Vector(-16,-16,-16), Vector(36,36,36), sk_npc_dmg_hand.GetFloat(), DMG_CLUB, 0.75 );

// did I hit someone?
if ( pHurt )
{
// play sound
WeaponSound( MELEE_HIT );

// Fake a trace impact, so the effects work out like a player's crowbaw
trace_t traceHit;
UTIL_TraceLine( pOperator->Weapon_ShootPosition(), pHurt->GetAbsOrigin(), MASK_SHOT_HULL, pOperator, COLLISION_GROUP_NONE, &traceHit );
ImpactEffect( traceHit );
}
else
{
WeaponSound( MELEE_MISS );
}
}


//-----------------------------------------------------------------------------
// Animation event
//-----------------------------------------------------------------------------
void CWeaponHand::Operator_HandleAnimEvent( animevent_t *pEvent, CBaseCombatCharacter *pOperator )
{
switch( pEvent->event )
{
case EVENT_WEAPON_MELEE_HIT:
HandleAnimEventMeleeHit( pEvent, pOperator );
break;

default:
BaseClass::Operator_HandleAnimEvent( pEvent, pOperator );
break;
}
}
Sauvegardez ensuite.

Compilation :

On y est presque, c'est presque terminé.
Pour cela il vous reste la compilation du code tout entier.

Maintenez un clique droit sur client_episodic-2005 // Générer
Maintenez un clique droit sur server_episodic-2005 // Générer

Le fichier client.dll se trouvera donc dans src\game\client\bin
Le fichier server.dll se trouvera donc dans src\game\server\bin

Dans le jeu :



Posez vos questions et déposez vos problèmes ou bien contactez moi directement si vous le souhaitez.

Dernière édition : 2011

5 commentaires:

panzer a dit…

Waaa pas mal, j'essayerai, sa doit bien changer du pied de biche,sa donne un genre c pas mal du tout.

Est pour quand les coup de téte mdr.

A +

Eaglesg a dit…

Woa, sympa, je pense qu'il va me servir...^^

Veilleur a dit…

Propose ton tuto sur Mapping-area.

freredarme a dit…

Déjà fait :)

Matthieu a dit…

Ouaaaaa merci :D

Une erreur est survenue dans ce gadget