Catapulte controlable.

Répondre
Partager Rechercher
Voici un script permettant de tirer avec une catapulte et de modifier son orientation, la distance/hauteur de la cible.

Code PHP:

//Fonctionnement ameliore d'une catapulte
//=======================================
//Par Holgadard (c) Decembre 2006
//Base sur le script de Ivellios, Muad'dib
//
//Fichier "on_used_catap"
//
// A placer dans le OnUsed de la catapulte
//
//Condition : creer une balliste.
//
//Variables locales utilisees a placer dans les proprietes de la catapulte:
//-------------------------------------------------------------------------
//"DistCible" float
//"HauteurCible" float
//"Reglage" float
//"Commande" int
//"PretePourTirer" int
//
//DistCible : contient la distance de la cible
//HauteurCible : contient la hauteur de la cible
//Reglage : contient la valeur de reglage pour les commande d'orientation ou de placement de la cible a viser
//Commande : contient la fonction assignee a la catapulte : tourner, changer la distance/hauteur de la cible ou tirer sur la cible
//         si = 0 : Charger la catapulte / Tirer sur la cible
//         si = 1 : Tourner a droite (positionnement visible de la catapulte par tranche de 20 degres)
//         si = 2 : Tourner a gauche (positionnement visible de la catapulte par tranche de 20 degres)
//         si = 3 : viser plus loin (modification de la distance de la cible - variable "DistCible" + "Reglage")
//         si = 4 : viser plus pres (modification de la distance de la cible - variable "DistCible" - "Reglage")
//         si = 5 : viser plus haut (modification de la hauteur de la cible - variable "HauteurCible" + "Reglage")
//         si = 6 : viser plus bas (modification de la hauteur de la cible - variable "HauteurCible" - "Reglage")
//PretePourTirer : Indique si la catapulte peut tirer sur la cible
//
//Fonctionnement : Selon la valeur de "Commande" (0 par defaut)
//-------------------------------------------------------------
//Lors du chargement :
//- Animation du PJ en train de charger la catapulte
//- Une petite flamme s'allume sur la cuillere de la catapulte pour indiquer qu'elle est prete a tirer
//- Attend le tir du PJ
//
//Lors du tir :
//- Creation d'un WayPoint "CIBLE" en fonction de la distance par rapport a la catapulte et son orientation
//- Destruction de la flamme sur la cuillere
//- Tir sur "CIBLE"
//- Destruction de "CIBLE"
//- Attend le rechargement par le PJ
//
//
//Pour faciliter l'utilisation des reglages et assignation des commandes,
//- Creer un levier (par exemple) sur lequel on y place un dialogue indiquant les differentes possibilites de reglages et de commandes de la catapulte
//- faire, dans ce dialogue, des petits scripts a placer dans "Actions Consequentes" des differentes branches du dialogue.
// Ces petits scripts devront assigner les differentes variables locales utilisees pour le fonctionnement de la catapulte.
void Flamme(object oCatapulte,location LocFlamme)
{
object oFlamme;
if (
GetObjectByTag(GetTag(oCatapulte)+"_Flamme")!=OBJECT_INVALID) return; //La flamme existe deja : ne pas en remettre une autre
oFlamme=CreateObject(OBJECT_TYPE_PLACEABLE,"plc_flamesmall",LocFlamme,FALSE,GetTag(oCatapulte)+"_Flamme"); //Creer la flamme sur la cuillere de la catapulte
SetName(oFlamme,GetTag(oFlamme)); //Definir la nom de la flamme
SetLocalInt(oCatapulte,"PretePourTirer",1); //Indique que la catapulte peut tirer
}
 
