SommairemapstutorielsforumtétéchargementsdiversLes liensLivre d'Or
Les joueurs d'échecs



(Animation du jeu COD adaptée pour CODUO)

Tutorial de Tropheus avec l'aide de Bushman.

Dans ce tutorial vous allez apprendre à insérer dans vos cartes solos l'animation de la carte Pathfinder où les soldats allemands jouent aux échecs.
La méthode utilisée ici est très similaire de celle utilisée pour faire pisser les personnages.

1/ MAPPING

Créer votre map comme d'habitude. Ensuite vous allez insérer les différentes entités que voici :

* 2 Actor/axis toujours avec un kar car l'animation est faite avec un kar, avec les case SPAWNER et FORCESPAWN cochées.

model / xmodel/character_german_wehrmact_officer
classname / actor_axis_wehrmacht_clean_officer_pistol
spawnflags / 3
origin / 144 128 24
targetname / ducon
export / 5
angles / 0 90 0

* 1 node_scripted qui sera le siège de l'animation. (Les angles du node donnent la direction de la l'animation)

classname / node_scripted
target / ducon
targetname / chess // Ici chess est "obligatoire" car sinon il faudrait le changer dans le script. (allons au plus simple)
origin / 48 16 40
angles / 0 135 0

* 3 Triggers : 2 Trigger_multiple qui seront les déclencheurs de début et de fin d'animation.
                     : 1 Trigger_damage qui sera le déclencheur si on tire sur les joueurs (simulation d'attaque).

Trigger_multiple 1 (Start de l'animation quand le joueur passe le trigger)

classname / trigger_multiple
targetname / ducon
target / auto1

Trigger_multiple 2 (Stoppe l'animation quand le joueur passe le trigger)

classname / trigger_multiple
targetname / auto1

Trigger_damage (Stoppe l'animation si on tire dessus)

classname / trigger_damage
targetname / auto1

Pour résumer voici ce que ça donne.

 

ATTENTION !!!


Screen dans radiant

- Comme vous pouvez le voir sur les screens et dans le jeu, le soldat debout s'appuie à un mur alors que l'autre est assis sur une caisse. Il faut donc que vous trouviez le bon brush dans la bonne position afin de rendre l'animation crédible.

- Le second bruh dont vous devez faire attention est celui qui tient le fusil du soldat assis. là aussi c''est à vous de trouver la bonne orientation taille etc....

- La troisième difficulté réside dans le fait que la caisse sur laquelle repose le jeu n'est pas solide. (on passe à travers.) Il faut donc que vous tailliez un brush de la taille de la caisse voire un peu inférieur (20 x 24 x 20) (Longueur x hauteur x largeur). Ce brush vous allez le texturer avec la texture "clip_wood" que vous trouverez dans le répertoire "common".

Astuce : Pour trouver la bonne position des brushes je vous conseille d'en créer plusieurs avec des textures différentes. De les placer sur votre map, et de voir ce que cela donne dans le jeu et ensuite d'affiner leur position.

 

Voici finie la partie mapping.

 

2/ SCRIPTING

a/ le fichier ma_map.gsc

main()
{
maps\_load::main();
maps\test_chess_anim::main();
maps\test_chess_anim::props();

//GIVE PLAYER WEAPONS
level.player takeallweapons();
level.player giveWeapon("panzerfaust");
level.player giveWeapon("springfield");
level.player giveWeapon("colt");
level.player giveWeapon("fraggrenade");
level.player switchToWeapon("springfield");

precacheModel("xmodel/chessgame_animrig");
precacheModel("xmodel/holophane_lamp");
precacheModel("xmodel/chessgame_animnode");
precacheModel("xmodel/chessgame_animrig");


thread chess (getnode ("chess","targetname")); //envoie vers la methode chess avec comme variable l'entité ayant chess comme targetname.


}

////////////////////////////////
deleter ()
{
self endon ("death");
println ("waiting for soundplayer deletion");
level waittill ("chess interrupted");
println ("deleting soundplayer");
// self stopsound();
self delete();
}
/////////////////////////////////
stopChessSounds ()
{
self endon ("death");
self waittill ("fight");
if (self.chessSounds)
self animscripts\face::SaySpecificDialogue (undefined, "german_enemy_sighted", 1.0);
}
///////////////////////////////////
chessSounds (guy1, guy2)
{
guy1 endon ("death");
guy2 endon ("death");
guy1 endon ("fight");
guy2 endon ("fight");

guy1 thread stopChessSounds();
guy2 thread stopChessSounds();
guy1.chessSounds = false;
guy2.chessSounds = false;
level.chessTalkTrigger waittill ("trigger");
guy1.chessSounds = true;
guy2.chessSounds = true;
println ("^5 TIME TO CHESS TALK");
level endon ("chess interrupted");
guy1 animscripts\face::SaySpecificDialogue (undefined, "Pathfinder_German_Guard1_wonder", 1.0, "sounddone");
guy1 waittill ("sounddone");
guy2 animscripts\face::SaySpecificDialogue (undefined, "Pathfinder_German_Guard2_1sttoknow", 1.0, "sounddone");
guy2 waittill ("sounddone");
guy1 animscripts\face::SaySpecificDialogue (undefined, "Pathfinder_German_Guard1_wrong", 1.0, "sounddone");
guy1 waittill ("sounddone");
guy2 animscripts\face::SaySpecificDialogue (undefined, "Pathfinder_German_Guard2_thepointis", 1.0, "sounddone");
guy2 waittill ("sounddone");
guy1 animscripts\face::SaySpecificDialogue (undefined, "Pathfinder_German_Guard1_sowhat", 1.0, "sounddone");
guy1 waittill ("sounddone");
maps\pathfinder_anim::enableChessSounds();
guy1.chessSounds = false;
guy2.chessSounds = false;
}

chess_leap_deathanim ()
{
self endon ("death");
while (1)
{
self waittill ("single anim", notetrack);

if (notetrack == "god mode")
{
// self.allowdeath = false;
props[0] = level.chess_pieces;
// if ((isalive (guy[0])) && (isdefined (guy[0].deathanim)))
thread anim_single (props, "fight", undefined, level.chess_pieces);
continue;
}

if (notetrack != "normal death")
continue;

self.allowdeath = true;
self.deathanim = undefined;
// self notify ("stop leaping");
// self.health = 90;
return;
}
}

chessSpecialDeath (spawn, node)
{
// self endon ("stop leaping");
spawn.allowdeath = true;
// spawn.health = 50000;
spawn waittill ("pain");
// spawn.deathanim = level.scr_anim[spawn.animname]["leap death"];
anim_single_solo (spawn, "leap death", undefined, node);
spawn DoDamage ( spawn.health + 50, spawn.origin );
}

chess ( node )
{
targets = getentarray (node.target,"targetname");
spawners = [];
for (i=0;i<targets.size;i++)
{
if (targets[i].classname == "trigger_multiple")
{
start_trigger = targets[i];
level.chessTalkTrigger = start_trigger;
stop_triggers = getentarray (start_trigger.target,"targetname");
}
else
spawners[spawners.size] = targets[i];
}
targets = undefined;
spawners[0].animname = "sit";
spawners[1].animname = "stand";

// thread maps\_anim::anim_spawner_teleport (spawners, "move 1", undefined, node);

guy = [];
for (i=0;i<spawners.size;i++)
{
spawners[i].count = 1;
while (1)
{
guy[i] = spawners[i] stalingradspawn();
if (isalive (guy[i]))
break;
else
wait (1);
}
}

for (i=0;i<guy.size;i++)
{
if (!i)
{
guy[i].animname = "sit";
guy[i].deathanim = level.scr_anim[guy[i].animname]["sit death"];
guy[i] thread chess_leap_deathanim();
}
else
{
guy[i].animname = "stand";
guy[i].deathanim = level.scr_anim[guy[i].animname]["death"];
}

guy[i].allowdeath = true;
guy[i].health = 1;
// guy[i] endon ("death");
// guy[i] endon ("pain");
}

thread chessSounds(guy[0], guy[1]);
chess_node = spawn ("script_model",(0,0,0));
chess_node setmodel ("xmodel/chessgame_animnode");
chess_node.origin = node.origin;
chess_node.angles = node.angles;

chess_pieces = spawn ("script_model",(0,0,0));
chess_pieces setmodel ("xmodel/chessgame_animrig");
chess_pieces.animname = "pieces";
chess_pieces.origin = chess_node gettagorigin ("TAG_crate");
chess_pieces.angles = chess_node gettagangles ("TAG_crate");
chess_pieces UseAnimTree(level.scr_animtree[chess_pieces.animname]);
level.chess_pieces = chess_pieces;
level thread chess_think( guy, node, chess_pieces );
array_thread (stop_triggers, ::trigger_stop, start_trigger);
// array_levelthread (guy, ::chess_pain);
level thread chess_radius( guy[0] );
start_trigger waittill ("stop trigger");

newguy = [];

continuer = false;
for (i=0;i<guy.size;i++)
{
if (isalive (guy[i]))
{
// if (guy[i].animname == "sit")
// thread chessSpecialDeath (guy[i], chess_node);

newguy[newguy.size] = guy[i];
continuer = true;
}
}
if (!continuer)
return;
guy = newguy;

level notify ("chess interrupted");
guy[0] notify ("fight");

anim_single (guy, "fight", undefined, node);

for (i=0;i<guy.size;i++)
{
if (isalive (guy[i]))
{
guy[i].deathanim = undefined;
// guy[i].health = 100;
}
}
}

chess_pain ( ai )
{
ai waittill ("pain");
if (isalive (ai))
ai notify ("end_sequence");
}

chess_radius ( guy )
{
guy endon ("death");
guy endon ("fight");

while (distance (level.player.origin, guy.origin) > 350)
wait (0.5);

guy notify ("player approaches");
}

chess_think ( guy, node, chess_pieces )
{
level endon ("chess interrupted");
for (i=0;i<guy.size;i++)
{
guy[i] endon ("death");
guy[i] endon ("pain");
guy[i] endon ("fight");
}

props[0] = chess_pieces;

guy[0] thread anim_loop ( guy, "idle", undefined, "player approaches", node);
println ("^c 1");
guy[0] waittill ("player approaches");

guy[0] anim_single (guy, "guard", undefined, node);

props[0] thread anim_single (props, "move 1", undefined, chess_pieces);
guy[0] anim_single (guy, "move 1", undefined, node);

guy[0] anim_single (guy, "think 1", undefined, node);
guy[0] anim_single (guy, "think 2", undefined, node);
guy[0] anim_single (guy, "think 1", undefined, node);
guy[0] anim_single (guy, "think 1", undefined, node);
guy[0] anim_single (guy, "think 2", undefined, node);


guy[0] anim_single (guy, "think 1", undefined, node);
guy[0] anim_single (guy, "think 2", undefined, node);
guy[0] anim_single (guy, "think 1", undefined, node);

props[0] thread anim_single (props, "move 2", undefined, chess_pieces);
guy[0] anim_single (guy, "move 2", undefined, node);

guy[0] anim_single (guy, "think 1", undefined, node);
guy[0] anim_single (guy, "think 1", undefined, node);
guy[0] anim_single (guy, "think 2", undefined, node);
guy[0] anim_single (guy, "think 1", undefined, node);

props[0] thread anim_single (props, "move 3", undefined, chess_pieces);
guy[0] anim_single (guy, "move 3", undefined, node);

level anim_loop ( guy, "idle", undefined, "chess interrupted", node);
}
///////////////////////////////////////
trigger_stop ( trigger )
{
if (self.classname == "trigger_damage")
self enableGrenadeTouchDamage();
self waittill ("trigger");
trigger notify ("stop trigger");
}

//////////////////////////////////////////////////
anim_single (guy, anime, tag, node, tag_entity)
{
maps\_anim::anim_single (guy, anime, tag, node, tag_entity);
}
////////////////////////////
anim_single_solo (guy, anime, tag, node, tag_entity)
{
newguy[0] = guy;
maps\_anim::anim_single (newguy, anime, tag, node, tag_entity);
}
////////////////////////////////
anim_loop ( guy, anime, tag, ender, node, tag_entity )
{
maps\_anim::anim_loop ( guy, anime, tag, ender, node, tag_entity );
}
//////////////////////////
array_thread (ents, process, var, excluders)
{
maps\_utility::array_thread (ents, process, var, excluders);
}
////////////////////

b/ Le fichier map_map_anim.gsc.

#using_animtree("generic_human");
main()
{

/*
chess animations; // Explications en angalis du fichier jeu pathinder_anim.gsc
play (think) animations on both characters until the player gets close enough to see them..
play (guard) for the last line of the guards dialogue
play (move1), then (move2), and finally (move3).These need to be played in order but you can play (think) between them if you need
to slow it down...

play (think) until the player interupts the seqence...
if (stand) guy is killed play a normal standing death. If he sees the player or is alerted by the player... play (panic) and he
will move to corner behavior in cover.
if (sit) guy is killed play (death). If he sees the player or is alerted by the player... play (leap) go for his gun.
chess animations; rig

when the (sit) guy reacts to the player he kicks and moves some of the props so play the corresponding anim (leap/death)
you will also need to play the corresponding chess piece animations for the moves (move1,move2,move3)
if this is done correctly the game board will look different based on when you interupt it and he will still be able to kick the
board at any point in the game...

*/
level.scr_animtree["stand"] = #animtree;
level.scr_anim["stand"]["fight"] = (%chess_standguy_paniccover);
level.scr_anim["stand"]["move 1"] = (%chess_standguy_move01);
level.scr_anim["stand"]["move 2"] = (%chess_standguy_move02);
level.scr_anim["stand"]["move 3"] = (%chess_standguy_move03);
level.scr_anim["stand"]["idle"][0] = (%chess_standguy_thinkidle);
level.scr_anim["stand"]["idle"][1] = (%chess_standguy_thinktwitch);
level.scr_anim["stand"]["think 1"] = (%chess_standguy_thinkidle);
// level.scrsound["stand"]["think 1"] = "Pathfinder_German_Guard1_hmm";
level.scr_anim["stand"]["think 2"] = (%chess_standguy_thinktwitch);
// level.scrsound["stand"]["think 2"] = "Pathfinder_German_Guard1_hmm";
level.scr_anim["stand"]["guard"] = (%chess_standguy_guard102);
level.scr_anim["stand"]["death"] = (%death_run_left);



level.scr_animtree["sit"] = #animtree;
level.scr_anim["sit"]["sit death"] = (%chess_sitguy_sitdeath);
level.scr_anim["sit"]["leap death"] = (%chess_sitguy_leapingdeath);

level.scr_anim["sit"]["fight"] = (%chess_sitguy_leapforgun);
level.scr_anim["sit"]["move 1"] = (%chess_sitguy_move01);
// level.scrsound["sit"]["move 1"] = "Pathfinder_German_Guard2_kibitz";
level.scr_anim["sit"]["move 2"] = (%chess_sitguy_move02);
// level.scrsound["sit"]["move 2"] = "Pathfinder_German_Guard2_kibitz";
level.scr_anim["sit"]["move 3"] = (%chess_sitguy_move03);
// level.scrsound["sit"]["move 3"] = "Pathfinder_German_Guard2_kibitz";
level.scr_anim["sit"]["idle"][0] = (%chess_sitguy_thinkidle);
level.scr_anim["sit"]["idle"][1] = (%chess_sitguy_thinktwitch);
level.scr_anim["sit"]["think 1"] = (%chess_sitguy_thinkidle);
level.scr_anim["sit"]["think 2"] = (%chess_sitguy_thinktwitch);
level.scr_anim["sit"]["guard"] = (%chess_sitguy_guard102);
}

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

enableChessSounds ()
{
level.scrsound["stand"]["think 1"] = "Pathfinder_German_Guard1_hmm";
level.scrsound["stand"]["think 2"] = "Pathfinder_German_Guard1_hmm";
level.scrsound["sit"]["move 1"] = "Pathfinder_German_Guard2_kibitz1";
level.scrsound["sit"]["move 2"] = "Pathfinder_German_Guard2_kibitz2";
level.scrsound["sit"]["move 3"] = "Pathfinder_German_Guard2_kibitz1";
}

#using_animtree("animation_rig_chessgame");
props()
{
level.scr_animtree["pieces"] = #animtree;

level.scr_anim["pieces"]["move 1"] = (%chess_pieces_move01);
level.scr_anim["pieces"]["move 2"] = (%chess_pieces_move02);
level.scr_anim["pieces"]["move 3"] = (%chess_pieces_move03);
level.scr_anim["pieces"]["fight"] = (%chess_props_leapforgun);
level.scr_anim["pieces"]["death"] = (%chess_props_sitdeath);
}

Cette fois-ci pas de fichiers sons à modifier...

Pour télécharger la map test CODUO seulement, cliquez ici.

Par Tropheus - 2005 Copyright © by CaskAmi Prod. Tout droit réservé.

 

Page générée en

Design / concept Amigos3D - Copyright ©2006 CaskAmi Prod. Tous droits réservés.
Caskami.com est hébergé; par Eliott-Ness.