def essayer_nage(self, origine, destination): """Essaye de nager et retourne un booléen de réussite. Le calcul compare la connaissance du talent nage, légèrement varié, au pourcentage porté par le joueur. Il est donc complètement lié à la force du joueur et à ce qu'il porte. Pour aider les nouveaux cela dit, le calcul est plus favorable : - Si le joueur tente d'aller vers le bord - Si le joueur est relativement bas niveau (entre 1 et 30). """ pc_poids = varier(int(self.poids / self.poids_max * 100), 5) connaissance = varier(self.pratiquer_talent("nage"), 15) # Si le joueur va vers le bord if destination.nom_terrain not in ("aquatique", "subaquatique"): connaissance += varier(40, 10) # Si le joueur est relativement bas niveau if self.niveau < 30: connaissance += varier(30 - self.niveau, 5) reussir = connaissance >= pc_poids return reussir
def echoue(self, personnage, cible): """Détermine si personnage réussit ou non à lancer ce sort.""" maitrise = (100 - personnage.sorts.get(self.cle, 0)) / 100 difficulte = self.difficulte / 100 if random() < difficulte * maitrise: return True if self.offensif and self.type_cible == "personnage": stat_lanceur = 0 stat_cible = 0 for nom_stat in self.stats: stat_lanceur += varier(getattr(personnage.stats, nom_stat), 10) stat_cible += varier(getattr(cible.stats, nom_stat), 10) if stat_lanceur < stat_cible: return True return False
def defendre(self, combattant, combattu, attaque, membre, degats, arme): """combattu tente de se défendre. Retourne les dégâts finalement infligés. Si la défense est totale, retourne 0. """ armes_def = combattu.get_armes() poids_combattant = combattant.poids / combattant.poids_max poids_combattu = combattu.poids / combattu.poids_max diff = (poids_combattant - poids_combattu) * 30 conn = combattu.get_talent("mains_nues") if armes_def: conn = combattu.get_talent(armes_def[0].cle_talent) if varier(combattu.pratiquer_talent(CLE_TALENT_ESQUIVE), 15) + diff >= \ varier(90, 10): attaque.envoyer_msg_tentative(combattant, combattu, membre, arme) combattant.envoyer("{} esquive votre coup.", combattu) combattu.envoyer("Vous esquivez le coup porté par {}.", combattant) combattant.salle.envoyer("{} esquive le coup porté par {}.", combattu, combattant) degats = 0 elif len([arme for arme in armes_def if arme.nom_type in \ ARMES_PARADE]) > 0 and varier(combattu.pratiquer_talent( CLE_TALENT_PARADE), 10) >= varier(conn, 15): attaque.envoyer_msg_tentative(combattant, combattu, membre, arme) combattant.envoyer("{} pare votre coup.", combattu) combattu.envoyer("Vous parez le coup porté par {}.", combattant) combattant.salle.envoyer("{} pare le coup porté par {}.", combattu, combattant) degats = 0 elif membre: objets = len(membre.equipe) and membre.equipe or [] for objet in objets: if objet and objet.est_de_type("armure"): encaisse = objet.encaisser(combattu, arme, degats) degats -= encaisse return degats
def actualiser_elements(self): """Actualise les éléments en fonction de la période.""" periode = self.periode n_elements = {} for elt in periode.elements: if not self.peut_porter(): break qtt = self.elements.get(elt.objet, 0) n_qtt = varier(elt.quantite, 3, 0) qtt += n_qtt if qtt > 0: n_elements[elt.objet] = qtt self.elements.clear() self.elements.update(n_elements)
def finie(self): """Retourne true si la période est finie, False sinon.""" tps = importeur.temps.temps jour = tps.jour mois = tps.mois t_j, t_m = self.fin t_j += varier(t_j, self.variation, min=None) if t_j < 0: t_m -= t_j // 30 t_j = t_j % 30 if mois > t_m: return True elif mois == t_m and jour > t_j: return True return False
def varier(base, marge): """Fait varier un nombre en fonction d'une marge. Le nombre précisée est la base. La marge renseigne la différence entre la base et la valeur minimum, d'une part, la base et la valeur maximum de l'autre. Ce peut sembler un peu dur à expliquer, mais voici un exemple qui rendra la chose limpide : varier(100, 20) -- retourne un nombre entre 80 et 120 Consulter les exemples ci-dessous pour plus d'informations. La marge peut être inférieure à 1. Dans ce cas, elle représente un pourcentage de la base : varier(200, 0,1) -- retourne entre 180 et 220 Paramètres à préciser : * base : la base (un nombre) * marge : la marge (un nombre) Exemples d'utilisation : # Retourne entre 800 et 1200 nombre = varier(1000, 200) # Retourne entre 900 et 1100 nombre = varier(1000, 0,1) # Retourne entre 99 et 101 nombre = varier(100, 0,01) # Préciser un nombre à virgule inférieur à 1 est utile si # vous ne connaissez pas l'ordre de grandeur de la base # (par exemple pour faire varier l'XP à donner au joueur). """ if marge < 1: marge = float(marge) marge = int(base * marge) variation = varier(int(base), int(marge), None) return Fraction(variation)
def interpreter(self, personnage, dic_masques): """Interprétation de la commande""" objet = dic_masques["nom_objet"].objet personnage.agir("depecer") if not objet.est_de_type("cadavre"): personnage << "|err|Vous ne pouvez dépecer " + objet.get_nom() + \ ".|ff|" return end = 5 try: personnage.stats.endurance -= end except DepassementStat: personnage << "|err|Vous êtes trop fatigué pour cela.|ff|" return if (datetime.now() - objet.apparition).seconds >= 750: personnage << "|err|Ce cadavre est trop abîmé pour être " \ "dépecé.|ff|" return armes = personnage.get_armes() lame = None for arme in armes: if arme.peut_depecer: lame = arme break if lame is None: personnage << "|err|Vous n'équipez rien pouvant dépecer.|ff|" return personnage << "Vous commencez à dépecer " + objet.get_nom() + "." personnage.etats.ajouter("depece") yield 5 if "depece" not in personnage.etats: return personnage.etats.retirer("depece") connaissance = varier(personnage.pratiquer_talent("depecage") + 1, 5) if connaissance < objet.pnj.niveau: personnage << "|err|Vous faites un beau gâchis en essayant de " \ "dépecer ce cadavre.|ff|" personnage.salle.envoyer("{} fait un beau gâchis en tentant de " \ "dépecer " + objet.get_nom() + ".", personnage) importeur.objet.supprimer_objet(objet.identifiant) else: importeur.objet.supprimer_objet(objet.identifiant) for elt, nb in objet.pnj.a_depecer.items(): for i in range(nb): o = importeur.objet.creer_objet(elt) personnage.salle.objets_sol.ajouter(o) personnage << "Vous dépecez " + objet.get_nom() + " avec " + \ lame.get_nom() + "." personnage.salle.envoyer("{} dépece " + objet.get_nom() + \ " avec " + lame.get_nom() + ".", personnage) objet.pnj.script["depece"].executer(personnage=personnage, salle=personnage.salle) personnage.gagner_xp_rel(objet.pnj.niveau, objet.pnj.gain_xp // 3, "survie")
def fin(self): """Retourne la fin semie aléatoire du cycle.""" if self.variation > 0: return varier(self.age + self.duree, self.variation) else: return self.age + self.duree
def interpreter(self, personnage, dic_masques): """Interprétation de la commande""" arme_de_jet = None for objet in personnage.equipement.equipes: if objet.est_de_type("arme de jet"): arme_de_jet = objet if arme_de_jet is None: personnage << "|err|Vous n'équipez aucune arme de jet.|ff|" return if arme_de_jet.projectile is None: personnage << "|err|Cette arme n'est pas chargée.|ff|" return salle = personnage.salle if not personnage.est_immortel() and salle.a_flag("anti combat"): personnage << "|err|Vous ne pouvez combattre ici.|ff|" return # Sélection de la cible if dic_masques["personnage_present"]: cible = dic_masques["personnage_present"].personnage else: cible = importeur.combat.cible.get(personnage) if cible is None or (hasattr(cible, "connecte") and \ not cible.connecte) or cible.est_mort(): personnage << "|err|Vous ne visez personne actuellement.|ff|" return chemin = None if personnage.salle is not cible.salle: chemin = personnage.salle.trouver_chemin(cible.salle) if chemin is None or not chemin.droit: personnage << "|err|Vous ne disposez pas d'un bon " \ "angle de tir.|ff|" return if not personnage.est_immortel() and cible.salle.a_flag("anti combat"): personnage << "|err|Vous ne pouvez combattre ici.|ff|" return projectile = arme_de_jet.projectile degats = projectile.degats_fixes + projectile.degats_variables if not personnage.est_immortel() and degats > 0: if not cible.pk: personnage << "|err|Vous ne pouvez tirer sur une cible " \ "qui n'a pas le flag PK activé.|ff|" return # 1. On fait partir le projectile personnage << lisser("Vous libérez la tension de {}.".format( arme_de_jet.get_nom())) personnage.salle.envoyer(lisser("{{}} libère la tension de {}.".format( arme_de_jet.get_nom())), personnage) arme_de_jet.projectile = None arme_de_jet.script["décoche"].executer(personnage=personnage, arme=arme_de_jet, projectile=projectile, cible=cible) # 2. On parcourt les salles adjacentes, si il y en a if chemin: for sortie in chemin: origine = sortie.parent destination = sortie.salle_dest direction = sortie.nom_complet if origine is personnage.salle: origine.envoyer("{} part en sifflant vers {}.".format( projectile.get_nom().capitalize(), direction)) else: origine.envoyer("{} passe en sifflant vers {}.".format( projectile.get_nom().capitalize(), direction)) if destination is cible.salle: destination.envoyer("{} arrive en sifflant dans les " \ "airs.".format(projectile.get_nom().capitalize())) else: # personnage et ible sont dans la même salle personnage.salle.envoyer("{} part en sifflant dans l'air.".format( projectile.get_nom().capitalize())) # 3. On voit si on atteint on manque la cible fact_p = varier(personnage.stats.agilite, 20) / 150 fact_p += (1 - personnage.poids / personnage.poids_max) / 4 fact_p += personnage.pratiquer_talent("maniement_arc") / 400 fact_c = varier(cible.stats.agilite, 20) / 150 fact_c += (1 - cible.poids / cible.poids_max) / 3 if fact_p > fact_c: if projectile.degats_fixes == 0: degats = 0 else: degats = varier(projectile.degats_fixes, \ projectile.degats_variables, projectile.degats_fixes) msg_auteur = "{} atteint {{}}" msg_cible = "{} vous atteint de plein fouet" if degats > 0: msg_auteur += " ({degats} points)." msg_cible += " ({degats} points) !" else: msg_auteur += "." msg_cible += " !" if personnage.salle is cible.salle: personnage.envoyer(msg_auteur.format( projectile.get_nom().capitalize(), degats=degats), cible) cible << msg_cible.format(projectile.get_nom().capitalize(), degats=degats) for autre in cible.salle.personnages: if autre is not personnage and autre is not cible: autre.envoyer("{} atteint {{}} de plein fouet.".format( projectile.get_nom().capitalize()), cible) # On appelle le script du projectile projectile.script["atteint"].executer(auteur=personnage, cible=cible, projectile=projectile, arme=arme_de_jet) if degats > 0: try: cible.stats.vitalite -= degats except DepassementStat: cible << "Trop, c'est trop ! Vous perdez conscience." cible.salle.envoyer("{} s'écroule sur le sol.", cible) if personnage.salle is not cible.salle: personnage << "Vous entendez un cri d'agonie non loin." cible.mourir(adversaire=personnage) else: cible.reagir_attaque(personnage) importeur.objet.supprimer_objet(projectile.identifiant) else: cible << "Vous esquivez {} d'un mouvement rapide.".format( projectile.get_nom()) cible.salle.envoyer("{{}} esquive {} d'un mouvement " \ "rapide.".format(projectile.get_nom()), cible) personnage.salle.objets_sol.ajouter(projectile)
def interpreter(self, personnage, dic_masques): """Interprétation de la commande""" arme_de_jet = None for objet in personnage.equipement.equipes: if objet.est_de_type("arme de jet"): arme_de_jet = objet if arme_de_jet is None: personnage << "|err|Vous n'équipez aucune arme de jet.|ff|" return if arme_de_jet.projectile is None: personnage << "|err|Cette arme n'est pas chargée.|ff|" return salle = personnage.salle if not personnage.est_immortel() and salle.a_flag("anti combat"): personnage << "|err|Vous ne pouvez combattre ici.|ff|" return # Sélection de la cible if dic_masques["personnage_present"]: cible = dic_masques["personnage_present"].personnage else: cible = importeur.combat.cible.get(personnage) if cible is None or (hasattr(cible, "connecte") and \ not cible.connecte) or cible.est_mort(): personnage << "|err|Vous ne visez personne actuellement.|ff|" return chemin = None if personnage.salle is not cible.salle: chemin = personnage.salle.trouver_chemin(cible.salle) if chemin is None or not chemin.droit: personnage << "|err|Vous ne disposez pas d'un bon " \ "angle de tir.|ff|" return if not personnage.est_immortel() and cible.salle.a_flag("anti combat"): personnage << "|err|Vous ne pouvez combattre ici.|ff|" return projectile = arme_de_jet.projectile degats = projectile.degats_fixes + projectile.degats_variables if not personnage.est_immortel() and degats > 0: if not cible.pk: personnage << "|err|Vous ne pouvez tirer sur une cible " \ "qui n'a pas le flag PK activé.|ff|" return # 1. On fait partir le projectile personnage << lisser("Vous libérez la tension de {}.".format( arme_de_jet.get_nom())) personnage.salle.envoyer( lisser("{{}} libère la tension de {}.".format( arme_de_jet.get_nom())), personnage) arme_de_jet.projectile = None arme_de_jet.script["décoche"].executer(personnage=personnage, arme=arme_de_jet, projectile=projectile, cible=cible) # 2. On parcourt les salles adjacentes, si il y en a if chemin: for sortie in chemin: origine = sortie.parent destination = sortie.salle_dest direction = sortie.nom_complet if origine is personnage.salle: origine.envoyer("{} part en sifflant vers {}.".format( projectile.get_nom().capitalize(), direction)) else: origine.envoyer("{} passe en sifflant vers {}.".format( projectile.get_nom().capitalize(), direction)) if destination is cible.salle: destination.envoyer("{} arrive en sifflant dans les " \ "airs.".format(projectile.get_nom().capitalize())) else: # personnage et ible sont dans la même salle personnage.salle.envoyer("{} part en sifflant dans l'air.".format( projectile.get_nom().capitalize())) # 3. On voit si on atteint on manque la cible fact_p = varier(personnage.stats.agilite, 20) / 150 fact_p += (1 - personnage.poids / personnage.poids_max) / 4 fact_p += personnage.pratiquer_talent("maniement_arc") / 400 fact_c = varier(cible.stats.agilite, 20) / 150 fact_c += (1 - cible.poids / cible.poids_max) / 3 if fact_p > fact_c: if projectile.degats_fixes == 0: degats = 0 else: degats = varier(projectile.degats_fixes, \ projectile.degats_variables, projectile.degats_fixes) msg_auteur = "{} atteint {{}}" msg_cible = "{} vous atteint de plein fouet" if degats > 0: msg_auteur += " ({degats} points)." msg_cible += " ({degats} points) !" else: msg_auteur += "." msg_cible += " !" if personnage.salle is cible.salle: personnage.envoyer( msg_auteur.format(projectile.get_nom().capitalize(), degats=degats), cible) cible << msg_cible.format(projectile.get_nom().capitalize(), degats=degats) for autre in cible.salle.personnages: if autre is not personnage and autre is not cible: autre.envoyer( "{} atteint {{}} de plein fouet.".format( projectile.get_nom().capitalize()), cible) # On appelle le script du projectile projectile.script["atteint"].executer(auteur=personnage, cible=cible, projectile=projectile, arme=arme_de_jet) if degats > 0: try: cible.stats.vitalite -= degats except DepassementStat: cible << "Trop, c'est trop ! Vous perdez conscience." cible.salle.envoyer("{} s'écroule sur le sol.", cible) if personnage.salle is not cible.salle: personnage << "Vous entendez un cri d'agonie non loin." cible.mourir(adversaire=personnage) else: cible.reagir_attaque(personnage) importeur.objet.supprimer_objet(projectile.identifiant) else: cible << "Vous esquivez {} d'un mouvement rapide.".format( projectile.get_nom()) cible.salle.envoyer("{{}} esquive {} d'un mouvement " \ "rapide.".format(projectile.get_nom()), cible) personnage.salle.objets_sol.ajouter(projectile)
def deplacer_vers(self, sortie, escalade=False, nage=False, fuite=True): """Déplacement vers la sortie 'sortie'""" salle = self.salle o_sortie = self.salle.sorties.get_sortie_par_nom(sortie) salle_dest = salle.sorties.get_sortie_par_nom(sortie).salle_dest # Calcul de l'endurance if escalade: end = min(8, o_sortie.diff_escalade * 2) elif nage: end = 10 else: end = self.salle.terrain.perte_endurance_dep # Vérifie que le personnage peut se déplacer (hook) retours = importeur.hook["personnage:peut_deplacer"].executer( self, salle_dest, o_sortie, end) if any(not r for r in retours): return # Modification de l'endurance retours = importeur.hook["personnage:calculer_endurance"].executer( self, end) n_endurance = end if retours: n_endurance = retours[0] if not self.est_en_combat(): self.agir("bouger") if o_sortie.diff_escalade and o_sortie.direction in ("haut", "bas") \ and not self.est_immortel() and not escalade: self << "|err|Vous devez escalader pour aller dans cette " \ "direction.|ff|" return if self.salle.nom_terrain in ("aquatique", "subaquatique") and \ not self.est_immortel() and not nage and not \ o_sortie.diff_escalade: self << "|err|Vous devez nager pour aller dans cette " \ "direction.|ff|" return try: self.stats.endurance -= n_endurance except DepassementStat: self << "|err|Vous êtes trop fatigué.|ff|" return if not self.est_immortel() and salle_dest.zone.fermee: self << "|err|Vous ne pouvez pas aller par là...|ff|" return if escalade: valeur_talent = self.get_talent("escalade") # note : la proba d'apprentissage du talent diminue si la pente # est trop facile par rapport au talent déjà possédé. # Si la connaissance dépasse la difficulté de plus de deux niveaux, # on divise par quatre la proba d'apprentissage if (valeur_talent / 10 > (o_sortie.diff_escalade + 2)): diviseur_proba = 4 # Si la connaissance dépasse la difficulté de plus d'un niveau, # on divise par deux la proba d'apprentissage elif (valeur_talent / 10 > (o_sortie.diff_escalade + 1)): diviseur_proba = 2 else: diviseur_proba = 1 valeur_talent = self.pratiquer_talent("escalade", diviseur_proba) # on rajoute une valeur entre -10 et +10 au talent aléatoirement # ainsi à partir de 10 en-dessous de la difficulté fois 10, on # commence à avoir une petite chance (si on est nu). À partir de # 10 au-dessus de la difficulté fois 10, on ne peut plus échouer # (si on est nu). tentative = varier(valeur_talent, 10) importeur.salle.logger.debug( "{} essaye d'escalader (réussir={}, difficulté={})".format( self.nom, round(tentative / 10, 2), o_sortie.diff_escalade)) reussir = tentative / 10 >= o_sortie.diff_escalade if not reussir: self.tomber() return if nage: reussir = self.essayer_nage(self.salle, salle_dest) if not reussir: self << "|err|Vous battez des bras et des jambes mais " \ "n'avancez pas.|ff|" self.salle.envoyer("{} bat des bras et des jambes mais " \ "n'avance pas.", self) return sortie = salle.sorties.get_sortie_par_nom(sortie) sortie_opp = sortie.sortie_opposee nom_opp = sortie_opp and sortie_opp.nom or "" fermer = False if not self.est_immortel() and sortie.porte and \ sortie.porte.verrouillee: self << "Cette porte semble fermée à clef.".format( sortie.nom_complet) return if not self.est_immortel() and sortie.porte and \ sortie.porte.fermee and not sortie.porte.verrouillee and \ not salle_dest.peut_entrer(self): self << "|err|Vous ne pouvez ouvrir cette porte.|ff|" return if self.est_en_combat(): reussite = self.essayer_fuir() if reussite: self << "Vous vous enfuyez..." self.etats.retirer("combat") combat = type(self).importeur.combat.get_combat_depuis_salle( self.salle) combat.supprimer_combattant(self) else: self << "|err|Vous ne parvenez pas à vous enfuir !|ff|" return # On appelle l'évènement sort des affections du personnage for affection in list(self.affections.values()): duree = affection.duree force = affection.force affection.affection.script["sort"].executer(personnage=self, salle=salle, force=force, duree=duree) # On appelle l'évènement 'sort' des affections de la salle for affection in list(salle.affections.values()): duree = affection.duree force = affection.force affection.affection.script["sort"].executer(personnage=self, salle=salle, force=force, duree=duree) # On appelle l'événement sort.avant de la salle salle.script["sort"]["avant"].executer(vers=sortie.nom, salle=salle, personnage=self, destination=salle_dest) # On appelle l'événement personnage.sort si nécessaire if hasattr(self, "script"): if self.salle is salle_dest: personnage.script["sort"].executer(vers=sortie.nom, salle=salle, destination=salle_dest, pnj=self) # On appelle les pnj.part des PNJs de la salle for perso in self.salle.personnages: if perso is not self and hasattr(perso, "script") and \ perso.peut_voir(self): perso.script["part"].executer(vers=sortie.nom, destination=salle_dest, pnj=perso, personnage=self) # Si la porte est fermée (pas verrouillée), on l'ouvre if not self.est_immortel() and sortie.porte and \ sortie.porte.fermee and not sortie.porte.verrouillee: self << "Vous ouvrez {}.".format(sortie.nom_complet) self.salle.envoyer("{{}} ouvre {}.".format(sortie.nom_complet), self) sortie.porte.ouvrir() fermer = True verbe = "s'en va vers" if escalade: verbe = "escalade" elif nage: verbe = "nage vers" else: retours = importeur.hook["personnage:verbe_deplacer"].executer( self, salle_dest) if retours: verbe = retours[0] if sortie.cachee: for personnage in salle.personnages: msg = "{{personnage}} {verbe}... Vous ne voyez pas " \ "très bien où." if personnage.est_immortel(): msg = "{{personnage}} {verbe} {sortie}." msg = msg.format(sortie=sortie.nom_complet, verbe=verbe) if personnage is not self: personnage.envoyer(msg, personnage=self) else: salle.envoyer("{{}} {} {}.".format(verbe, sortie.nom_complet), self) # On appelle l'évènement sort.apres salle.script["sort"]["apres"].executer(vers=sortie.nom, salle=salle, personnage=self, destination=salle_dest) if fermer: self.salle.envoyer("Vous entendez une porte se refermer.", self) sortie.porte.fermer() self.envoyer("Vous passez {} et refermez derrière vous.".format( sortie.nom_complet)) # Plonger sous l'eau if salle.nom_terrain != "subaquatique" and \ salle_dest.nom_terrain == "subaquatique": self.plonger() # Emerger de sous l'eau if salle.nom_terrain == "subaquatique" and \ salle_dest.nom_terrain != "subaquatique": self.emerger() self.salle = salle_dest # On appelle l'hook de déplacement importeur.hook["personnage:deplacer"].executer( self, salle_dest, o_sortie, end) # On appelle l'évènement entre.avant if self.salle is salle_dest: salle_dest.script["entre"]["avant"].executer( depuis=nom_opp, salle=salle_dest, personnage=self) verbe = "arrive" retours = importeur.hook["personnage:verbe_arriver"].executer( self, salle_dest) if retours: verbe = retours[0] self.envoyer(self.salle.regarder(self)) salle_dest.envoyer("{{}} {verbe}.".format(verbe=verbe), self) # Envoi de tips if salle_dest.magasin: self.envoyer_tip("Entrez %lister%|vr| pour voir les produits " \ "en vente dans ce magasin.") if salle_dest in importeur.commerce.questeurs: self.envoyer_tip("Entrez %questeur%|vr| pour interagir avec " \ "le questeur présent.") if salle.nom_terrain != "subaquatique" and \ salle_dest.nom_terrain == "subaquatique": self.envoyer_tip("Vous êtes sous l'eau. " \ "Attention au manque d'air !") # On appelle l'évènement entre.apres if self.salle is salle_dest: salle_dest.script["entre"]["apres"].executer( depuis=nom_opp, salle=salle_dest, personnage=self) if salle.nom_zone != salle_dest.nom_zone: salle_dest.zone.script["entre"].executer( origine=salle, salle=salle_dest, personnage=self) # On appelle l'évènement 'sort' des affections de la salle for affection in list(salle_dest.affections.values()): duree = affection.duree force = affection.force affection.affection.script["entre"].executer(personnage=self, salle=salle_dest, force=force, duree=duree) # On appelle l'événement personnage.entre si nécessaire if hasattr(self, "script"): if self.salle is salle_dest: self.script["entre"].executer(depuis=nom_opp, salle=salle_dest, pnj=self) # On appelle les pnj.arrive des PNJs de la salle for perso in salle_dest.personnages: if perso is not self and hasattr(perso, "script") and \ perso.peut_voir(self): perso.script["arrive"].executer(depuis=nom_opp, pnj=perso, personnage=self, salle=salle) importeur.hook["pnj:arrive"].executer(perso, self)