Beispiel #1
0
    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
Beispiel #2
0
    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
Beispiel #3
0
    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
Beispiel #4
0
    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
Beispiel #5
0
    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
Beispiel #6
0
    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)
Beispiel #7
0
    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
Beispiel #8
0
    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
Beispiel #9
0
    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)
Beispiel #10
0
    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)
Beispiel #11
0
    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")
Beispiel #12
0
 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
Beispiel #13
0
    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)
Beispiel #14
0
 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
Beispiel #15
0
    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)
Beispiel #16
0
    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")
Beispiel #17
0
    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)