[English]

NEWS
INTRODUCTION
TERMINOLOGIE
LE CODE SOURCE
LES BUGS
TUTORIAUX
DOWNLOADS
L'AUTEUR

  LES MODS: AJOUTER UNE COMMANDE POUR CREER DES SENTINELLES
Ecrit par Christoffer "Eldritch" Lundberg

1.
Soyez sûrs d'avoir le code source ouvert dans votre éditeur/compilateur favoris C/C++. Ouvrez le fichier bh_agun.c.

2.
Localisez la fonction void CastSentrygun(void). Si elle n'existe pas, vous devez la créer. Si vous possédez déjà la fonction, vous aurez seulement besoin de la modifer. Ca devrait ressembler à cela:

void CastSentrygun(void)
{
#define BOTRANGE 2000

VECTORCH position;

if (AvP.Network!=I_No_Network)
{
NewOnScreenMessage("NO SENTRYGUNS IN MULTIPLAYER MODE");
return;
}
position=Player->ObStrategyBlock->DynPtr->Position;
position.vx+=MUL_FIXED(Player->ObStrategyBlock->DynPtr->OrientMat.mat31,BOTRANGE);
position.vy+=MUL_FIXED(Player->ObStrategyBlock->DynPtr->OrientMat.mat32,BOTRANGE);
position.vz+=MUL_FIXED(Player->ObStrategyBlock->DynPtr->OrientMat.mat33,BOTRANGE);
CreateSentrygun(&position, 1);
}
3.
Après cela, localisez la fonction void CastSentryGun(VECTORCH *Position,int type). Si elle n'existe pas, vous devez la créer. Si vous possédez déjà la fonction, vous aurez seulement besoin de la modifer. Ca devrait ressembler à cela:
void CreateSentrygun(VECTORCH *Position,int type)
{
STRATEGYBLOCK* sbPtr;
int i;

/* create and initialise a strategy block */
sbPtr = CreateActiveStrategyBlock();
if (!sbPtr)
{
NewOnScreenMessage("FAILED TO CREATE BOT: SB CREATION FAILURE");
return; /* failure */
}
InitialiseSBValues(sbPtr);
sbPtr->I_SBtype = I_BehaviourAutoGun;
AssignNewSBName(sbPtr);

/* create, initialise and attach a dynamics block */
sbPtr->DynPtr = AllocateDynamicsBlock(DYNAMICS_TEMPLATE_SPRITE_NPC);
if (sbPtr->DynPtr)
{
// Obtient le bloc dynamique attaché au joueur & et la coordonnée Y du joueur:
DYNAMICSBLOCK *PlayerDyn = Player->ObStrategyBlock->DynPtr;
EULER GunEuler = {0, PlayerDyn->OrientEuler.EulerY, 0};

DYNAMICSBLOCK *dynPtr = sbPtr->DynPtr;
GLOBALASSERT(dynPtr);

// Vérifications de sûreté...
if (Player==NULL) return;
if (Player->ObStrategyBlock==NULL) return;


dynPtr->PrevPosition = dynPtr->Position = *Position;
dynPtr->OrientEuler = GunEuler; // Oriente la Sentinelle en face du joueur
CreateEulerMatrix(&dynPtr->OrientEuler, &dynPtr->OrientMat);
TransposeMatrixCH(&dynPtr->OrientMat);
dynPtr->UseDisplacement=0;

dynPtr->Mass=10000; /* As opposed to 160. */
}
else
{
/* dynamics block allocation failed... */
RemoveBehaviourStrategy(sbPtr);
NewOnScreenMessage("FAILED TO CREATE GUN: DYNBLOCK CREATION FAILURE");
return;
}
sbPtr->shapeIndex = 0;
sbPtr->maintainVisibility = 1;
sbPtr->containingModule = ModuleFromPosition(&(sbPtr->DynPtr->Position), (MODULE*)0);

/* create, initialise and attach an alien data block */
sbPtr->SBdataptr = (void *)AllocateMem(sizeof(AUTOGUN_STATUS_BLOCK));
if (sbPtr->SBdataptr)
{
SECTION *root_section;
AUTOGUN_STATUS_BLOCK *agunStatus = (AUTOGUN_STATUS_BLOCK *)sbPtr->SBdataptr;

/* Initialise les stats de la sentinelle*/
{
NPC_DATA *NpcData;
NpcData=GetThisNpcData(I_NPC_SentryGun);
LOCALASSERT(NpcData);
sbPtr->SBDamageBlock.Health=NpcData->StartingStats.Health< sbPtr->SBDamageBlock.Armour=NpcData->StartingStats.Armour< sbPtr->SBDamageBlock.SB_H_flags=NpcData->StartingStats.SB_H_flags;
}
agunStatus->behaviourState=I_inactive; // Rend la Sentinelle inactive jusqu'à utilisation
agunStatus->Target=NULL;
COPY_NAME(agunStatus->Target_SBname,Null_Name);
agunStatus->targetTrackPos.vx=0;
agunStatus->targetTrackPos.vy=0;
agunStatus->targetTrackPos.vz=0;

agunStatus->stateTimer=0;
agunStatus->Gun_Pan=0;
agunStatus->Gun_Tilt=0;
agunStatus->gunpandir=0;
agunStatus->guntiltdir=0;

agunStatus->IAmFar=1;
agunStatus->Firing=0;
agunStatus->Drama=0;
agunStatus->OnTarget=0;
agunStatus->OnTarget_LastFrame=0;
agunStatus->WhirrSoundOn=0;
agunStatus->GunFlash=NULL;
agunStatus->soundHandle=SOUND_NOACTIVEINDEX;
agunStatus->soundHandle2=SOUND_NOACTIVEINDEX;
agunStatus->ammo=500;
agunStatus->roundsFired=0;
agunStatus->volleyFired=0;
agunStatus->incidentFlag=0;
agunStatus->incidentTimer=0;

agunStatus->HModelController.section_data=NULL;
agunStatus->HModelController.Deltas=NULL;
for(i=0;ideath_target_ID[i] =0;
agunStatus->death_target_sbptr=0;
agunStatus->death_target_request=0;

root_section=GetNamedHierarchyFromLibrary("sentry","gun");

if (!root_section)
{
RemoveBehaviourStrategy(sbPtr);
NewOnScreenMessage("FAILED TO CREATE GUN: NO HMODEL");
return;
}
Create_HModel(&agunStatus->HModelController,root_section);
InitHModelSequence(&agunStatus->HModelController,HMSQT_Xenoborg,XBSS_Powered_Up_Standard,ONE_FIXED);

{
DELTA_CONTROLLER *delta;

delta=Add_Delta_Sequence(&agunStatus->HModelController,"GunTilt",(int)HMSQT_Xenoborg,(int)XBSS_Head_Vertical_Delta,0);
GLOBALASSERT(delta);
delta->timer=32767;
delta->Active=0;

delta=Add_Delta_Sequence(&agunStatus->HModelController,"GunPan",(int)HMSQT_Xenoborg,(int)XBSS_Head_Horizontal_Delta,0);
GLOBALASSERT(delta);
delta->timer=32767;
delta->Active=0;
}

/* Containment test NOW! */
if(!(sbPtr->containingModule))
{
/* no containing module can be found... abort*/
RemoveBehaviourStrategy(sbPtr);
NewOnScreenMessage("FAILED TO CREATE GUN: MODULE CONTAINMENT FAILURE");
return;
}
LOCALASSERT(sbPtr->containingModule);

MakeSentrygunNear(sbPtr);

NewOnScreenMessage("SENTRYGUN LOADED");
}
else
{
/* no data block can be allocated */
RemoveBehaviourStrategy(sbPtr);
NewOnScreenMessage("FAILED TO CREATE GUN: MALLOC FAILURE");
return;
}
if(AvP.Network != I_No_Network)
{
AddNetGameObjectID(sbPtr);
}
}
4.
Fermez bh_agun.c et ouvrez le fichier gamecmds.cpp. Localisez l'entrée "XENOBORG". Ajoutez une nouvelle commande console appelée SENTRYGUNBOT en ajoutant les lignes suivantes au fichier après l'entrée XENOBORG:
ConsoleCommand :: Make
(
"SENTRYGUNBOT",
"CREATES A SENTRY GUN…",
CastSentrygun,
IsACheat
);
5.
Puis localisez la ligne extern void CastXenoborg(void); et ajoutez le prototype suivant:
extern void CastSentrygun(void);
6.
Fermez gamecmds.cpp et ouvrez le fichier winmain.cpp. Localisez la ligne ForceLoad_PredAlien = TRUE. Après le bloc entier des "case", ajoutez-en un nouveau (s'il n'existe pas) pour les Sentinelles:
case 's':
ForceLoad_SentryGun = TRUE;
break;

Maintenant qu'avons-nous fait? Nous avons ajouté une nouvelle commande console pour charger les Sentinelles qui sont seulement disponibles si nous lançons le jeu avec le paramètre -debug. La commande est SENTRYGUNBOT. Cela créera une Sentinelle en face du joueur, sur la même direction que ce dernier. Cela, cependant, ne marchera pas en Multiplayer (voir ci-dessous). Nous avons également ajouté un nouveau paramètre pour forcer le chargement des Sentinelles dans notre jeu. Pour l'utiliser, entrez les paramètres suivants pendant le chargement d'avp.exe:

-debug -ls

Pourquoi la Sentinelle ne va-t-elle pas marcher en Multiplayer donc? Eh bien, les raisons sont multiples et trop abondantes pour un programmeur amateur comme moi-même pour trouver la réponse. Lorsque vous essayez ceci, le système entier crash pour tous les autres joueurs excepté celui qui a chargé la Sentinelle. Si quelqu'un trouvait la raison de cela, ce serait chaleureusement bienvenue.

J'espère que vous avez apprécié ce petit tutorial.

Chris