void main()
{
object oPC=GetLastUsedBy();
object oCible;
float fDistance=GetLocalFloat(OBJECT_SELF,"DistCible"); //Distance de la cible.
float fHauteur=GetLocalFloat(OBJECT_SELF,"HauteurCible");//Hauteur de la cible
float fReglage=GetLocalFloat(OBJECT_SELF,"Reglage");//Precision du reglage de la catapulte
int iCmd=GetLocalInt(OBJECT_SELF,"Commande"); //Commande assignee a la catapulte (reglage orientaion/distance/hauteur/ ou tirer
if (fDistance<10.0fDistance=10.0//Distance minimun de la cible par rapport a la catapulte pour eviter de se tirer dessus
//if (fHauteur<0.0) fHauteur=0.0; //Limiter la hauteur de la cible
location LocCatapulte GetLocation(OBJECT_SELF); //Localise la catapulte
vector vCatapulte GetPositionFromLocation(LocCatapulte); //Position de la catapulte dans la zone
//Un peu de trigonometrie...
location LocCible Location(GetAreaFromLocation(LocCatapulte),Vector(vCatapulte.x+fDistance*cos(GetFacing(OBJECT_SELF)),vCatapulte.y+fDistance*sin(GetFacing(OBJECT_SELF)),fHauteur),GetFacingFromLocation(LocCatapulte)); //Definir la position de la cible et sa hauteur par rapport a l'orientation de la catapulte.
location LocFlamme Location(GetAreaFromLocation(LocCatapulte),Vector(vCatapulte.x-0.7*cos(GetFacing(OBJECT_SELF)),vCatapulte.y-0.7*sin(GetFacing(OBJECT_SELF)),vCatapulte.z+0.7),GetFacingFromLocation(LocCatapulte)); //Definir la position de la flamme sur la cuillere par rapport a l'orientation de la catapulte.
location LocUser=Location(GetAreaFromLocation(LocCatapulte),Vector(vCatapulte.x-1.5*cos(GetFacing(OBJECT_SELF)),vCatapulte.y-1.5*sin(GetFacing(OBJECT_SELF)),vCatapulte.z),GetFacingFromLocation(LocCatapulte)); //Definir la position du tireur derriere la catapulte pour la recharger.
 
//LES COMMANDES DE LA CATAPULTE
//-----------------------------
if (iCmd==0//Tirer sur la cible
{
if (
GetLocalInt(OBJECT_SELF"PretePourTirer"))
    {
//Faire feu sur la cible si PretePourTirer=1
    
oCible CreateObject(OBJECT_TYPE_WAYPOINT"nw_waypoint001"LocCibleFALSE"CIBLE"); //Creer la cible
    
location lCible GetLocationGetNearestObjectByTag"CIBLE"OBJECT_SELF) ); 
    
DestroyObject(GetObjectByTag(GetTag(OBJECT_SELF)+"_Flamme")); //Detruit la flamme de la cuillere
    
ActionWait(2.0); //Attend que la flamme soit eteinte avant d'envoyer la charge sur la cible
    
ActionCastSpellAtLocation(SPELL_FIREBALLlCibleMETAMAGIC_ANYTRUEPROJECTILE_PATH_TYPE_BALLISTIC); //Tire une boule de feu sur la cible
    
DestroyObject(oCible); //Destruction de la cible
    
DeleteLocalInt (OBJECT_SELF"PretePourTirer"); 
    }
else
    {
//Il faut charger la catapulte (PretePourTirer=0).
    //Annimations du PJ en train de charger la catapulte
    
AssignCommand(oPC,ActionMoveToLocation(LocUser)); //Le PJ va derriere la catapulte
    
DelayCommand(2.0,AssignCommand(oPC,PlayAnimation(ANIMATION_LOOPING_GET_LOW,1.0,1.5))); //Le PJ se penche pour rammasser une charge
    
DelayCommand(4.0,AssignCommand(oPC,SetFacing(GetFacing(OBJECT_SELF)-90.0))); //Le PJ se tourne vers la catapulte
    
DelayCommand(5.0,AssignCommand(GetLastUsedBy(),PlayAnimation(ANIMATION_LOOPING_GET_MID,1.0,1.5))); //Le PJ charge la catapulte
    //Catapulte prete a faire feu
    
DelayCommand(6.5,Flamme(OBJECT_SELF,LocFlamme)); //Met une flamme sur la cuillere de la catapulte et indique qu'elle est prete a tirer
    
}
}
if ((
iCmd==1) || (iCmd==4) || (iCmd==6)) fReglage=-fReglage//Modifier le reglage pour plus pres/bas/tourner a droite
if ((iCmd==1) || (iCmd==2)) //Tourner vers la droite / gauche
{
SetFacing(GetFacing(OBJECT_SELF)+fReglage); //Tourne la catapulte (le placeable tourne par tranche de 20 degres)
//Replace la flamme sur la cuillere par rapport a la nouvelle orientation.
if (GetLocalInt(OBJECT_SELF,"PretePourTirer"))
    {
    
DestroyObject(GetObjectByTag(GetTag(OBJECT_SELF)+"_Flamme"));
    
LocFlamme Location(GetAreaFromLocation(LocCatapulte),Vector(vCatapulte.x-0.7*cos(GetFacing(OBJECT_SELF)),vCatapulte.y-0.7*sin(GetFacing(OBJECT_SELF)),vCatapulte.z+0.7),GetFacingFromLocation(LocCatapulte)); //Definir la position de la cible par rapport a l'orientation de la catapulte.
    
DelayCommand(0.5,Flamme(OBJECT_SELF,LocFlamme));
    }
FloatingTextStringOnCreature("Orientation : "+FloatToString(GetFacing(OBJECT_SELF),3,2)+"°"GetLastUsedBy());
}
if ((
iCmd==3) || (iCmd==4)) //Asjuster la distance de la cible (loin / pres)
{
fDistance=fDistance+fReglage//Modifie la distance
if (fDistance<10.0fDistance=10.0//distance de securite : la catapulte ne peut pas se tirer dessus.
SetLocalFloat(OBJECT_SELF,"DistCible",fDistance); //Enregistre la distance
FloatingTextStringOnCreature("Distance du tir : "+FloatToString(fDistance,3,2)+" mètres."GetLastUsedBy());
}
if ((
iCmd==5) || (iCmd==6)) //Asjuster la hauteur de la cible (haut / bas)
{
fHauteur=fHauteur+fReglage//Modifie la hauteur
//if (fHauteur<0.0) fHauteur=0.0;
SetLocalFloat(OBJECT_SELF,"HauteurCible",fHauteur); //Enregistre la hauteur
FloatingTextStringOnCreature("Hauteur de la cible : "+FloatToString(fHauteur,3,2)+" mètres."GetLastUsedBy());
}

Fontionnement du script ci-dessus :

Placement d'une cible fictive en fonction de l'angle définit par l'orientation de la catapulte et la distance de la cible par rapport à celle de la catapulte.

Pour cela, il faut déterminer l'emplacement exact, et l'orientation du placeable dans la zone. D'où, apès cela, un petit calcul trigonométrique pour positionner la cible en face de la catapulte et la flamme sur la cuillère quand elle est prête à faire feu.


J'ai fait une petite mise à jour du script ci-dessus afin de mettre le feu à l'impact du tir de catapulte. Ça rend un peu plus réalistes les dégats causés par une boule de feu


Voici le script :
Code PHP:

 
 
//Fonctionnement ameliore d'une catapulte
//=======================================
//Par Holgadard (c) Decembre 2006
//Base sur le script de Ivellios, Muad'dib
//
//Fichier "on_used_catap"
//
// A placer dans le OnUsed de la catapulte
//
//Condition : creer une balliste.
//
//Variables locales utilisees a placer dans les proprietes de la catapulte:
//-------------------------------------------------------------------------
//"DistCible" float
//"HauteurCible" float
//"Reglage" float
//"Commande" int
//"PretePourTirer" int
//
//DistCible : contient la distance de la cible
//HauteurCible : contient la hauteur de la cible
//Reglage : contient la valeur de reglage pour les commande d'orientation ou de placement de la cible a viser
//Commande : contient la fonction assignee a la catapulte : tourner, changer la distance/hauteur de la cible ou tirer sur la cible
//         si = 0 : Charger la catapulte / Tirer sur la cible
//         si = 1 : Tourner a droite (positionnement visible de la catapulte par tranche de 20 degres)
//         si = 2 : Tourner a gauche (positionnement visible de la catapulte par tranche de 20 degres)
//         si = 3 : viser plus loin (modification de la distance de la cible - variable "DistCible" + "Reglage")
//         si = 4 : viser plus pres (modification de la distance de la cible - variable "DistCible" - "Reglage")
//         si = 5 : viser plus haut (modification de la hauteur de la cible - variable "HauteurCible" + "Reglage")
//         si = 6 : viser plus bas (modification de la hauteur de la cible - variable "HauteurCible" - "Reglage")
//PretePourTirer : Indique si la catapulte peut tirer sur la cible
//
//Fonctionnement : Selon la valeur de "Commande" (0 par defaut)
//-------------------------------------------------------------
//Lors du chargement :
//- Animation du PJ en train de charger la catapulte
//- Une petite flamme s'allume sur la cuillere de la catapulte pour indiquer qu'elle est prete a tirer
//- Attend le tir du PJ
//
//Lors du tir :
//- Creation d'un WayPoint "CIBLE" en fonction de la distance par rapport a la catapulte et son orientation
//- Destruction de la flamme sur la cuillere
//- Tir sur "CIBLE"
//- Destruction de "CIBLE"
//- Attend le rechargement par le PJ
//
//
//Pour faciliter l'utilisation des reglages et assignation des commandes,
//- Creer un levier (par exemple) sur lequel on y place un dialogue indiquant les differentes possibilites de reglages et de commandes de la catapulte
//- faire, dans ce dialogue, des petits scripts a placer dans "Actions Consequentes" des differentes branches du dialogue.
// Ces petits scripts devront assigner les differentes variables locales utilisees pour le fonctionnement de la catapulte.
void Flamme(object oCatapulte,location LocFlamme)
{
object oFlamme;
if (
GetObjectByTag(GetTag(oCatapulte)+"_Flamme")!=OBJECT_INVALID) return; //La flamme existe deja : ne pas en remettre une autre
oFlamme=CreateObject(OBJECT_TYPE_PLACEABLE,"plc_flamesmall",LocFlamme,FALSE,GetTag(oCatapulte)+"_Flamme"); //Creer la flamme sur la cuillere de la catapulte
SetName(oFlamme,GetTag(oFlamme)); //Definir la nom de la flamme
SetLocalInt(oCatapulte,"PretePourTirer",1); //Indique que la catapulte peut tirer
}
 
void FlammeSurCible(object oCible)
{
//if (oCibleProche==OBJECT_INVALID) return;
//ChangeToStandardFaction(oCible, STANDARD_FACTION_HOSTILE);
int iRand=Random(2);
string sRefFlam;
object oFlamme;
switch (
iRand)
    {
    case 
0sRefFlam="plc_flamemedium"; break;
    case 
1sRefFlam="plc_flamelarge"; break;
    default: 
sRefFlam="plc_flamemedium"; break;
    }
object oCibleProche=GetNearestObject(OBJECT_TYPE_ALLoCible);
if (
GetDistanceBetween(oCibleoCibleProche)>2.0oCibleProche=OBJECT_INVALID;
if (
oCibleProche!=OBJECT_INVALIDoFlamme=CreateObject(OBJECT_TYPE_PLACEABLE,sRefFlam,GetLocation(oCible),FALSE);
DestroyObject(oCible); //Destruction de la cible
//ChangeToStandardFaction(oFlamme, STANDARD_FACTION_HOSTILE);
}
 
void main()
{
object oPC=GetLastUsedBy();
object oCible;
float fDistance=GetLocalFloat(OBJECT_SELF,"DistCible"); //Distance de la cible.
float fHauteur=GetLocalFloat(OBJECT_SELF,"HauteurCible");//Hauteur de la cible
float fReglage=GetLocalFloat(OBJECT_SELF,"Reglage");//Precision du reglage de la catapulte
int iCmd=GetLocalInt(OBJECT_SELF,"Commande"); //Commande assignee a la catapulte (reglage orientaion/distance/hauteur/ ou tirer
if (fDistance<10.0fDistance=10.0//Distance minimun de la cible par rapport a la catapulte pour eviter de se tirer dessus
SetLocalFloat(OBJECT_SELF,"DistCible",fDistance);
//if (fHauteur<0.0) fHauteur=0.0; //Limiter la hauteur de la cible
location LocCatapulte GetLocation(OBJECT_SELF); //Localise la catapulte
vector vCatapulte GetPositionFromLocation(LocCatapulte); //Position de la catapulte dans la zone
//Un peu de trigonometrie...
location LocCible Location(GetAreaFromLocation(LocCatapulte),Vector(vCatapulte.x+fDistance*cos(GetFacing(OBJECT_SELF)),vCatapulte.y+fDistance*sin(GetFacing(OBJECT_SELF)),fHauteur),GetFacingFromLocation(LocCatapulte)); //Definir la position de la cible et sa hauteur par rapport a l'orientation de la catapulte.
location LocFlamme Location(GetAreaFromLocation(LocCatapulte),Vector(vCatapulte.x-0.7*cos(GetFacing(OBJECT_SELF)),vCatapulte.y-0.7*sin(GetFacing(OBJECT_SELF)),vCatapulte.z+0.7),GetFacingFromLocation(LocCatapulte)); //Definir la position de la flamme sur la cuillere par rapport a l'orientation de la catapulte.
location LocUser=Location(GetAreaFromLocation(LocCatapulte),Vector(vCatapulte.x-1.5*cos(GetFacing(OBJECT_SELF)),vCatapulte.y-1.5*sin(GetFacing(OBJECT_SELF)),vCatapulte.z),GetFacingFromLocation(LocCatapulte)); //Definir la position du tireur derriere la catapulte pour la recharger.
 
//LES COMMANDES DE LA CATAPULTE
//-----------------------------
if (iCmd==0//Tirer sur la cible
{
if (
GetLocalInt(OBJECT_SELF"PretePourTirer"))
    {
//Faire feu sur la cible si PretePourTirer=1
    
AssignCommand(GetLastUsedBy(),PlayAnimation(ANIMATION_LOOPING_GET_MID,1.0,1.0)); //Le PJ charge la catapulte
    
oCible CreateObject(OBJECT_TYPE_WAYPOINT"nw_waypoint001"LocCibleFALSEGetTag(OBJECT_SELF)+"_CIBLE"); //Creer la cible
    //oCible = CreateObject(OBJECT_TYPE_PLACEABLE, "plc_invisobj", LocCible, FALSE, GetTag(OBJECT_SELF)+"_CIBLE"); //Creer la cible
    //ChangeToStandardFaction(oCible, STANDARD_FACTION_HOSTILE);
    //location lCible = GetLocation( GetNearestObjectByTag( GetTag(OBJECT_SELF)+"_CIBLE", OBJECT_SELF, 1 ) ); 
    
location lCible GetLocation(oCible); // Définition du point d'impact
    
DestroyObject(GetObjectByTag(GetTag(OBJECT_SELF)+"_Flamme")); //Detruit la flamme de la cuillere
    
ActionWait(2.0); //Attend que la flamme de la cuillere soit eteinte avant d'envoyer la charge sur la cible
    
ActionCastSpellAtLocation(SPELL_FIREBALLlCibleMETAMAGIC_ANYTRUEPROJECTILE_PATH_TYPE_BALLISTIC); //Tire une boule de feu sur la cible
    
DelayCommand(((fDistance*1.3)/10),FlammeSurCible(oCible)); //Met le feu a l'impact
    //DelayCommand(((fDistance*1.3)/10),ExecuteScript("of_catap_fsc",oCible)); //Met le feu a l'impact
    
DeleteLocalInt (OBJECT_SELF"PretePourTirer"); 
    }
else
    {
//Il faut charger la catapulte (PretePourTirer=0).
    //Annimations du PJ en train de charger la catapulte
    
AssignCommand(oPC,ActionMoveToLocation(LocUser)); //Le PJ va derriere la catapulte
    
DelayCommand(2.0,AssignCommand(oPC,PlayAnimation(ANIMATION_LOOPING_GET_LOW,1.0,1.5))); //Le PJ se penche pour rammasser une charge
    
DelayCommand(4.0,AssignCommand(oPC,SetFacing(GetFacing(OBJECT_SELF)-90.0))); //Le PJ se tourne vers la catapulte
    
DelayCommand(5.0,AssignCommand(GetLastUsedBy(),PlayAnimation(ANIMATION_LOOPING_GET_MID,1.0,1.5))); //Le PJ charge la catapulte
    //Catapulte prete a faire feu
    
DelayCommand(6.5,Flamme(OBJECT_SELF,LocFlamme)); //Met une flamme sur la cuillere de la catapulte et indique qu'elle est prete a tirer
    
}
}
if ((
iCmd==1) || (iCmd==4) || (iCmd==6)) fReglage=-fReglage//Modifier le reglage pour plus pres/bas/tourner a droite
if ((iCmd==1) || (iCmd==2)) //Tourner vers la droite / gauche
{
AssignCommand(GetLastUsedBy(),PlayAnimation(ANIMATION_LOOPING_GET_MID,1.0,1.0)); //Le PJ charge la catapulte
DelayCommand(1.0,SetFacing(GetFacing(OBJECT_SELF)+fReglage)); //Tourne la catapulte (le placeable tourne par tranche de 20 degres)
//Replace la flamme sur la cuillere par rapport a la nouvelle orientation.
if (GetLocalInt(OBJECT_SELF,"PretePourTirer"))
    {
    
DestroyObject(GetObjectByTag(GetTag(OBJECT_SELF)+"_Flamme"));
    
LocFlamme Location(GetAreaFromLocation(LocCatapulte),Vector(vCatapulte.x-0.7*cos(GetFacing(OBJECT_SELF)),vCatapulte.y-0.7*sin(GetFacing(OBJECT_SELF)),vCatapulte.z+0.7),GetFacingFromLocation(LocCatapulte)); //Definir la position de la cible par rapport a l'orientation de la catapulte.
    
DelayCommand(0.5,Flamme(OBJECT_SELF,LocFlamme));
    }
DelayCommand(1.1,FloatingTextStringOnCreature("Orientation : "+FloatToString(GetFacing(OBJECT_SELF),3,2)+"°"GetLastUsedBy()));
}
if ((
iCmd==3) || (iCmd==4)) //Asjuster la distance de la cible (loin / pres)
{
AssignCommand(GetLastUsedBy(),PlayAnimation(ANIMATION_LOOPING_GET_MID,1.0,1.0)); //Le PJ charge la catapulte
fDistance=fDistance+fReglage//Modifie la distance
if (fDistance<10.0fDistance=10.0//distance de securite : la catapulte ne peut pas se tirer dessus.
SetLocalFloat(OBJECT_SELF,"DistCible",fDistance); //Enregistre la distance
DelayCommand(1.0,FloatingTextStringOnCreature("Distance du tir : "+FloatToString(fDistance,3,2)+" mètres."GetLastUsedBy()));
}
if ((
iCmd==5) || (iCmd==6)) //Asjuster la hauteur de la cible (haut / bas)
{
AssignCommand(GetLastUsedBy(),PlayAnimation(ANIMATION_LOOPING_GET_MID,1.0,1.0)); //Le PJ charge la catapulte
fHauteur=fHauteur+fReglage//Modifie la hauteur
//if (fHauteur<0.0) fHauteur=0.0;
SetLocalFloat(OBJECT_SELF,"HauteurCible",fHauteur); //Enregistre la hauteur
DelayCommand(1.0,FloatingTextStringOnCreature("Hauteur de la cible : "+FloatToString(fHauteur,3,2)+" mètres."GetLastUsedBy()));
}

Pour que le feu à l'impact soit actif, il est nécessaire qu'un object soit proche de l'impact (plein de waypoints par exemple). Ceci parce que du feu sur de l'eau, ça fait bizarre.

Si vous voulez du feu à chaque impact, il suffit de remplacer dans FlammeSurCible

Code PHP:

if (oCibleProche!=OBJECT_INVALIDoFlamme=CreateObject(OBJECT_TYPE_PLACEABLE,sRefFlam,GetLocation(oCible),FALSE); 

par


Code PHP:

oFlamme=CreateObject(OBJECT_TYPE_PLACEABLE,sRefFlam,GetLocation(oCible),FALSE); 

Question
Pb sur flammes à l'impact.
REMARQUE après quelques tests approfondis : la faction de la catapulte a son importance. En effet une catapulte ne fera aucun dégât à une créature de même faction qu'elle, ou neutre comme populace.

OBSERVATIONS sur les flammes à l'impact. Là aussi, la faction de la catapulte a son importance. Si la catapulte est hostile, la flamme à l'impact est permanente, mais dans les autres cas, la flamme s'éteint. Je ne comprend pas pourquoi.

Si quelqu'un pouvait m'aider à résoudre ce mystère pour que la flamme à l'impact soit permanente, quelle que soit la faction de la catapulte, ce serait sympa.

Ça fait plusieurs jours que je planche dessus, sans résultat.

Mon but étant de faire une bataille navale qui soit réaliste par tir de catapultes interposées avec dégât visibles sur les navires.

J'ai déjà presque fini de réaliser le script du PNJ qui contrôle la catapulte.
Bon, ben j'ai trouvé la solution à mon problème de flammes à l'impact qui s'éteint, après moult recherches et tests divers.

Comme je l'ai dit précédemment, la faction de l'objet a son importance. Dans NWN, les objets et placeables sont, par défaut, hostiles.

Donc, quand la faction de la catapulte est défenseur (par exemple), son tir est de même faction qu'elle. Par conséquent cela détruit tout ce qui est ennemi de Défenseur, y compris les flammes créées à l'impact pour effets visuels, qui sont, je le rappelles, hostiles.

Solution : créer des objets personnalisés flammes de faction populace (neutre par défaut). Remplacer leur sRef respectif dans la commande "FlammeSurCible" du script de la catapulte.

Et voilou.

EDIT : mieux vaut créer des flammes de même faction que la catapulte. Ce sera plus sûr.
Juste pour infos, je vous met le script sur lequel je me suis basé :

By Ivellios Thanks : Muad'dib
Code PHP:

 
////////////////////////////// ////////////
//By Ivellios     Thanks : Muad'dib //
//Script :                             //
//Tire de boule de feu en lob.         //
//A mettre dans :                     //
//Le OnUsed de la catapulte et         //
//faire un wp pour tag "Cible".        //
////////////////////////////// ////////////
 
void main()
{
 
if (
GetLocalInt(OBJECT_SELF"recharger") == 0)
{
 
    
location lCible GetLocationGetNearestObjectByTag"Cible"OBJECT_SELF) );
 
    
ActionCastSpellAtLocation(SPELL_FIREBALLlCibleMETAMAGIC_ANYTRUEPROJECTILE_PATH_TYPE_BALLISTIC);
 
    
SetLocalInt (OBJECT_SELF"recharger"1);
 
    
ActionWait(12.0);
 
    
ActionDoCommand(SetLocalInt(OBJECT_SELF,"recharger"0));
}
 
else
{
 
    
SpeakString("La catapulte n'est pas encore rechargé.");
}

Bientôt, je donnerai le script du PNJ qui contrôle la catapulte. C'est presque au point. Encore quelques bugs à corriger. Et ce sera fin prêt pour des batailles navales.
Mise à jour
Petite mise à jour du script :

Remplacez la commande interne "FlammeSurCible" par le code ci-dessous
Cela à pour effet de sélectionner le placeable "Flamme" adéquat en fonction de l'hostilité du tireur : vos tirs ne pourront plus détruire les effets flammes déjà posés (de même pour les tirs de l'ennemi).

Editer et copier les placeables :
- plc_flamelarge : changer le sRef par flamelarge_n et changer la faction par celle de la catapulte.
- plc_flamemedium : changer le sRef par flamemedium_n et changer la faction par celle de la catapulte.

Code PHP:

//Flamme a l'impact
void FlammeSurCible(object oCibleobject oTireur)
{
int iHostile=FALSE;
if (
GetStandardFactionReputation(STANDARD_FACTION_HOSTILEoTireur)>50iHostile=TRUE;
string sRefFlam;
object oFlamme;
switch (
Random(2))
    {
    case 
0: if (iHostilesRefFlam="plc_flamemedium"; else sRefFlam="flamemedium_n"; break;
    case 
1: if (iHostilesRefFlam="plc_flamelarge"; else sRefFlam="flamelarge_n"; break;
    default: if (
iHostilesRefFlam="plc_flamelarge"; else sRefFlam="flamelarge_n"; break;
    }
object oCibleProche=GetNearestObject(OBJECT_TYPE_ALLoCible); //Test si un objet est proche de la cible
if (GetDistanceBetween(oCibleoCibleProche)>2.0oCibleProche=OBJECT_INVALID//Distance OK entre cible et objet pour mettre une flamme a l'impact ?
if (oCibleProche!=OBJECT_INVALIDoFlamme=CreateObject(OBJECT_TYPE_PLACEABLE,sRefFlam,GetLocation(oCible),FALSE); //Flamme a l'impact
DestroyObject(oCible); //Destruction de la cible


Dans le corps du script, remplacer :

Code PHP:

//LES COMMANDES DE LA CATAPULTE
//-----------------------------
if (iCmd==0//Tirer sur la cible
{
if (
GetLocalInt(OBJECT_SELF"PretePourTirer"))
    {
//Faire feu sur la cible si PretePourTirer=1
//... code 
    
DelayCommand(((fDistance*1.3)/10),FlammeSurCible(oCibleoPC)); //Met le feu a l'impact
 
// ... reste du code ... 
PNJ qui utilise la catapulte.
Comme promis, voici le script du PNJ qui contrôle la catapulte.

Quelques règles pour faire une bataille navale.

- 2 navires minimums : l'un est destiné à l'ennemi
- 1 PNJ et 1 catapulte, tous deux, faction Hostile sur le bateau ennemi.
- 1 PNJ et 1 catapulte, tous deux, faction Défenseur sur votre bateau.
- Sur les catapultes, placer dans leur OnUsed, le script donné plus haut.
- Sur les PNJ, mettre une variable locale type int "Tireur_Catapulte" de valeur =1
(ceci parce que, pour moi-même, j'ai créé un dialogue avec le PNJ qui me permet de prendre le contrôle de la catapulte ou de le rendre au PNJ).
- Placer le script ci-dessous dans le OnHeartBeat de chaque PNJ qui utilise une catapulte.

- facultatif : placer un levier de sol pour les commandes de la catapulte (le levier n'a pas de réelle utilité pour le PNJ tireur. J'en ai créer un pour effectuer les divers réglages de la catapulte lorsque c'est le PJ qui en prend le contrôle).

Tag de la catapulte : "Catapulte_" + Tag du PNJ
Tag du levier : "Levier_" + Tag de la catapulte.


Fonctionnement basique du script du PNJ
----------------------------------------------------
- Le PNJ cherche un ennemi
- Si ennemi présent : le PNJ règle la catapulte et tire tant que l'ennemi ou lui-même n'est pas mort.

Fonctionnement détaillé :
--------------------------------
Point d"origine de la zone : en bas à gauche

Ce que fait le script lorsqu'un ennemi est présent (j'ai dû ressortir les cours de trigonométrie) :
- Déplacemement du point d'origine de la zone pour le placer sur la catapulte (la catapulte devient donc le nouveau point d'origine de la zone).
- Recherche l'angle formé entre la catapulte et l'ennemi.
- Recherche l'angle formé entre l'ennemi et l'orientation de la catapulte.
- Définir dans quel sens tourner la catapulte
- Definir la distance entre la catapulte, la cible de la catapulte et l'ennemi visé.
- Affecter les commandes à la catapulte pour faire les réglages adéquats et tirer.


Voici le script du PNJ (il est assez lourd)


Code PHP:

 
//////////////////////////////////////
// Tireur de catapulte automatise //
//        (C) OF, Dec 2006         //
//                                 //
//             v1.2                //
//////////////////////////////////////
//
// A placer dans le OnHeartbeat du PNJ qui controle la catapulte
//
// Condition de fonctionnnement :
//-------------------------------
// - Creer un PNJ et placer ce code dans son OnHeartBeat
// - Dans les proprietes du PNJ, placer une variable locale "Tireur_Catapulte" type int
//     - si =0 : le PNJ se ballade aleatoirement (vous pouvez, par exemple, etablir un dialogue avec le PNJ
//     - si =1 : le PNJ prend le controle de la catapulte
// - Creer une balliste d'apparence "Catapulte"
// - Tag de la catapulte : "Catapulte_" + Tag du PNJ
// - Placer dans le OnUsed de la catapulte "of_used_catap"
// - Changer la faction de la catapulte et mettre la même que celui du PNJ tireur
//
//Facultatif
//----------
// - Creer un levier au sol pres de la catapulte
// - Tag du levier : "Levier_" + Tag de la catapulte
void ReglerDist(object oCatapulteobject oTireurfloat fDistEnnemi)
{
int iDist=abs(FloatToInt(fDistEnnemi));
object oLevier=GetObjectByTag("Levier_"+GetTag(oCatapulte));
float fDelai=0.1;
if (
GetLocalInt(oTireur,"Levier")) //Le tireur doit actionner le levier de commandes ?
    
{//OUI
    
AssignCommand(oTireur,ActionInteractObject(oLevier)); //Le tireur actionne le levier de commande (ne fait rien si le levier n'existe pas).
    
fDelai=1.3;
    }
DeleteLocalInt(oTireur,"Levier"); //Le tireur n'est plus autorise a utiliser le levier de commandes.
//Definir la valeur du reglage
SetLocalFloat(oCatapulte,"Reglage",1.0); //Defaut
if (iDist>1SetLocalFloat(oCatapulte,"Reglage",1.0);
if (
iDist>5SetLocalFloat(oCatapulte,"Reglage",5.0);
if (
iDist>10SetLocalFloat(oCatapulte,"Reglage",10.0);
DelayCommand(fDelai,AssignCommand(oTireur,ActionInteractObject(oCatapulte))); //Le tireur actionne la catapulte
DelayCommand(fDelai+0.3,SpeakString("La catapulte est réglée sur "+FloatToString(GetLocalFloat(oCatapulte,"DistCible"),3,0)+" mètres."));
}
 
void ReglerOrient(object oCatapulteobject oTireurfloat fOrientEnnemi)
{
object oLevier=GetObjectByTag("Levier_"+GetTag(oCatapulte));
float fDelai=0.1;
if (
GetLocalInt(oTireur,"Levier")) //Le tireur doit actionner le levier de commandes ?
    
{//OUI
    
AssignCommand(oTireur,ActionInteractObject(oLevier)); //Le tireur actionne le levier de commande
    
fDelai=1.3;
    }
DeleteLocalInt(oTireur,"Levier"); //Le tireur n'est plus autorise a utiliser le levier de commandes.
int iDiffAng=abs(FloatToInt(fOrientEnnemi-GetFacing(oCatapulte)));
//Definir la valeur de l'angle de reglage
SetLocalFloat(oCatapulte,"Reglage",1.0);
if (
iDiffAng>1SetLocalFloat(oCatapulte,"Reglage",1.0);
if (
iDiffAng>5SetLocalFloat(oCatapulte,"Reglage",5.0);
if (
iDiffAng>10SetLocalFloat(oCatapulte,"Reglage",10.0);
DelayCommand(fDelai,AssignCommand(oTireur,ActionInteractObject(oCatapulte))); //Le tireur actionne la catapulte
DelayCommand(fDelai+0.3,SpeakString("Angle de tir : "+FloatToString(GetFacing(oCatapulte),3,0)+" degrés."));
}
 
void main()
{
    
//ExecuteScript("nw_c2_default1", OBJECT_SELF);
//Placer des // sur les 2 lignes suivantes pour que le PNJ soit le seul a utiliser la catapulte.
    
if ( (!GetLocalInt(OBJECT_SELF,"Tireur_Catapulte")) || (!IsInConversation(OBJECT_SELF)) ) ActionRandomWalk();
    if ( (!
GetLocalInt(OBJECT_SELF,"Tireur_Catapulte")) || (IsInConversation(OBJECT_SELF)) ) return;
    
ClearAllActions();
    
object oEnnemiCible=GetLocalObject(OBJECT_SELF,"EnnemiCible");
    
object oArea=GetArea(OBJECT_SELF);
    
object oCatapulte=GetObjectByTag("Catapulte_"+GetTag(OBJECT_SELF));
    
object oLevier=GetObjectByTag("Levier_"+GetTag(oCatapulte));
    
float fDelai=0.1;
    
float fDistEnnemi=500.0;
    if (
GetLocalFloat(OBJECT_SELF,"DistEnnemi")<=10.0SetLocalFloat(OBJECT_SELF,"DistEnnemi",fDistEnnemi);
 
    
//Recherche d'un ennemi
    
if (oEnnemiCible==OBJECT_INVALID)
     {
//Le PNJ n'a pas encore identifie un ennemi, il en cherche un
     
object oEnnemi=GetFirstObjectInArea(oArea);
     while (
oEnnemi!=OBJECT_INVALID || oEnnemiCible!=OBJECT_INVALID)
        {
        if (
GetObjectType(oEnnemi)==OBJECT_TYPE_CREATURE)
         {
         if ( (
GetIsEnemy(oEnnemiOBJECT_SELF)) && (oEnnemiCible==OBJECT_INVALID) || ( ((oEnnemiCible!=OBJECT_INVALID) && (fDistEnnemi<GetDistanceBetween(OBJECT_SELFoEnnemi))) ) )
            {
            
SetLocalObject(OBJECT_SELF,"EnnemiCible",oEnnemi); //Ennemi identifie.
            
SetLocalFloat(OBJECT_SELF,"DistEnnemi",GetDistanceBetween(OBJECT_SELFoEnnemi));
            
SpeakString("Navire ennemi en vue ! Je vais régler la catapulte.");
            }
         }
        
oEnnemi=GetNextObjectInArea(oArea);
        }
     } else
     {
//Le PNJ a deja un ennemi. Verifie s'il est mort.
     
if (GetIsDead(oEnnemiCible)) DeleteLocalObject(OBJECT_SELF,"EnnemiCible"); //L'ennemi est mort : preparation pour en chercher un autre
        
else
         {
//L'ennemi est encore vivant : verifie que la catapulte le vise.
         
float fDistVisee=GetLocalFloat(oCatapulte,"DistCible"); //Distance du tir actuellement règle
         
if (fDistVisee<10.0fDistVisee=10.0;
         
SetLocalFloat(oCatapulte,"DistCible",fDistVisee);
         
float fDistCible=GetDistanceBetween(oCatapulteoEnnemiCible); //Distance entre ennemi et catapulte
         
fDistEnnemi=fDistCible-fDistVisee//Distance entre ennemi et reglage de la cible de la catapulte
         
vector vEnnemi=GetPositionFromLocation(GetLocation(oEnnemiCible)); //Position de l'ennemi sur la carte
         
vector vCatapulte=GetPositionFromLocation(GetLocation(oCatapulte)); //Position de la catapulte sur la carte
         //Origine de la carte : point en bas a gauche.
         //float fOrigineX=vCatapulte.x; //Deplacement d'absysse vers la catapulte
         //float fOrigineY=vCatapulte.y; //Deplacement d'ordonnee vers la catapulte
         //Deplacement du point d'origine de la zone (en bas a gauche) pour le placer sur la catapulte.
         
float fEnnemiX=vEnnemi.x-vCatapulte.x//Absysse de la cible par rapport a la catapulte
         
float fEnnemiY=vEnnemi.y-vCatapulte.y//Ordonnee de la cible par rapport a la catapulte
         
float fCorrAngle=8.0//Valeur de la correction de l'erreur d'orientation
         
if (fDistCible>37.0fCorrAngle=fCorrAngle/2.0//nouvelle correction en fonction de la distance de la cible.
         
float fOrientEnnemi=VectorToAngle(Vector(fEnnemiX*cos(fDistCible), fEnnemiY*sin(fDistCible),0.0)); //Calcul de l'angle forme par la cible par rapport a la catapulte
         //Correction de l'angle de tir (bizarrement la catapulte tir a cote de la cible. Le code ci-dessus permet de remedier au probleme).
         
if ( ((fOrientEnnemi>=0.0) && (fOrientEnnemi<=90.0)) || ((fOrientEnnemi>=180.0) && (fOrientEnnemi<=270.0)) )
            {
            
fOrientEnnemi=fOrientEnnemi+fCorrAngle;
            
//SendMessageToPC(GetFirstPC(),GetName(OBJECT_SELF)+" / Correction d'angle +"+FloatToString(fCorrAngle,3,0)+"."); //Debug
            
}
         else
         if ( ((
fOrientEnnemi>=270.0) && (fOrientEnnemi<=360.0)) || ((fOrientEnnemi>=90.0) && (fOrientEnnemi<=180.0)) )
            {
            
fOrientEnnemi=fOrientEnnemi-fCorrAngle;
            
//SendMessageToPC(GetFirstPC(),GetName(OBJECT_SELF)+" / Correction d'angle +"+FloatToString(fCorrAngle,3,0)+"."); //Debug
            
}
         
float fAngle=fOrientEnnemi-GetFacing(oCatapulte); //Angle entre orientation (et la position par rapport a l'ennemi) de la catapulte et l'ennemi
         
int CmdCatap//Commande de la catapulte
         
CmdCatap=0//Charger/Tirer par defaut.
         //Reglage distance avec une petite marge pour que le tireur evite de regler la distance indefiniement.
         
if (fDistEnnemi>=0.0) { if (fDistEnnemi>=(IntToFloat(Random(300))/100)) CmdCatap=3; }
         if (
fDistEnnemi<=0.0) { if (-fDistEnnemi>=(IntToFloat(Random(300))/100)) CmdCatap=4; }
         
//Reglage orientation
         
if (abs(FloatToInt(fAngle))>=Random(5)) //Marge de reglage : evite que le PNJ règle indefiniement la catapulte
            
{
            if (
fAngle>=0.0)
             { if (
fAngle<=180.0CmdCatap=2; else CmdCatap=1; }
                 else
             { if (
fAngle<=-180.0CmdCatap=2; else CmdCatap=1; }
            }
 
         
//SendMessageToPC(GetFirstPC(),GetName(OBJECT_SELF)+" / - Angle entre catap et ennemi : / "+FloatToString(fOrientEnnemi-GetFacing(oCatapulte),3,0)+"/"); //Debug
 
         //Actions du tireur
         
switch(CmdCatap)
            {
            case 
1:
             {
//Tourner a droite
             
if (GetLocalInt(oCatapulte,"Commande")!=1SetLocalInt(OBJECT_SELF,"Levier",1);
             
SetLocalInt(oCatapulte,"Commande",1);
             
ReglerOrient(oCatapulteOBJECT_SELFfOrientEnnemi);
             break;
             }
            case 
2:
             {
//Tourner a gauche
             
if (GetLocalInt(oCatapulte,"Commande")!=2SetLocalInt(OBJECT_SELF,"Levier",1);
             
SetLocalInt(oCatapulte,"Commande",2);
             
ReglerOrient(oCatapulteOBJECT_SELFfOrientEnnemi);
             break;
             }
            case 
3:
             {
//Viser plus loin
             
if (GetLocalInt(oCatapulte,"Commande")!=3SetLocalInt(OBJECT_SELF,"Levier",1);
             
SetLocalInt(oCatapulte,"Commande",3);
             
ReglerDist(oCatapulte,OBJECT_SELF,fDistEnnemi);
             break;
             }
            case 
4:
             {
//Viser plus pres
             
if (GetLocalInt(oCatapulte,"Commande")!=4SetLocalInt(OBJECT_SELF,"Levier",1);
             
SetLocalInt(oCatapulte,"Commande",4);
             
ReglerDist(oCatapulte,OBJECT_SELF,fDistEnnemi);
             break;
             }
            default:
             {
//Charger la catapulte / Tirer sur l'ennemi
             
if (GetLocalInt(oCatapulte,"Commande")!=0SetLocalInt(OBJECT_SELF,"Levier",1);
             if (
GetLocalInt(OBJECT_SELF,"Levier"))
                {
                
AssignCommand(OBJECT_SELF,ActionInteractObject(oLevier));
                
fDelai=1.3;
                }
             
DeleteLocalInt(OBJECT_SELF,"Levier");
             
SetLocalInt(oCatapulte,"Commande",0);
             
DelayCommand(fDelaiAssignCommand(OBJECT_SELF,ActionInteractObject(oCatapulte)));
             break;
             }
            }
         }
     }

Catapulte controlable v2.0
Voici un petit mod de démo d'une bataille navale.

L'objet de cette démo : un Pnj voit un navire ennemi et va utiliser une catapulte pour lui tirer dessus. L'ennemi fait de même : bataille navale.

Le PJ peut prendre le contrôle de la catapulte et effectuer divers réglages via un dialogue : pivoter, viser plus loin, plus près, ...

Les scripts ont été entièrement refait par rapport à la version précédente.

Un système anti-blocage à été prévu. Dans certains cas, lors du réglage de la catapulte, il se peut que le PNJ ou le PJ reste bloqué, du coup, il ne peut plus rien faire. Si c'est le PJ qui est bloqué, un dialogue doit être établit avec un PNJ pour requérir son aide.

Sur la catapulte que le PJ peut utiliser dans cette démo, un mode administrateur à été mis en place pour modifier toutes les possibilités de contrôle.



http://aigleroyal2.neuf.fr/NWN1/DEMO_BatNav/DEMO_BatNav.jpg



Quelques règles :

L'arme de siège doit être de même faction (ou s'y approchant le plus) que celle de son utilisateur.

Pour simplifier :

- L'ennemi doit utiliser une arme de faction "Hostile".
- L'allié doit utiliser une arme de faction "Défenseur".

Pourquoi ? Parce que l'arme de siège va être considérée comme un lanceur de sort et le sort sera de même faction que son lanceur. Et dans NWN, on ne peut pas blesser son allié.


Objets et créatures personnalisés :

Les armes de siège :

Editer et copier une catapulte ou une baliste standard.
- Le tag de la catapulte doit contenir "catapult".
- Le tag de la baliste doit contenir "ballist".
- placer le script "pl_used" dans le OnUsed de l'objet.
- Cocher la case "Intrigue" de l'objet
- Cocher la case "Utilisable"
- Décocher la case "Inventaire"
- Changer la faction en fonction de qui va utiliser l'objet

La flamme d'impact (facultatif) :

Editer et copier une grande flame (effet visuel dans la liste des plaçables)
- Le ResRef blueprint doit être "plc_flamelarge2"
- Cocher la case "Intrigue" de l'objet

Le Pnj qui contrôle l'objet :

- Créer une créature personnalisée.
- Le tag doit contenir "catapultier"
- Placer le script "pnj_heartbeat" dans le OnHeartBeat du PNJ
- Placer le script "pnj_perception" dans le OnPerception du PNJ
- Placer le dialogue "dlg_catapultier".
- Editer les factions selon vos souhaits.


Utilisation de la catapulte :

Le premier qui utilise l'arme en devient le propriétaire. Si c'est vous, le PNJ ne touchera pas à la catapulte. Si c'est le PNJ le propriétaire, vous n'aurez pas le droit d'utiliser l'arme sauf si :
- Le propriétaire est mort
- Vous demandez le changement de propriétaire.



Les téléchargements :

Le module de démo.
Le erf de la zone (avec tous les scripts).
La flamme d'impact.
La catapulte amie.
La catapulte ennemie.
Le PNJ ennemi.
Le PNJ ami.


Le Pnj peut utiliser indifféremment une baliste ou une catapulte.

Le script est facilement adaptable à tout autre plaçable.
C'est sympa comme truc Ca peut donner des trucs intéressants une fois mis en contexte, par exemple des joueurs qui prennent part à des affrontements de grande ampleur (genre défendre un fort !).

Citation :
Publié par Holgadard
Et dans NWN, on ne peut pas blesser son allié.
Tu peux si le serveur est mis en mode full pvp je crois. Ou la zone. Bref je sais plus trop mais c'est possible.
Sinon tu peux ptêtre essayer de changer la faction de la catapulte ? je suis pas sûr que ça soit possible mais bon.



J'ai constaté un petit bug sinon : quand au début on traine un peu et que le PNJ prend les commandes de la catapulte, et que ensuite on lui parle pour reprendre la catapulte, et ben on peut pas utiliser la catapulte. Pourtant le pnj a bien enregistré parceque si je lui reparle il me propose de reprendre le contrôle (de la catapulte).
Merci.
Citation :
Publié par Taern
J'ai constaté un petit bug sinon : quand au début on traine un peu et que le PNJ prend les commandes de la catapulte, et que ensuite on lui parle pour reprendre la catapulte, et ben on peut pas utiliser la catapulte. Pourtant le pnj a bien enregistré parceque si je lui reparle il me propose de reprendre le contrôle (de la catapulte).
Ah, je vais voir ça. Merci de cette remarque.

J'ai vu aussi, qu'on peut mettre un plaçable sous forme de Navire Drow. Ça m'a fait germer l'idée de bataille navale un peu plus dynamique (placement aléatoire des navires ennemis - dans ce genre de concept, le tireur et la catapulte ennemis deviennent obsolètes, du moins pour la bataille navale).
Petite remarque que je n'est pas précisée : une petite notion de hasard à été incluse dans le script du PNJ, ce qui fait que l'issue de la bataille via catapultes est incertaine.

Projet également d'y introduire des tirs de test (on ne peut pas toujours viser juste du 1er coup !).

EDIT : Taern, je n'ai pas réussis à reproduire ton bug, ça marche bien chez moi . Par contre j'en ai un autre : flamme d'impact sur l'eau de mer, alors que cela ne devrai pas se produire.
Répondre

Connectés sur ce fil

 
1 connecté (0 membre et 1 invité) Afficher la liste détaillée des connectés