Aller au contenu


[Résolu]Destruction D'Objet D'Inventaire


  • Veuillez vous connecter pour répondre
3 réponses à ce sujet

#1 beeratwork

beeratwork

Posté 10 avril 2010 - 16:34

J'aimerais bien réussir à faire un script général permettant de détruire un objet :
- par exemple qui pourrait être invoqué
- par exemple qui ne contient aucun modèle 3D mais est utilisé pour obtenir un effet spécial (coup de poing enchanté, lanceur de sort, etc)
- par exemple qui ne peux pas être utilisé par le joueur
- par exemple qui comme il ne peux être rammassé, encombre la sauvegarde

Le premier script que j'avais fait est celui-ci :
ScriptName AARFSLSelfDisableOnDropAndPlayerScript
; Script d'objet // Object script
;
; Ce script sert à faire disparaître un objet jetté à terre ou ajouté au joueur. ; This script is used to destroy an object dropped on the ground or added to the player  ; L'arme est abandonnée // The weapon is dropped Begin OnDrop	RemoveMe End
; Si l'arme est ajoutée au joueur // If the weapon is added to the player
Begin OnAdd player
 RemoveMe
End
; Bug : le joueur s'en équippe // Bug : the player equip it
Begin OnEquip player
 RemoveMe
 MessageBox "Mauvais joueur ! SVP jouez correctement... Cet objet n'est pas pour vous !"
 ; MessageBox "Bad gamer ! Please play correctly... This object is not for you !"
End

Problèmes :
- le bloc Begin ondrop est foireux : risque de CTD en mode menu et aucun effet si un ennemi perd son épée (il est désarmé).
- l'objet n'est supprimé que s'il est ajouté au joueur (il le ramasse), si un compagnon le ramasse, lui, il aura l'objet

J'ai donc tenté d'améliorer ce script :
scn aaShehaiSelfDisableOnDeathScript  ; Script d'objet // Object script
short MustBeDestroy
short Dropped
ref RefContainer
ref RefCatcher

; Si l'arme est jetée // If the weapon is dropped
Begin OnDrop
 set MustBeDestroy to 1
End

; Si l'arme est ajoutée à un acteur // If the weapon is added to an actor
Begin OnAdd
 if (MustBeDestroy == 1)
  RemoveMe
 endif
End
; Bug : un acteur s'en équippe // Bug : an actor equip it
Begin OnEquip
 if (MustBeDestroy == 1)
  RemoveMe
 endif
End

