Day.png);">
Apprendre


Vous êtes
nouveau sur
Oniromancie?

Visite guidée
du site


Découvrir
RPG Maker


Apprendre
RPG Maker

Tutoriels
Guides
Making-of

Dans le
Forum

Section Entraide

Jeux: Clovers Quest / News: Le Miroir de Philéas / Jeux: Oui-Oui et le Chien Qui Saute / Jeux: Our forthcoming dreams / News: Les résultats du 4ème concours (...) / Chat

Bienvenue
visiteur !




publicité RPG Maker!

Statistiques

Liste des
membres


Contact

Mentions légales

304 connectés actuellement

31144498 visiteurs
depuis l'ouverture

1601 visiteurs
aujourd'hui



Barre de séparation

Partenaires

Indiexpo

Akademiya RPG Maker

Blog Alioune Fall

Fairy Tail Constellations

Le Comptoir Du clickeur

ConsoleFun

Leo-Games

Le Temple de Valor

Offgame

Tous nos partenaires

Devenir
partenaire



forums

Index du forum > Entraide > [RESOLU] [RMXP] Effet sonore si immunité à état


Wingan - posté le 10/03/2025 à 08:49:13 (18 messages postés)

❤ 0

Domaine concerné: script
Logiciel utilisé: RMXP
Bien le bonjour !

Petite demande de la part d'un amateur du Ruby : je souhaiterais donner une indication claire au joueur lorsqu'il essaie d'appliquer un état à un ennemi qui y est immunisé. Je pensais à un effet sonore.

J'ai essayé avec ChatGPT qui semble avoir de bonnes idée, mais la solution qu'il me propose génère toujours une erreur quelque part.
Manifestement, ça se joue dans Game_Battler_2, et plus particulièrement la portion suivante :

Portion de code : Tout sélectionner

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
 
def states_plus(plus_state_set)
    # 有効フラグをクリア
    effective = false
    # ループ (付加するステート)
    for i in plus_state_set
      # このステートが防御されていない場合
      unless self.state_guard?(i)
        # このステートがフルでなければ有効フラグをセット
        effective |= self.state_full?(i) == false
        # ステートが [抵抗しない] の場合
        if $data_states[i].nonresistance
          # ステート変化フラグをセット
          @state_changed = true
          # ステートを付加
          add_state(i)
        # このステートがフルではない場合
        elsif self.state_full?(i) == false
          # ステート有効度を確率に変換し、乱数と比較
          if rand(100) < [0,100,80,60,40,20,0][self.state_ranks[i]]
            # ステート変化フラグをセット
            @state_changed = true
            # ステートを付加
            add_state(i)
          end
        end
      end
    end
    # メソッド終了
    return effective
  end
 



L'IA m'a proposé une portion de code qui me paraît parfaitement logique, mais qui provoque une syntax error lorsque j'essaie de l'intégrer :

Portion de code : Tout sélectionner

1
2
3
4
5
6
7
8
9
10
11
 
if self.state_ranks[i] == 0
  # 💥 L'ennemi est immunisé, on joue un son d'échec
  $game_system.se_play($data_system.buzzer_se)
else
  # 🌀 Appliquer l'état selon les probabilités
  if rand(100) < [0,100,80,60,40,20,0][self.state_ranks[i]]
    add_state(i)
  end
end
 