Begin GameMode
 set RefContainer to GetContainer
 if (RefContainer <= 0)
  set MustBeDestroy to 1
  set RefCatcher to PlaceAtMe aaShehaiCreaNull 1
  RefCatcher.Disable
  RefCatcher.Kill
  Activate RefCatcher
 elseif (RefContainer > 0 && RefContainer.GetDead == 1)
  set MustBeDestroy to 1
  RemoveMe
 endif
 ; if ((Dropped == 1 || RefContainer <= 0) && MustBeDestroy == 0)
 ; elseif (Dropped == 1 || (RefContainer > 0 && (RefContainer.GetDead == 1 || RefContainer.GetIsCreature == 0 || RefContainer.IsActor == 0) && MustBeDestroy == 0)
 ; if (RefContainer != RefOldContainer)
 ; if (RefContainer != 0)
 ;  MessageBox "Removed"
 ;  RemoveMe
 ; elseif (RefContainer == 0 && RefOldContainer != 0)
 ;  MessageBox "On old"
 ;  RemoveMe RefOldContainer
 ; elseif (RefContainer == 0 && RefOldContainer == 0)
 ;  MessageBox "On player"
 ;  RemoveMe player
 ; endif
 ; set RefOldContainer to RefContainer
 ; endif
End
J'ai laissé les commentaires s'il y a des idées à reprendre. J'aurais bien voulu que ça fonctionne aussi avec une arme invoquée, en fait.

Pour explication :
MustBeDestroy est une variable qui sert à signale que l'objet doit être détruit.
RefCatcher est un attrapeur : en fait une créature qui me sert juste à attraper l'objet puis je la tue, comme la créature n'est pas une référence persistente, elle sera détruite avec l'épée (si elle la possède toujours) au bout de 3 jours. Et comme je la désactive, le joueur ne peu pas la voir et donc fouiller son inventaire ou se prendre les pieds dedans.

Quand l'objet n'est pas dans un container (RefCatcher = 0), je signale que l'objet doit être détruit et je le fait ramasser par l'attrapeur mort.
Si l'objet est dans un container mort, je retire l'objet. Donc normalement l'objet devrait être supprimé avant même que les mouches ne pondent sur l'attrapeur mort. Une épée scriptée ainsi et posée au sol dans une cellule initialement disparait sans qu'on ai eu le temps de le remarquer.

Le problème :
- Si un un acteur (et cela inclu le joueur) invoque l'épée, il peux l'utiliser.
- L'épée est en quest item, donc il est censé ne pas pouvoir la perdre et la fin du sort lui retire l'épée.
=> Oui, mais si le joueur ne perd pas l'épée, comment faire pour qu'un PNJ ou une créature ne la perde pas ?
- J'ai créé une nouvelle créature qui possède initialement cette épée. L'épée ne s'envole pas et la créature ne dispose pas du sort d'invocation. Cependant, à la mort de la créature qui est désarmée (car l'épée est un objet de quête ?), l'épée ne disparaît pas et "MustBeDestroy" vaut 1.
=> Comment supprimer un objet lorsqu'il quitte un inventaire, qu'il est jetté ou bien lorsque l'acteur est désarmé ?



Bon comme je suis content et que j'ai envie de me gratifier, je me reprend :"Comme je suis très intelligent"...J'ai trouvé une solution, cependant, je me demande si lorsque l'objet est à terre, je le transfère au joueur ou à ma créature invisible ? C'est-à-dire que si je le transfère au joueur, on va entendre un petit "slack" comme lorsqu'on ramasse un objet à terre. Ce n'est pas la cas avec la créature, mais je n'utilise pas de "CreateFullActorCopy" parceque l'objet est supprimé de l'inventaire de la créature et le script est sur l'objet... En fait ça veut dire que pour supprimer le clone de mon attrapeur créé avec "createfullactorcopy" je devrais utiliser "deletefullactorcopy", après ajout de l'objet, oui, mais là, j'ai risque de bug...enfin, y a peu être un moyen... bon, en attendant, je me demande si c'est mieux de créer une créature qu'on tue direct ou de transférer l'objet au joueur pour qu'il se supprime tout seul ?
ScriptName AARFSLSelfDisableOnDropAndPlayerScript
; Script d'objet // Object script;
; Ce script sert à faire disparaître un objet jetté à terre ou ajouté au joueur.
; This script is used to destroy an object dropped on the ground or added to the player
short MustBeDestroy
ref RefContainer
ref RefCatcher
float	timer

; Si l'arme est jetée ou donnée // If the weapon is dropped or given
Begin OnDrop
 set MustBeDestroy to 1
 set timer to 0.1
End

Begin GameMode
 set RefContainer to GetContainer
 if (RefContainer > 0)
 ; Si le container est mort ou qu'il n'est pas un acteur // If the container is dead or if it is not an actor
  if (MustBeDestroy == 0)
   if (RefContainer.GetDead == 1 || (RefContainer.GetIsCreature == 0 && RefContainer.IsActor == 0))
	set MustBeDestroy to 1
	set timer to 0.1
	RemoveMe
   endif
 ; Si l'arme doit être détruite et qu'elle est reprise // If the weapon must be destroyed and if it's picked
  else
   RemoveMe
  endif
 else
  if (MustBeDestroy == 0)
   set MustBeDestroy to 1
   set timer to 0.1
  else
   if (timer > 0)
	set timer to (timer - GetSecondsPassed)
   else
	Activate player
   endif
  endif
 endif
End

Modifié par beeratwork, 06 mai 2010 - 11:29.


#2 beeratwork

beeratwork

Posté 13 avril 2010 - 06:33

Je suis sous internet explorer... enfin, je vais pouvoir mettre le script de façon lisible ???
ScriptName AARFSLSelfDisableondropAndPlayerScript

; Script d'objet // Object script
;
; Ce script sert à faire disparaître un objet jetté à terre ou ajouté au joueur.
; This script is used to destroy an object dropped on the ground or added to the player

short MustBeDestroy
ref RefContainer
ref RefCatcher
float timer

; Si l'arme est jetée ou donnée // If the weapon is dropped or given

Begin OnDrop
 set MustBeDestroy to 1
 set timer to 0.1
End

Begin GameMode
 set RefContainer to GetContainer
 if (RefContainer > 0)
 ; Si le container est mort ou qu'il n'est pas un acteur // If the container is dead or if it is not an actor
  if (MustBeDestroy == 0)
   if (RefContainer.GetDead == 1 || (RefContainer.GetIsCreature == 0 && RefContainer.IsActor == 0))
	set MustBeDestroy to 1
	set timer to 0.1
	RemoveMe
   endif
 ; Si l'arme doit être détruite et qu'elle est reprise // If the weapon must be destroyed and if it's picked
  else
   RemoveMe
  endif
 else
  if (MustBeDestroy == 0)
   set MustBeDestroy to 1
   set timer to 0.1
  else
   if (timer > 0)
	set timer to (timer - GetSecondsPassed)
   else
	Activate player
   endif
  endif
 endif
End


#3 beeratwork

beeratwork

Posté 15 avril 2010 - 11:22

Je rencontre encore un petit problème que je n'ai pas vu tout de suite car j'ai d'abord testé ça avec une créature placée directement dans la cellule où je suis avec le TESC.

Si la créature est placée avc le TESC, elle est équipée de l'arme. Si la créature est placée près de vous à l'aide d'un activateur et via placeatme/createfullactorcopy, problème : le jeux n'a pas encore initialisé RefContainer et l'épée est supprimée à la création de la créature. Si on fait une action une seule fois pour mettre un "set refContainer to 1" avant les vérification et après le "set RefContainer to GetContainer", alors comme RefContainer vaut 0 à la création, puis qu'il passe à 1, ont fait le test pour vérifier si la créature est morte, et le jeu ne lui a pas encore donné vie puisqu'il est en train de la créer ! Donc il retire l'épée. J'ai testé ça avec des MsgBox m'affichant les valeurs et c'est effrayant.

Quelqu'un a une idée ?

#4 beeratwork

beeratwork

Posté 06 mai 2010 - 11:44

Bon, le problème est résolu et le script corrigé sera disponible à partir de farmerslife v6. Je n'ai pas pu contourner le fait que l'objet soit supprimé en étant ajouté au joueur car passer par une créature est succeptible de bug. Cela produit donc un petit bruit comme lorsque le joueur ramasse un objet, mais ce n'est pas important à côté d'un retour à windows ou d'une suppression échouée. Deplus, si l'objet est placé dans l'ID d'un acteur et que l'on utilise CreateFullActorCopy, il peut y avoir des problèmes.
Le script tel qu'il est écrit ici permet d'éviter que l'objet soit supprimé dès la création d'une référence ingame : en effet la référence construite in game à l'activation d'un autel piégé, par exemple, n'est pas encore initialisée, contrairement à une référence construite dans le TESC qui elle est déjà paramétrée et chargée au chargement de la cellule lorsque le joueur rentre dedans.

Donc le script peut-être utilisé sur des armes sans modèle 3D qui servent juste à donner des "coups de poing enchanté" ou bien à figurer une arme réellement invisible (pas de modèle donc pas de shader d'enchantement actif, mais ça n'empêche pas de faire des dégâts d'enchantement), ou bien à faire disparaître une arme invoquée au cas où son possesseur parviendrait à la perdre, etc. Le script peut aussi être utiliser sur des objets qui doivent s'autodétruire si le joueur les prend hors de leur coffre.

Le script corrigé :
scn AARFSLSelfDisableOnDropAndPlayerScript

; Script d'objet // Object script
;
; Ce script sert à faire disparaître un objet jetté à terre ou ajouté au joueur.
; Attention ! Si vous utilisez ce script sur un objet ajouté à une référence crée avec CreateFullActorCopy ! CreateFullActorCopy peut supprimer le script. Dans ce cas, après l'appel de CreateFullActorCopy, appeler une fonction puis ajouter l'objet au clone.
; This script is used to destroy an object dropped on the ground or added to the player.
; Warning ! If you use this script on an item created with createfullActorCopy ! CreateFullActorCopy can remove the script. In this case, after the call of createFullActorCopy, call another function and add the item to the clone.

short MustBeDestroy
short Initialisation
ref  RefContainer
float timer

; Si l'arme est jetée ou donnée // If the weapon is dropped or given
Begin OnDrop
 set MustBeDestroy to 1
 set timer to 0.1
End

Begin GameMode
; Acquisition du container à chaque exécution // Get the container for each run.
 set RefContainer to GetContainer

; Attendre 0.1s pour empêcher l'auto-destruction lors de l'initialisation sur un container (lorsque PlaceAtMe ou CreateFullActorCopy est utilisé).
; Wait 0.1s to stop self-destruction at the initialisation on a container (when PlaceAtMe or CreateFullActorCopy is used).
 if (Initialisation == 0)
  set Initialisation to 1
  set timer to 0.1
 elseif (Initialisation == 1)
  if (timer > 0)
   set timer to (timer - getSecondsPassed)
  else
   set Initialisation to 2
  endif
; Vérifier le container // Check the container
 elseif (Initialisation == 2)
 ; Dans un container // In a container
  if (RefContainer > 0)
  ; Si le container est mort ou qu'il n'est pas un acteur // If the container is dead or if it is not an actor
   if (MustBeDestroy == 0)
	if (RefContainer.GetDead == 1 || (RefContainer.GetIsCreature == 0 && RefContainer.IsActor == 0))
	 set MustBeDestroy to 1
	 set timer to 0.1
	 RemoveMe
	endif
  ; Si l'arme doit être détruite et qu'elle est reprise // If the weapon must be destroyed and if it's picked
   else
	RemoveMe
   endif
  else
  ; Détruire l'objet // Destroy the item
   if (MustBeDestroy == 0)
	set MustBeDestroy to 1
	set timer to 0.1
   else
	if (timer > 0)
	 set timer to (timer - GetSecondsPassed)
	else
	 Activate player
	endif
   endif
  endif
 endif
End





0 utilisateur(s) li(sen)t ce sujet

0 membre(s), 0 invité(s), 0 utilisateur(s) anonyme(s)