Voilà. Si quelqu'un a une idée, ce serait super.
(Et ce serait encore plus super si je pouvais définir l'ID des états pour lesquels je veux que l'effet sonore se lance en cas d'immunité.)

Merci d'avance pour votre attention !


Semmy - posté le 10/03/2025 à 18:17:48 (29 messages postés) -

❤ 1

Éparpillée façon puzzle

Tu as bien inséré le code à la place des lignes 20 à 25 ? Fait attention il a retiré le @state_change = true.
Enlève les émojis de ses commentaires aussi. Je tenterais pas le diable.


Mack - posté le 10/03/2025 à 19:16:58 (2325 messages postés) - staff -

❤ 1

Par rapport à ce que j'ai vu ce matin, ça me parait correct d'un point de vue syntaxique, si tu colles au bon endroit, je vois pas trop pourquoi ça planterais.

Par contre, ça risque de pas marcher :F

En réorganisant un tout petit peu le code, ça donne ça :

Portion de code : Tout sélectionner

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
  #--------------------------------------------------------------------------
  # * State Change (+) Application
  #     plus_state_set  : State Change (+)
  #--------------------------------------------------------------------------
  def states_plus(plus_state_set)
    # Clear effective flag
    effective = false
    # Loop (added state)
    for i in plus_state_set
      # If this state is not guarded
      unless self.state_guard?(i)
        # Set effective flag if this state is not full
        effective |= self.state_full?(i) == false
        # If states offer [no resistance]
        if $data_states[i].nonresistance
          # Set state change flag
          @state_changed = true
          # Add a state
          add_state(i)
        # If this state is not full
        elsif self.state_full?(i) == false
          # Convert state effectiveness to probability,
          # compare to random numbers
          #p self.state_ranks[i]
          if self.state_ranks[i] == 6
            # 💥 L'ennemi est immunisé, on joue un son d'échec
            $game_system.se_play($data_system.buzzer_se)            
          elsif rand(100) < [0,100,80,60,40,20,0][self.state_ranks[i]]
            # Set state change flag
            @state_changed = true
            # Add a state
            add_state(i)
          end
        end
      end
    end
    # End Method
    return effective
  end



( A savoir que le p self.state_ranks commenté permet d'afficher une pop up avec la valeur de self.state_ranks, ce qui peut être très pratique pour faire des tests )

Et dans ce cas là, les ennemis ayant une résistance A dans un statut auront un petit bruit qui sera jouer si on essaye d'ajouter ce statut.

Grossièrement, c'est exactement ce que tu as mis, sauf que :
- Au lieu de faire un :

Portion de code : Tout sélectionner

1
2
3
4
5
6
7
if XXX
 
else
  if YYY
 
  end
end



J'ai simplement fait un :

Portion de code : Tout sélectionner

1
2
3
4
5
if XXX
 
elsif YYY
 
end



Ca fait exactement la même chose, juste ça prend moins de lignes :F.

- Et le second truc que j'ai changé, c'est :

Portion de code : Tout sélectionner

1
if self.state_ranks[i] == 6


Dans ton bout de code, tu avais mis 0.
Or, le tableau des statuts marche un peu bizarrement, il commence à 1, et pas 0.
Donc 6 = F, 5 = E, D= 4, ... A = 1
On peut le déduire grâce à cette ligne :

Portion de code : Tout sélectionner

1
elsif rand(100) < [0,100,80,60,40,20,0][self.state_ranks[i]]


Ce qu'elle fait est assez simple :
Dans la partie gauche du <, elle va simplement tirer un nombre entre 0 et 100 ( 99 ? ).
Dans la partie droite, on va regarder la valeur de self.state_ranks, qui correspond à la lettre affichée en BD. Or, on peut voir que le tableau contient 7 éléments au lieux de 6, donc déjà, on commence à 1 et pas à 0.
Ensuite, puisque on va tirer un nombre aléatoire entre 0 et 100, et qu'on va le comparer à la partie droite, que ce tableau contient les %age de résis des statuts, on peut en déduire que A = 1, B = 2, ... F= 6.
( Puisque A = je mets le statut dans tout les cas, peut importe la valeur que j'ai tiré à gauche, elle sera toujours plus basse que 100. Tandis que pour le F, c'est la valeur 0, donc impossible de mettre le statuts )

- J'ai aussi gardé le :

Portion de code : Tout sélectionner

1
            @state_changed = true


J'sais pas à quoi ça sert, mais je pense que c'est important :F

A savoir quand même, que ce son, il va être jouer au lancement du sort, pas au moment ou le "MISS" pop, ce qui peu être un peu étrange.

( Je prend note de tout les commentaires, même si je n'y répond pas )


Wingan - posté le 11/03/2025 à 07:31:13 (18 messages postés)

❤ 0

Et rebonjour !

Merci énormément pour ta réponse et ces explications détaillées ! C'est très pédagogique
Ahem, par contre, pour une raison qui m'échappe totalement... Je ne constate aucune différence avec ce script. Aucun effet sonore n'est joué, et quand je retire le # pour afficher p self.state_ranks, rien n'apparaît. Je me demande si je n'ai pas un script similaire prioritaire par rapport à Game_Battler_2 ?

De toute façon...
1 - Si l'effet sonore est censé être joué au lancement de l'attaque et non au moment du popup, en effet, ce n'est malheureusement pas extra.
2 - Ce n'est que quelques heures après avoir publié cette question que je me suis rendu compte que ce système ne marcherait pas pour mon projet en raison d'un choix de game design. J'ai certaines attaques, par exemple, qui infligent 3 effets de Poison différents en même temps : un puissant (pour les mobs et les personnages du joueur), un moyen (pour les ennemis forts) et un réduit (pour les boss). Chaque personnage/ennemi est donc nécessairement immunisé à 2 effets de Poison sur 3, et avec ce script, on entendrait l'effet d'immunité même si le personnage/ennemi subit le Poison contre lequel il n'est pas immunisé...

Donc je pense qu'on peut laisser couler, mais merci encore pour vos retours, je suis content d'en avoir appris un peu plus sur cette portion de script que je pourrais retoucher ne serait-ce que pour les probas des effets


Mack - posté le 11/03/2025 à 19:28:55 (2325 messages postés) - staff -

❤ 0

Par curiosité, j'ai voulu voir si en utilisant principalement ChatGPT pour faire ce que tu voulais, c'était possible, et je suis pas certain que pour quelque chose "d'aussi compliqué", ça soit une bonne idée.

Grossièrement, j'ai commencé par lui décrire ce que tu voulais faire, et il a commencé par me proposer de rajouter du code dans la def apply_state_changes de Scene_Battle.
Sauf que bien évidement, elle n'existe pas :F

Donc je lui dit, et il me réoriente vers la def add_state de Game_Battler.
Qui est appelé uniquement quand on ajoute un statuts ( donc que le check sur la proba est passé, donc ne sera jamais appelé si la cible résiste ). Donc déjà, ça part mal, mais en plus de ça, c'est appelé au tout début du lancement de l'attaque, donc ça ne va pas du tout :F

Je lui fait remarqué, et il me dit qu'effectivement, il dit de la merde, et me propose autre chose :F
A partir de là, il va me proposer plusieurs solutions ( def update_phase4_step3 et def update_phase4_step4 dans Scene_Battle ), qui ne sont pas aux bon moments !

Donc on continue à lui dire, et il finit par me trouver le bon endroit ( def update de Sprite_Battler).
Il va me pondre ce bout de code :

Portion de code : Tout sélectionner

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
STATUS_FAMILIES = {
  :poison => { :ids => [5, 6, 7], :sound => "Audio/SE/Poison_Resist" },
  :sleep  => { :ids => [8], :sound => "Audio/SE/Sleep_Resist" }
}
 
class Sprite_Battler
  alias update_with_resist_sound update
 
  def update
    was_damage_visible = self.damage_pop
    update_with_resist_sound
 
    # Vérifie si le popup de dégâts vient d'apparaître
    if self.damage_pop && !was_damage_visible
      target = @battler
      return if target.nil?
 
      # Vérifier si une famille entière de statuts a été résistée
      resisted_sounds = []
 
      if target.current_action != nil
        attempted_states = target.current_action.states_to_inflict
        STATUS_FAMILIES.each_key do |family|
          data = STATUS_FAMILIES[family]
          family_states = attempted_states & data[:ids]
 
          if !family_states.empty? && family_states.all? { |s_id| target.state_resist?(s_id) }
            resisted_sounds.push(data[:sound])
          end
        end
      end
 
      # Jouer un son si au moins une famille de statuts a été complètement résistée
      if !resisted_sounds.empty?
        Audio.se_play(resisted_sounds.first) # Joue le premier son trouvé
      end
    end
  end
end
 



A première vue, ça semble pas mal, il va regarder si à cette frame là il doit faire apparaitre des dégâts ( self.damage_pop ), puis appeler le standard de RMXP, et refaire un check pour savoir si entre temps ça à afficher un pop up ( if self.damage_pop && !was_damage_visible ).
Bon, déjà, là y a du caca :F

Portion de code : Tout sélectionner

1
self.damage_pop


N'existe pas, c'est :

Portion de code : Tout sélectionner

1
@battler.damage_pop


Pas bien grave, mais bon.

Ensuite, en regarder la vrai def update de Sprite_Battler, ligne 109 à 114, on peut voir ça :

Portion de code : Tout sélectionner

1
2
3
4
5
6
      if @battler.damage_pop
        damage(@battler.damage, @battler.critical)
        @battler.damage = nil
        @battler.critical = false
        @battler.damage_pop = false
      end


Donc grossièrement, on regarde si on doit afficher un pop up, puis on l'affiche, et on vient mettre à false le @battler.damage_pop pour ne pas l'afficher à la prochaine frame.

Donc si on regarde ce que ChatPGT nous à donné :

Portion de code : Tout sélectionner

1
if self.damage_pop && !was_damage_visible


Ça ne peut pas marcher.
Puisque self.damage_pop ( @battler.damage_pop ) ne peut pas être vrai après être passer dans le standard.


Ensuite, la plus grosse erreur de ChatGPT :

Portion de code : Tout sélectionner

1
2
3
target = @battler
...
target.current_action



Ça veut dire qu'il va regarder l'action effectué par le sprite sur lequel un pop up à eu lieu.
Donc si j'empoisonne mon enemy, il va pas regarder l'attaque de mon héros, mais l'attaque de l'ennemi, impossible d'avoir un résultat donc :F

Je lui fait remarqué, et il me dit rajouter ce bout de code :

Portion de code : Tout sélectionner

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class Game_Battler
  attr_accessor :last_attacker
 
  alias attack_effect_with_attacker_tracking attack_effect
  def attack_effect(attacker)
    @last_attacker = attacker # Stocke l’attaquant
    attack_effect_with_attacker_tracking(attacker)
  end
 
  alias skill_effect_with_attacker_tracking skill_effect
  def skill_effect(attacker, skill)
    @last_attacker = attacker # Stocke l’attaquant
    skill_effect_with_attacker_tracking(attacker, skill)
  end
 
  alias item_effect_with_attacker_tracking item_effect
  def item_effect(item)
    @last_attacker = $game_party.actors[0] if $game_party.actors.size > 0 # Suppose que c'est un objet utilisé par un allié
    item_effect_with_attacker_tracking(item)
  end
end


Et de remplacer target.current_action.states_to_inflict par :

Portion de code : Tout sélectionner

1
2
3
4
5
6
7
      attacker = @battler.last_attacker
      @battler.last_attacker = nil
      return if attacker.nil?
      
      target = @battler
...
attacker.current_action



On continue, pour récupérer la liste des statuts à infligé, il utilise ça :

Portion de code : Tout sélectionner

1
attempted_states = target.current_action.states_to_inflict


Evidemment, states_to_inflict n'existe pas :F


Ensuite, pour savoir si la cible est immunisé au statut, il utilise :

Portion de code : Tout sélectionner

1
target.state_resist?(s_id)


Qui n'existe pas non plus !


Au final, j'ai réussi à faire ce code là :

Portion de code : Tout sélectionner

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
 
# Tableau de familles de statuts.
#   Dans cet exemple, la famille "Poison" contient les status 2 et 3
#   Et la famille Sleep contient uniquement le statut 16
#   Si j'utilise un sort ( ou une arme ) qui va m'infliger les statuts 2,3, et 16
#   Sur un ennemi qui résiste au deux status de poison ( F aux statuts 2/3 )
#   Mais pas de résistance au sleep, j'aurais le son 001-System01 qui va se jouer.
#   Si mon ennemi resiste à un des statuts 2 ou 3, alors aucun son ne sera joué
#   Idem pour le sleep, si mon ennemi resiste au statut 16, le son 003-System03 sera joué.
# Si il résiste aux 3 statuts, 1 seul son sera joué, et ça sera le premier trouvé dans 
# STATUS_FAMILIES
 
 
STATUS_FAMILIES = {
  :poison => { :ids => [2,3], :sound => "Audio/SE/001-System01" },
  :sleep  => { :ids => [16], :sound => "Audio/SE/003-System03" }
}
 
 
class Game_Battler
  
  #--------------------------------------------------------------------------
  # * Public Instance Variables
  #--------------------------------------------------------------------------
  attr_reader   :current_action
  attr_accessor :last_attacker
 
  alias attack_effect_with_attacker_tracking attack_effect
  def attack_effect(attacker)
    @last_attacker = attacker # Stocke l’attaquant
    attack_effect_with_attacker_tracking(attacker)
  end
 
  alias skill_effect_with_attacker_tracking skill_effect
  def skill_effect(attacker, skill)
    @last_attacker = attacker # Stocke l’attaquant
    skill_effect_with_attacker_tracking(attacker, skill)
  end
 
  alias item_effect_with_attacker_tracking item_effect
  def item_effect(item)
    @last_attacker = $game_party.actors[0] if $game_party.actors.size > 0 # Suppose que c'est un objet utilisé par un allié
    item_effect_with_attacker_tracking(item)
  end
end
 
class Game_BattleAction
  def skill?
    return @skill_id > 0
  end
  
  def item?
    return @item_id > 0
  end
  
  def attack?
    return @basic == 0
  end
end
 
 
class Sprite_Battler
  alias update_with_resist_sound update
 
  def update
    
    if @battler
      was_damage_visible = @battler.damage_pop
    end
    
    update_with_resist_sound
 
    # Vérifie si le popup de dégâts vient d'apparaître
    if was_damage_visible && !@battler.damage_pop
      
      attacker = @battler.last_attacker
      @battler.last_attacker = nil
      return if attacker.nil?
      
      target = @battler
      
      # Récupération des statuts tentés par l'action actuelle
      attempted_states = []
      action = attacker.current_action
      if action != nil
                
        if action.skill?
          attempted_states = $data_skills[action.skill_id].plus_state_set
        elsif action.item?
          attempted_states = $data_items[action.item_id].plus_state_set
        elsif action.attack?
          attempted_states = attacker.plus_state_set
        end
      end
      
      return if attempted_states.empty? # Pas de statuts à vérifier
            
      # Vérifier si une famille entière de statuts a été résistée
      resisted_sounds = []
      STATUS_FAMILIES.each_key do |family|
        data = STATUS_FAMILIES[family]
        family_states = attempted_states & data[:ids]
 
        if !family_states.empty? && family_states.all? { |s_id| target.state_ranks[s_id] == 6 }
          resisted_sounds.push(data[:sound])
        end
      end
 
      # Jouer un son si au moins une famille de statuts a été complètement résistée
      if !resisted_sounds.empty?
        Audio.se_play(resisted_sounds.first) # Joue le premier son trouvé
      end
    end
  end
end
 



Tu remarqueras donc que y a quand même pas mal de trucs que j'ai du faire moi même, parce qu'il avait du mal à me sortir le code parfait :F
( Typiquement, il m'avait dit d'utiliser action.skill?/item?/attack?, qui n'existe pas, j'ai du les faire moi même )



Là, je ne fais que jouer un seul son, mais on pourrait très bien jouer tout les sons trouvé ( ça risque d'être le bordel :F ), ou bien jouer une animation paramétrable à la place du son ( ou pas d'ailleurs ).



Donc bref, en y allant à tâtons, tu peux arriver, surtout si tu comprends un peu le scripting, et que tu comprends ce que chatGPT essaye de faire, mais si t'y connais absolument rien je pense que c'est absolument pas utilisable.
Surement que sur des trucs bien plus simple ( modifier la taille d'une fenêtre, rajouter un champs de texte, ... ) ça doit le faire, mais sinon j'ai de gros doute :F

( Je prend note de tout les commentaires, même si je n'y répond pas )


Wingan - posté le 11/03/2025 à 21:24:32 (18 messages postés)

❤ 0

...
Alors.

Je réponds sous l'effet de l'excitation, mais... purée de brocolis, ça marche absolument nickel ! C'est incroyable !! Je suis sur ce projet depuis 2008 et j'ai ENFIN un moyen d'annoncer au joueur que l'ennemi est immunisé à une altération ! T'as pas idée à quel point je suis heureux, c'est une immense mise à jour de quality of life !!

Tous les tests fonctionnent pour l'instant, mais je vais pousser un peu plus pour vérifier s'il n'y a pas des conflits qui pourraient apparaître avec mes autres scripts. Mais franchement, tu as déjà toute ma gratitude ! Merci mille fois d'avoir pris ce temps pour rédiger ce script salvateur (et pour toutes les informations que tu as fournies, sacré boulot !)


Mack - posté le 12/03/2025 à 19:37:43 (2325 messages postés) - staff -

❤ 0

Pas de soucis ;)
Quand les tests seront bon pour toi, je te laisserais passer en résolu :)


A savoir aussi que j'ai "bêtement" fait ce que t'as demandé, on pourrait aller plus loin en affichant un pop avec une image spécifique pour chaque résistance, sur un morceau aléatoire du battler enemy, et qui disparaitrait au fur et a mesure, ou ce genre de truc !

( Je prend note de tout les commentaires, même si je n'y répond pas )


Wingan - posté le 12/03/2025 à 21:24:19 (18 messages postés)

❤ 0

Ouah, j'ai ouvert la boîte de Pandore, dis donc !

Puisque tu me le proposes si gentiment, à la limite, si tu pouvais faire en sorte que l'effet sonore soit accompagné d'un pop-up avec un texte du style "Immunité" (ou tout autre système permettant d'afficher du texte en parallèle de l'effet, via une image par exemple), ce serait très cool.

Je ne vais pas chercher à complexifier davantage, étant donné que tout ce que je voulais, c'était faire comprendre quand un ennemi est immunisé ou non.

J'aurais peut-être une dernière demande ensuite, mais on va déjà voir pour ce pop-up !

Au cas où, j'envoie le script édité pour mon projet :

Portion de code : Tout sélectionner

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
 
# Merci à Mack !
# Tableau de familles de statuts.
#   Dans cet exemple, la famille "Poison" contient les status 2 et 3
#   Et la famille Sleep contient uniquement le statut 16
#   Si j'utilise un sort ( ou une arme ) qui va m'infliger les statuts 2,3, et 16
#   Sur un ennemi qui résiste au deux status de poison ( F aux statuts 2/3 )
#   Mais pas de résistance au sleep, j'aurais le son 001-System01 qui va se jouer.
#   Si mon ennemi resiste à un des statuts 2 ou 3, alors aucun son ne sera joué
#   Idem pour le sleep, si mon ennemi resiste au statut 16, le son 003-System03 sera joué.
# Si il résiste aux 3 statuts, 1 seul son sera joué, et ça sera le premier trouvé dans 
# STATUS_FAMILIES
 
 
STATUS_FAMILIES = {
  :Poison => { :ids => [3,643,646], :sound => "Audio/SE/immu" },
  :Étourdissement  => { :ids => [2], :sound => "Audio/SE/immu" },
  :Sommeil  => { :ids => [7], :sound => "Audio/SE/immu" },
  :Cécité  => { :ids => [4], :sound => "Audio/SE/immu" },
  :Silence  => { :ids => [5], :sound => "Audio/SE/immu" },
  :Folie  => { :ids => [6,678], :sound => "Audio/SE/immu" },
  :Paralysie  => { :ids => [8], :sound => "Audio/SE/immu" },
  :Tétanie  => { :ids => [30], :sound => "Audio/SE/immu" },
  :Hémorragie  => { :ids => [17,644,648], :sound => "Audio/SE/immu" },
}
 
 
class Game_Battler
  
  #--------------------------------------------------------------------------
  # * Public Instance Variables
  #--------------------------------------------------------------------------
  attr_reader   :current_action
  attr_accessor :last_attacker
 
  alias attack_effect_with_attacker_tracking attack_effect
  def attack_effect(attacker)
    @last_attacker = attacker # Stocke l’attaquant
    attack_effect_with_attacker_tracking(attacker)
  end
 
  alias skill_effect_with_attacker_tracking skill_effect
  def skill_effect(attacker, skill)
    @last_attacker = attacker # Stocke l’attaquant
    skill_effect_with_attacker_tracking(attacker, skill)
  end
 
  alias item_effect_with_attacker_tracking item_effect
  def item_effect(item)
    @last_attacker = $game_party.actors[0] if $game_party.actors.size > 0 # Suppose que c'est un objet utilisé par un allié
    item_effect_with_attacker_tracking(item)
  end
end
 
class Game_BattleAction
  def skill?
    return @skill_id > 0
  end
  
  def item?
    return @item_id > 0
  end
  
  def attack?
    return @basic == 0
  end
end
 
 
class Sprite_Battler
  alias update_with_resist_sound update
 
  def update
    
    if @battler
      was_damage_visible = @battler.damage_pop
    end
    
    update_with_resist_sound
 
    # Vérifie si le popup de dégâts vient d'apparaître
    if was_damage_visible && !@battler.damage_pop
      
      attacker = @battler.last_attacker
      @battler.last_attacker = nil
      return if attacker.nil?
      
      target = @battler
      
      # Récupération des statuts tentés par l'action actuelle
      attempted_states = []
      action = attacker.current_action
      if action != nil
                
        if action.skill?
          attempted_states = $data_skills[action.skill_id].plus_state_set
        elsif action.item?
          attempted_states = $data_items[action.item_id].plus_state_set
        elsif action.attack?
          attempted_states = attacker.plus_state_set
        end
      end
      
      return if attempted_states.empty? # Pas de statuts à vérifier
            
      # Vérifier si une famille entière de statuts a été résistée
      resisted_sounds = []
      STATUS_FAMILIES.each_key do |family|
        data = STATUS_FAMILIES[family]
        family_states = attempted_states & data[:ids]
 
        if !family_states.empty? && family_states.all? { |s_id| target.state_ranks[s_id] == 6 }
          resisted_sounds.push(data[:sound])
        end
      end
 
      # Jouer un son si au moins une famille de statuts a été complètement résistée
      if !resisted_sounds.empty?
        Audio.se_play(resisted_sounds.first) # Joue le premier son trouvé
      end
    end
  end
end
 
 



Et encore merci, sincèrement


Mack - posté le 12/03/2025 à 22:14:07 (2325 messages postés) - staff -

❤ 0

Portion de code : Tout sélectionner

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
 
# Tableau de familles de statuts.
#   Dans cet exemple, la famille "Poison" contient les status 2 et 3
#   Et la famille Sleep contient uniquement le statut 16
#   Si j'utilise un sort ( ou une arme ) qui va m'infliger les statuts 2,3, et 16
#   Sur un ennemi qui résiste au deux status de poison ( F aux statuts 2/3 )
#   Mais pas de résistance au sleep, j'aurais le son 001-System01 qui va se jouer.
#   Si mon ennemi resiste à un des statuts 2 ou 3, alors aucun son ne sera joué
#   Idem pour le sleep, si mon ennemi resiste au statut 16, le son 003-System03 sera joué.
# Si il résiste aux 3 statuts, 1 seul son sera joué, et ça sera le premier trouvé dans 
# STATUS_FAMILIES
 
 
STATUS_FAMILIES = {
  :poison => { :ids => [2,3], :sound => "Audio/SE/001-System01", :picture => "poison" },
  :sleep  => { :ids => [16], :sound => "Audio/SE/003-System03" , :picture => "sleep" }
}
 
# Puissance de la disparation de l'image
STATE_FRAME = 5
 
class Game_Battler
  
  #--------------------------------------------------------------------------
  # * Public Instance Variables
  #--------------------------------------------------------------------------
  attr_reader   :current_action
  attr_accessor :last_attacker
 
  alias attack_effect_with_attacker_tracking attack_effect
  def attack_effect(attacker)
    @last_attacker = attacker # Stocke l’attaquant
    attack_effect_with_attacker_tracking(attacker)
  end
 
  alias skill_effect_with_attacker_tracking skill_effect
  def skill_effect(attacker, skill)
    @last_attacker = attacker # Stocke l’attaquant
    skill_effect_with_attacker_tracking(attacker, skill)
  end
 
  alias item_effect_with_attacker_tracking item_effect
  def item_effect(item)
    @last_attacker = $game_party.actors[0] if $game_party.actors.size > 0 # Suppose que c'est un objet utilisé par un allié
    item_effect_with_attacker_tracking(item)
  end
end
 
class Game_BattleAction
  def skill?
    return @skill_id > 0
  end
  
  def item?
    return @item_id > 0
  end
  
  def attack?
    return @basic == 0
  end
end
 
 
class Sprite_Battler
  
  alias initialize_with_resist_sound initialize
  
  def initialize(viewport, battler = nil)
    initialize_with_resist_sound(viewport, battler)
    
    # On va venir créer une liste qui contiendra tout nos Sprite
    @pop_up_res = []
    
  end
  
  alias update_with_resist_sound update
 
  def update
    
    if @battler
      was_damage_visible = @battler.damage_pop
    end
    
    update_with_resist_sound
 
    # Vérifie si le popup de dégâts vient d'apparaître
    if was_damage_visible && !@battler.damage_pop
      
      attacker = @battler.last_attacker
      @battler.last_attacker = nil
      return if attacker.nil?
      
      target = @battler
      
      # Récupération des statuts tentés par l'action actuelle
      attempted_states = []
      action = attacker.current_action
      if action != nil
                
        if action.skill?
          attempted_states = $data_skills[action.skill_id].plus_state_set
        elsif action.item?
          attempted_states = $data_items[action.item_id].plus_state_set
        elsif action.attack?
          attempted_states = attacker.plus_state_set
        end
      end
      
      return if attempted_states.empty? # Pas de statuts à vérifier
            
      # Vérifier si une famille entière de statuts a été résistée
      resisted_sounds = []
      STATUS_FAMILIES.each_key do |family|
        data = STATUS_FAMILIES[family]
        family_states = attempted_states & data[:ids]
 
        if !family_states.empty? && family_states.all? { |s_id| target.state_ranks[s_id] == 6 }
          resisted_sounds.push(data[:sound])
          
          # Point tout en haut à gauche
          x = self.y - @width
          y = self.x - @width
          
          # On ajoute un peu d'aléatoire
          x += rand(@width)
          y += rand(@width)
          
          # Et on créer notre sprite que l'on ajoute dans la liste
          p = Sprite_StateR.new(data[:picture], x, y)
          @pop_up_res.push(p)
          
        end
      end
 
      # Jouer un son si au moins une famille de statuts a été complètement résistée
      if !resisted_sounds.empty?
        Audio.se_play(resisted_sounds.first) # Joue le premier son trouvé
      end
    end
    
    # On va venir update tout les sprites
    for s in @pop_up_res
      # Et s'ils ont été disposed? ( effacé ), on vient les supprimer de la liste
      if (s.disposed?())
        @pop_up_res.delete(s)
        s = nil
      else
        # Sinon on met à jour
        s.update()
      end
    end
    
  end
  
  # Quand le sprite principal est disposed, il faut aussi disposed ceux de la liste
  # Sinon, en fin de combat on pourrait toujours avoir nos image, alors qu'on est sur la map
  
  alias dispose_with_resist_sound dispose
  
  def dispose
      for s in @pop_up_res
        @pop_up_res.delete(s)
        s.dispose()
        s = nil
      end
     dispose_with_resist_sound
  end
end
 
 
# Pour la classe, c'est un truc tout basique :
class Sprite_StateR < Sprite
  # On va créer son bitmap depuis une picture, dont le nom est passé en paramétre
  #   ( Donc depuis le tableau STATUS_FAMILIES )
  # On change la position X/Y pour celle qu'on donne en param, et on gère la OX/OY
  # ( Origin X, Origin Y, le point de "centre" )
  def initialize(pic_name, x, y)
    super()
    self.bitmap = RPG::Cache.picture(pic_name)
    self.x = x
    self.y = y
    @width = bitmap.width
    @height = bitmap.height
    self.ox = @width / 2
    self.oy = @height / 2
  end
  
  # A chaque update, on va faire que l'oppacité diminue, et si elle attend 0,
  # On efface le sprite
  def update
    self.opacity -= STATE_FRAME
    if self.opacity == 0
      dispose()
    end
  end
    
  # Si on efface le sprite, on vient effacer son bitmap
  def dispose
    if self.bitmap != nil
      self.bitmap.dispose
    end
    super
  end
  
end
  
 



J'ai fait un truc un peu basique, ça va venir afficher une image selon ce que tu auras configurer, à peu près sur le sprite de la cible.
Le sprite va disparaitre tout seul, et surtout, tu peux avoir plusieurs sprites en même temps ( dans mon exemple, si j'inflige poison + sleep, mais que la cible résiste aux 2, j'ai 1 son, mais 2 images )

Je pense que le placement complétement aléatoire sur le sprite de la cible, c'est un peu casse gueule, on pourrait avoir plusieurs icones affiché au même endroit, ou ce manger les une les autres.
Sur ce système de placement, je te laisse voir un peu toi même ce que tu veux faire, j'te laisse essayer des trucs ( avec ChatGPT, y a moyen de tirer quelque chose je pense )

Et si jamais tu galères trop, hésite pas à reposter :)

( Je prend note de tout les commentaires, même si je n'y répond pas )


Wingan - posté le 12/03/2025 à 22:25:13 (18 messages postés)

❤ 0

Je... ne m'attendais pas à recevoir une réponse si vite. Sur le papier, ça a l'air excellentissime, surtout si tu as réussi à gérer l'apparition de sprites distincts malgré plusieurs états en une seule attaque !
Je testerai ça demain, j'ai trop hâte ! Merci beaucoup (encore !)


Wingan - posté le 13/03/2025 à 11:35:22 (18 messages postés)

❤ 0

Bien, j'ai fait plein de tests et me suis servi de ChatGPT pour gérer cette histoire de placement, mais aussi pour limiter ces effets aux Battlers ennemis (pour diverses raisons).

Tout fonctionne parfaitement ! Voici la portion de code que j'ai un peu retouchée. Je vais sans doute bidouiller encore un peu les coordonnées, mais c'est pas trop mal pour l'instant avec des icônes en 28*28, quelle que soit la taille du Battler.

Portion de code : Tout sélectionner

1
2
3
4
5
6
7
8
9
 
        if !family_states.empty? && family_states.all? { |s_id| target.state_ranks[s_id] == 6 }
          return unless target.is_a?(Game_Enemy) #ennemis uniquement
          resisted_sounds.push(data[:sound])
          
          # Point tout en haut à gauche
          x = self.x + (-40 + rand(70))
          y = self.y - 125 - (-60 + rand(60))
 



Et au cas où ça intéresserait quelqu'un, voici le code entier (avec les retouches liées à mon projet) :

Portion de code : Tout sélectionner

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
 
# Merci à Mack !
# Tableau de familles de statuts.
#   Dans cet exemple, la famille "Poison" contient les status 2 et 3
#   Et la famille Sleep contient uniquement le statut 16
#   Si j'utilise un sort ( ou une arme ) qui va m'infliger les statuts 2,3, et 16
#   Sur un ennemi qui résiste au deux status de poison ( F aux statuts 2/3 )
#   Mais pas de résistance au sleep, j'aurais le son 001-System01 qui va se jouer.
#   Si mon ennemi resiste à un des statuts 2 ou 3, alors aucun son ne sera joué
#   Idem pour le sleep, si mon ennemi resiste au statut 16, le son 003-System03 sera joué.
# Si il résiste aux 3 statuts, 1 seul son sera joué, et ça sera le premier trouvé dans 
# STATUS_FAMILIES
 
 
STATUS_FAMILIES = {
  :Poison => { :ids => [3,643,646], :sound => "Audio/SE/immu", :picture => "poison" },
  :Étourdissement  => { :ids => [2], :sound => "Audio/SE/immu", :picture => "étourdissement" },
  :Sommeil  => { :ids => [7], :sound => "Audio/SE/immu", :picture => "sommeil" },
  :Cécité  => { :ids => [4], :sound => "Audio/SE/immu", :picture => "cécité" },
  :Silence  => { :ids => [5], :sound => "Audio/SE/immu", :picture => "silence" },
  :Folie  => { :ids => [6,678], :sound => "Audio/SE/immu", :picture => "folie" },
  :Paralysie  => { :ids => [8], :sound => "Audio/SE/immu", :picture => "paralysie" },
  :Tétanie  => { :ids => [30], :sound => "Audio/SE/immu", :picture => "tétanie" },
  :Hémorragie  => { :ids => [17,644,648], :sound => "Audio/SE/immu", :picture => "hémorragie" }
}
 
 
# Puissance de la disparation de l'image
STATE_FRAME = 2
 
class Game_Battler
  
  #--------------------------------------------------------------------------
  # * Public Instance Variables
  #--------------------------------------------------------------------------
  attr_reader   :current_action
  attr_accessor :last_attacker
 
  alias attack_effect_with_attacker_tracking attack_effect
  def attack_effect(attacker)
    @last_attacker = attacker # Stocke l’attaquant
    attack_effect_with_attacker_tracking(attacker)
  end
 
  alias skill_effect_with_attacker_tracking skill_effect
  def skill_effect(attacker, skill)
    @last_attacker = attacker # Stocke l’attaquant
    skill_effect_with_attacker_tracking(attacker, skill)
  end
 
  alias item_effect_with_attacker_tracking item_effect
  def item_effect(item)
    @last_attacker = $game_party.actors[0] if $game_party.actors.size > 0 # Suppose que c'est un objet utilisé par un allié
    item_effect_with_attacker_tracking(item)
  end
end
 
class Game_BattleAction
  def skill?
    return @skill_id > 0
  end
  
  def item?
    return @item_id > 0
  end
  
  def attack?
    return @basic == 0
  end
end
 
 
class Sprite_Battler
  
  alias initialize_with_resist_sound initialize
  
  def initialize(viewport, battler = nil)
    initialize_with_resist_sound(viewport, battler)
    
    # On va venir créer une liste qui contiendra tout nos Sprite
    @pop_up_res = []
    
  end
  
  alias update_with_resist_sound update
 
  def update
    
    if @battler
      was_damage_visible = @battler.damage_pop
    end
    
    update_with_resist_sound
 
    # Vérifie si le popup de dégâts vient d'apparaître
    if was_damage_visible && !@battler.damage_pop
      
      attacker = @battler.last_attacker
      @battler.last_attacker = nil
      return if attacker.nil?
      
      target = @battler
      
      # Récupération des statuts tentés par l'action actuelle
      attempted_states = []
      action = attacker.current_action
      if action != nil
                
        if action.skill?
          attempted_states = $data_skills[action.skill_id].plus_state_set
        elsif action.item?
          attempted_states = $data_items[action.item_id].plus_state_set
        elsif action.attack?
          attempted_states = attacker.plus_state_set
        end
      end
      
      return if attempted_states.empty? # Pas de statuts à vérifier
            
      # Vérifier si une famille entière de statuts a été résistée
      resisted_sounds = []
      STATUS_FAMILIES.each_key do |family|
        data = STATUS_FAMILIES[family]
        family_states = attempted_states & data[:ids]
 
        if !family_states.empty? && family_states.all? { |s_id| target.state_ranks[s_id] == 6 }
          return unless target.is_a?(Game_Enemy) #ennemis uniquement
          resisted_sounds.push(data[:sound])
          
          # Point tout en haut à gauche
          x = self.x + (-40 + rand(70))
          y = self.y - 125 - (-60 + rand(60))
          
          # Et on créer notre sprite que l'on ajoute dans la liste
          p = Sprite_StateR.new(data[:picture], x, y)
          @pop_up_res.push(p)
          
        end
      end
 
      # Jouer un son si au moins une famille de statuts a été complètement résistée
      if !resisted_sounds.empty?
        Audio.se_play(resisted_sounds.first) # Joue le premier son trouvé
      end
    end
    
    # On va venir update tout les sprites
    for s in @pop_up_res
      # Et s'ils ont été disposed? ( effacé ), on vient les supprimer de la liste
      if (s.disposed?())
        @pop_up_res.delete(s)
        s = nil
      else
        # Sinon on met à jour
        s.update()
      end
    end
    
  end
  
  # Quand le sprite principal est disposed, il faut aussi disposed ceux de la liste
  # Sinon, en fin de combat on pourrait toujours avoir nos image, alors qu'on est sur la map
  
  alias dispose_with_resist_sound dispose
  
  def dispose
      for s in @pop_up_res
        @pop_up_res.delete(s)
        s.dispose()
        s = nil
      end
     dispose_with_resist_sound
  end
end
 
 
# Pour la classe, c'est un truc tout basique :
class Sprite_StateR < Sprite
  # On va créer son bitmap depuis une picture, dont le nom est passé en paramétre
  #   ( Donc depuis le tableau STATUS_FAMILIES )
  # On change la position X/Y pour celle qu'on donne en param, et on gère la OX/OY
  # ( Origin X, Origin Y, le point de "centre" )
  def initialize(pic_name, x, y)
    super()
    self.bitmap = RPG::Cache.picture(pic_name)
    self.x = x
    self.y = y
    @width = bitmap.width
    @height = bitmap.height
    self.ox = @width / 2
    self.oy = @height / 2
  end
  
  # A chaque update, on va faire que l'oppacité diminue, et si elle attend 0,
  # On efface le sprite
  def update
    self.opacity -= STATE_FRAME
    if self.opacity == 0
      dispose()
    end
  end
    
  # Si on efface le sprite, on vient effacer son bitmap
  def dispose
    if self.bitmap != nil
      self.bitmap.dispose
    end
    super
  end
  
end
  
 
 



La mission est accomplie et le résultat dépasse de loin mes attentes. Encore merci pour tous tes efforts, tant dans la création du script que dans les explications. C'est vraiment un immense apport pour mon projet, et ça me rend franchement content :D

Sujet résolu !


Mack - posté le 13/03/2025 à 17:16:14 (2325 messages postés) - staff -

❤ 0

Parfait :)


Attention par contre au return unless, ça va empêcher l'exécution de toute la partie suivante.


Dans ton cas, c'est pas gênant du tout, par contre, imaginons que dans le même script, au niveau de la ligne :

Portion de code : Tout sélectionner

1
2
    # On va venir update tout les sprites
    for s in @pop_up_res


( 146 / 147 )

Le code ne sera pas lu. En plus, à ce niveau là, tu est dans une boucle ( STATUS_FAMILIES.each_key do ), et je trouve ça pas très propre de quitter la boucle comme ça :F ( Mais d'un point de vue technique, ça marche parfaitement ^^ )
De même, là on fait beaucoup de calcul, qui au final se trouve inutile, puisque la cible n'est pas un ennemi ( toute la partie calcul de l'attaquant, calcul de l'action, ..., bref, la quasi intégralité du script jusqu'à ta condition :F ).

De plus, la partie d'après sert uniquement à update l'animation de l'image. Dans ton cas on s'en que pour la résistance, mais par exemple, tu pourrais rajouter une animation lors d'un coup critique en réutilisant le système d'animation, et si tu gardes ton return unless à cet, l'animation ne sera jamais mise à jour

En soit, c'est pas grave, mais personnellement, à la ligne 96 :

Portion de code : Tout sélectionner

1
   if was_damage_visible && !@battler.damage_pop


J'aurais simplement ajouter ta condition :

Portion de code : Tout sélectionner

1
   if was_damage_visible && !@battler.damage_pop && target.is_a?(Game_Enemy)


Comme ça, si on a pas un ennemi en face, on ne fait rien :)

( Je prend note de tout les commentaires, même si je n'y répond pas )


Wingan - posté le 13/03/2025 à 20:43:19 (18 messages postés)

❤ 0

Merci pour ce retour ! J'ai remplacé la ligne 96 par ta proposition, mais j'ai un message d'erreur qui apparaît lorsque j'essaie d'appliquer un état :

line 96: NameError occurred
undefined local variable or method 'target' for #<Sprite_Battler:0x102x80d8>

Une petite idée ?
Dans le pire des cas, si jamais on ne trouve pas de réelle solution, je peux retirer cette portion censée empêcher les sons/animations du côté des personnages, car je ne crois pas avoir un seul perso 100 % immunisé à un statut. Mais dans le doute...


Mack - posté le 13/03/2025 à 21:28:20 (2325 messages postés) - staff -

❤ 0

Ah oui, petite erreur de ma part, j'ai oublié de remplacer le target par @battler

( Je prend note de tout les commentaires, même si je n'y répond pas )


Wingan - posté le 14/03/2025 à 06:05:12 (18 messages postés)

❤ 0

En effet, ça a l'air d'aller mieux :)
Je poste la dernière version du script qui, donc, émet un effet sonore et fait apparaître un sprite quelques secondes lorsque l'ennemi est immunisé à un état de notre choix, défini dans les familles au début du script :

Merci, ô grand maître du Ruby !

Portion de code : Tout sélectionner

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
 
 
# Merci à Mack !
# Tableau de familles de statuts.
#   Dans cet exemple, la famille "Poison" contient les status 2 et 3
#   Et la famille Sleep contient uniquement le statut 16
#   Si j'utilise un sort ( ou une arme ) qui va m'infliger les statuts 2,3, et 16
#   Sur un ennemi qui résiste au deux status de poison ( F aux statuts 2/3 )
#   Mais pas de résistance au sleep, j'aurais le son 001-System01 qui va se jouer.
#   Si mon ennemi resiste à un des statuts 2 ou 3, alors aucun son ne sera joué
#   Idem pour le sleep, si mon ennemi resiste au statut 16, le son 003-System03 sera joué.
# Si il résiste aux 3 statuts, 1 seul son sera joué, et ça sera le premier trouvé dans 
# STATUS_FAMILIES
 
 
STATUS_FAMILIES = {
  :Poison => { :ids => [3,643,646], :sound => "Audio/SE/immu", :picture => "poison" },
  :Étourdissement  => { :ids => [2], :sound => "Audio/SE/immu", :picture => "étourdissement" },
  :Sommeil  => { :ids => [7], :sound => "Audio/SE/immu", :picture => "sommeil" },
  :Cécité  => { :ids => [4], :sound => "Audio/SE/immu", :picture => "cécité" },
  :Silence  => { :ids => [5], :sound => "Audio/SE/immu", :picture => "silence" },
  :Folie  => { :ids => [6,678], :sound => "Audio/SE/immu", :picture => "folie" },
  :Paralysie  => { :ids => [8], :sound => "Audio/SE/immu", :picture => "paralysie" },
  :Tétanie  => { :ids => [30], :sound => "Audio/SE/immu", :picture => "tétanie" },
  :Hémorragie  => { :ids => [17,644,648], :sound => "Audio/SE/immu", :picture => "hémorragie" }
}
 
 
# Puissance de la disparation de l'image
STATE_FRAME = 2
 
class Game_Battler
  
  #--------------------------------------------------------------------------
  # * Public Instance Variables
  #--------------------------------------------------------------------------
  attr_reader   :current_action
  attr_accessor :last_attacker
 
  alias attack_effect_with_attacker_tracking attack_effect
  def attack_effect(attacker)
    @last_attacker = attacker # Stocke l’attaquant
    attack_effect_with_attacker_tracking(attacker)
  end
 
  alias skill_effect_with_attacker_tracking skill_effect
  def skill_effect(attacker, skill)
    @last_attacker = attacker # Stocke l’attaquant
    skill_effect_with_attacker_tracking(attacker, skill)
  end
 
  alias item_effect_with_attacker_tracking item_effect
  def item_effect(item)
    @last_attacker = $game_party.actors[0] if $game_party.actors.size > 0 # Suppose que c'est un objet utilisé par un allié
    item_effect_with_attacker_tracking(item)
  end
end
 
class Game_BattleAction
  def skill?
    return @skill_id > 0
  end
  
  def item?
    return @item_id > 0
  end
  
  def attack?
    return @basic == 0
  end
end
 
 
class Sprite_Battler
  
  alias initialize_with_resist_sound initialize
  
  def initialize(viewport, battler = nil)
    initialize_with_resist_sound(viewport, battler)
    
    # On va venir créer une liste qui contiendra tout nos Sprite
    @pop_up_res = []
    
  end
  
  alias update_with_resist_sound update
 
  def update
    
    if @battler
      was_damage_visible = @battler.damage_pop
    end
    
    update_with_resist_sound
 
    # Vérifie si le popup de dégâts vient d'apparaître
    if was_damage_visible && !@battler.damage_pop && @battler.is_a?(Game_Enemy)
      
      attacker = @battler.last_attacker
      @battler.last_attacker = nil
      return if attacker.nil?
      
      target = @battler
      
      # Récupération des statuts tentés par l'action actuelle
      attempted_states = []
      action = attacker.current_action
      if action != nil
                
        if action.skill?
          attempted_states = $data_skills[action.skill_id].plus_state_set
        elsif action.item?
          attempted_states = $data_items[action.item_id].plus_state_set
        elsif action.attack?
          attempted_states = attacker.plus_state_set
        end
      end
      
      return if attempted_states.empty? # Pas de statuts à vérifier
            
      # Vérifier si une famille entière de statuts a été résistée
      resisted_sounds = []
      STATUS_FAMILIES.each_key do |family|
        data = STATUS_FAMILIES[family]
        family_states = attempted_states & data[:ids]
 
        if !family_states.empty? && family_states.all? { |s_id| target.state_ranks[s_id] == 6 }
          resisted_sounds.push(data[:sound])
          
          # Point tout en haut à gauche
          x = self.x + (-40 + rand(70))
          y = self.y - 125 - (-60 + rand(60))
          
          # Et on créer notre sprite que l'on ajoute dans la liste
          p = Sprite_StateR.new(data[:picture], x, y)
          @pop_up_res.push(p)
          
        end
      end
 
      # Jouer un son si au moins une famille de statuts a été complètement résistée
      if !resisted_sounds.empty?
        Audio.se_play(resisted_sounds.first) # Joue le premier son trouvé
      end
    end
    
    # On va venir update tout les sprites
    for s in @pop_up_res
      # Et s'ils ont été disposed? ( effacé ), on vient les supprimer de la liste
      if (s.disposed?())
        @pop_up_res.delete(s)
        s = nil
      else
        # Sinon on met à jour
        s.update()
      end
    end
    
  end
  
  # Quand le sprite principal est disposed, il faut aussi disposed ceux de la liste
  # Sinon, en fin de combat on pourrait toujours avoir nos image, alors qu'on est sur la map
  
  alias dispose_with_resist_sound dispose
  
  def dispose
      for s in @pop_up_res
        @pop_up_res.delete(s)
        s.dispose()
        s = nil
      end
     dispose_with_resist_sound
  end
end
 
 
# Pour la classe, c'est un truc tout basique :
class Sprite_StateR < Sprite
  # On va créer son bitmap depuis une picture, dont le nom est passé en paramétre
  #   ( Donc depuis le tableau STATUS_FAMILIES )
  # On change la position X/Y pour celle qu'on donne en param, et on gère la OX/OY
  # ( Origin X, Origin Y, le point de "centre" )
  def initialize(pic_name, x, y)
    super()
    self.bitmap = RPG::Cache.picture(pic_name)
    self.x = x
    self.y = y
    @width = bitmap.width
    @height = bitmap.height
    self.ox = @width / 2
    self.oy = @height / 2
  end
  
  # A chaque update, on va faire que l'oppacité diminue, et si elle attend 0,
  # On efface le sprite
  def update
    self.opacity -= STATE_FRAME
    if self.opacity == 0
      dispose()
    end
  end
    
  # Si on efface le sprite, on vient effacer son bitmap
  def dispose
    if self.bitmap != nil
      self.bitmap.dispose
    end
    super
  end
  
end
  
 
 
 



Index du forum > Entraide > [RESOLU] [RMXP] Effet sonore si immunité à état

repondre up

Suite à de nombreux abus, le post en invités a été désactivé. Veuillez vous inscrire si vous souhaitez participer à la conversation.

Haut de page

Merci de ne pas reproduire le contenu de ce site sans autorisation.
Contacter l'équipe - Mentions légales

Plan du site

Communauté: Accueil | Forum | Chat | Commentaires | News | Flash-news | Screen de la semaine | Sorties | Tests | Gaming-Live | Interviews | Galerie | OST | Blogs | Recherche
Apprendre: Visite guidée | RPG Maker 95 | RPG Maker 2003 | RPG Maker XP | RPG Maker VX | RPG Maker MV | Tutoriels | Guides | Making-of
Télécharger: Programmes | Scripts/Plugins | Ressources graphiques / sonores | Packs de ressources | Midis | Eléments séparés | Sprites
Jeux: Au hasard | Notre sélection | Sélection des membres | Tous les jeux | Jeux complets | Jouables en ligne | Le cimetière | RPG Maker 95 | RPG Maker 2000 | RPG Maker 2003 | RPG Maker XP | RPG Maker VX | RPG Maker VX Ace | RPG Maker MV | Autres | Proposer
Ressources RPG Maker 2000/2003: Chipsets | Charsets | Panoramas | Backdrops | Facesets | Battle anims | Battle charsets | Monstres | Systems | Templates
Ressources RPG Maker XP: Tilesets | Autotiles | Characters | Battlers | Window skins | Icônes | Transitions | Fogs | Templates
Ressources RPG Maker VX: Tilesets | Charsets | Facesets | Systèmes
Ressources RPG Maker MV: Tilesets | Characters | Faces | Systèmes | Title | Battlebacks | Animations | SV/Ennemis
Archives: Palmarès | L'Annuaire | Livre d'or | Le Wiki | Divers