|
|
@@ -1,1528 +1,1542 @@
|
|
|
-#from __future__ import unicode_literals
|
|
|
-# -*- coding: utf-8 -*-
|
|
|
-from __future__ import division
|
|
|
-
|
|
|
-from PyQt4.QtCore import *
|
|
|
-from PyQt4.QtGui import *
|
|
|
-
|
|
|
-##from ui.ecran_editionAttaques import Ui_editionAttaques
|
|
|
-
|
|
|
-import Modes
|
|
|
-import Actions
|
|
|
-from Case import Case
|
|
|
-from Combattant import Combattant
|
|
|
-from Decor import Decor
|
|
|
-from Pinceau import Pinceau
|
|
|
-from ProjectionDep import ProjectionDep
|
|
|
-from Cache import Cache
|
|
|
-from Terrain import Terrain
|
|
|
-
|
|
|
-from EcranEditionCombattant import EcranEditionCombattant
|
|
|
-from EcranEditionDecor import EcranEditionDecor
|
|
|
-from EcranEditionTerrain import EcranEditionTerrain
|
|
|
-from EcranAffichageTexte import EcranAffichageTexte
|
|
|
-from EcranGestionCombat import EcranGestionCombat
|
|
|
-from EcranSelectionPj import EcranSelectionPj
|
|
|
-from EcranVol import EcranVol
|
|
|
-
|
|
|
-import regles as regles
|
|
|
-from outilsSvg import *
|
|
|
-import br
|
|
|
-
|
|
|
-from math import sqrt
|
|
|
-
|
|
|
-m_couleursRapides = [(255,255,255), (200,200,200), (130,130,130), (90,90,90), (15,15,15), \
|
|
|
- (0,85,0), (170,255,0), (170,255,127), (85,85,0), (85,0,0), (170,85,0), (100,50,0), \
|
|
|
- (255,255,127), (240,80,0), (85,170,255), (85,85,255), (85,0,255), (0,255,255)]
|
|
|
-
|
|
|
-class Plateau(QGraphicsScene):
|
|
|
- """plateau de jeu contenant les cases, decors et pions"""
|
|
|
- def __init__(self, fenetre, parent=None):
|
|
|
- super(Plateau, self).__init__()
|
|
|
- #parametres et variables
|
|
|
-
|
|
|
- self.fenetre = fenetre
|
|
|
-
|
|
|
- ##partie et infos plateau
|
|
|
- self.id = ""
|
|
|
- self.nom = ""
|
|
|
- self.chapitre = 0
|
|
|
- self.tour = 1
|
|
|
-
|
|
|
- self.enCours = False
|
|
|
- self.public = False
|
|
|
- self.dateCreation = ""
|
|
|
- self.dateSvg = ""
|
|
|
- self.notes = ""
|
|
|
-
|
|
|
- #carac
|
|
|
- self.nbCasesX = 0
|
|
|
- self.nbCasesY = 0
|
|
|
- self.hCase = 0
|
|
|
-
|
|
|
- #objets
|
|
|
- self.pinceau = Pinceau(self)
|
|
|
- self.cases = {} #dict des cases du plateau (coordonnées: case)
|
|
|
- self.combattants = {} #liste de combattants positionnes sur le plateau
|
|
|
- self.decors = {} #liste des decors places sur le plateau
|
|
|
- self.caches = {}
|
|
|
- self.listeCasesZonePlacement = []
|
|
|
- self.polygoneZonePlacement = None
|
|
|
- self.entreesSorties = []
|
|
|
-
|
|
|
- #infos combat
|
|
|
- self.numCombattantEnCours = 0
|
|
|
- self.ordreJeu = {} #numero du pion: ordre de jeu
|
|
|
-
|
|
|
- #note: la hauteur Z (qui gere l'empilement des objets graphiques est distribuee de cette maniere:
|
|
|
- #cases : 0 a 9
|
|
|
- #pions : 10 et +
|
|
|
-
|
|
|
- def __getstate__(self):
|
|
|
- self.dateSvg = time()
|
|
|
- state = {key:value for key, value in self.__dict__.items() if not key in ["fenetre", "modeActif", \
|
|
|
- "editionTerrain", "editionCreature", "editionDecor", \
|
|
|
- "polygoneZonePlacement", "gestionCombat", \
|
|
|
- "editionAttaques", "pinceau"]}
|
|
|
- return (state)
|
|
|
-
|
|
|
- def __setstate__(self, state):
|
|
|
- self.__dict__ = state
|
|
|
-
|
|
|
- def vue(self):
|
|
|
- return self.fenetre.ui.cbt_vue
|
|
|
-
|
|
|
- def creer(self, idPlateau, nom, chapitre, formeCases, nbCasesX, nbCasesY, couleur = QColor(0, 255, 0, 80)):
|
|
|
- """cree le plateau"""
|
|
|
- self.id = idPlateau
|
|
|
- self.nom = nom
|
|
|
- self.chapitre = chapitre
|
|
|
- self.dateCreation = time()
|
|
|
- self.hCase = 120 #hauteur d'une case
|
|
|
- self.nbCasesX = nbCasesX #nb cases en x
|
|
|
- self.nbCasesY = nbCasesY #nb cases en y
|
|
|
- self.formeCases = formeCases
|
|
|
- self.modeActif = Modes.ModeBase(self)
|
|
|
- self.gestionCombat = None
|
|
|
- self.initialisationGraphique()
|
|
|
- self.connexions()
|
|
|
-
|
|
|
- #cree les cases hexagonales
|
|
|
- for x in range(nbCasesX):
|
|
|
- for y in range(nbCasesY):
|
|
|
- c = Case(self)
|
|
|
- c.creer(x, y, couleur)
|
|
|
- self.cases[(x,y)] = c
|
|
|
-
|
|
|
- self.plateauModeCreation()
|
|
|
-
|
|
|
- def recreer(self, fenetre):
|
|
|
- self.fenetre = fenetre
|
|
|
- self.gestionCombat = None
|
|
|
- super(Plateau, self).__init__()
|
|
|
- self.modeActif = Modes.ModeBase(self)
|
|
|
- self.connexions()
|
|
|
- self.initialisationGraphique()
|
|
|
-
|
|
|
- #recreation des cases
|
|
|
- for coord in self.cases:
|
|
|
- self.cases[coord].recreer(self)
|
|
|
-
|
|
|
- #recreation des caches
|
|
|
- self.initListeCaches()
|
|
|
-
|
|
|
- #recreation des pions
|
|
|
- for numCombattant in self.combattants:
|
|
|
- self.combattants[numCombattant].ajouterAuPlateau(self)
|
|
|
- self.majOrdreJeu()
|
|
|
-
|
|
|
- #recreation des decors
|
|
|
- for num in self.decors:
|
|
|
- self.decors[num].ajouterAuPlateau(self)
|
|
|
-
|
|
|
- #recreation des marqueurs entree/sortie
|
|
|
- for entreeSortie in self.entreesSorties:
|
|
|
- entreeSortie.recreer(self)
|
|
|
-
|
|
|
- #recreation de la zone de placement:
|
|
|
- if len(self.listeCasesZonePlacement) > 0:
|
|
|
- self.polygoneZonePlacement = None
|
|
|
- self.majZonePlacement(self.listeCasesZonePlacement)
|
|
|
-
|
|
|
- self.plateauModeCombat()
|
|
|
-
|
|
|
- def fermer(self):
|
|
|
- """ferme le plateau 'proprement'"""
|
|
|
- self.miniature()
|
|
|
- self.pinceau = None
|
|
|
- for item in self.items():
|
|
|
- item.prepareGeometryChange()
|
|
|
- self.removeItem(item)
|
|
|
- if self.gestionCombat != None:
|
|
|
- del self.gestionCombat
|
|
|
- self.fenetre.reinitialiserPanneauxPlateau()
|
|
|
-
|
|
|
- def miniature(self):
|
|
|
- """renvoie une miniature du plateau (QPixMap compresse) qui sera enregistree avec les infos de la sauvegarde"""
|
|
|
-## img = QImage(128, 128, QImage.Format_ARGB32_Premultiplied)
|
|
|
- img = QPixmap(1024, 768)
|
|
|
- img.fill(QColor("white"))
|
|
|
- peintre = QPainter(img)
|
|
|
- self.render(peintre)
|
|
|
- peintre.end()
|
|
|
- img.scaledToHeight(128, Qt.FastTransformation)
|
|
|
-
|
|
|
- def connexions(self):
|
|
|
- """connecte le plateau aux differents widgets de la fenetre principale"""
|
|
|
- #modes d'interaction
|
|
|
- self.fenetre.connect(self.fenetre.ui.cbt_modeCreation, SIGNAL("clicked()"), self.plateauModeCreation, Qt.UniqueConnection)
|
|
|
- self.fenetre.connect(self.fenetre.ui.cbt_modeCombat, SIGNAL("clicked()"), self.plateauModeCombat, Qt.UniqueConnection)
|
|
|
-## self.fenetre.connect(self.fenetre.ui.modeAffichagePlateau, SIGNAL("currentIndexChanged(int)"), self.majModeAffichage, Qt.UniqueConnection)
|
|
|
-
|
|
|
-
|
|
|
- #affichage de fenetres
|
|
|
- self.fenetre.connect(self.fenetre.ui.cbt_afficherGestion, SIGNAL("clicked()"), self.afficheEcranGestionCombat, Qt.UniqueConnection)
|
|
|
- self.fenetre.connect(self.fenetre.ui.cbt_ajouterPj, SIGNAL("clicked()"), self.ajouterPj, Qt.UniqueConnection)
|
|
|
- self.fenetre.connect(self.fenetre.ui.pi_listeAttributs, SIGNAL("cellChanged(int,int)"), self.listeAttributCelluleModifiee, Qt.UniqueConnection)
|
|
|
-
|
|
|
- self.fenetre.connect(self.fenetre.ui.cp_dialogueCouleurs, SIGNAL("clicked()"), self.modePeintureCase, Qt.UniqueConnection)
|
|
|
- self.fenetre.connect(self.fenetre.ui.cp_pipetteCouleur, SIGNAL("clicked()"), self.modeCopieTerrain, Qt.UniqueConnection)
|
|
|
- self.fenetre.connect(self.fenetre.ui.cp_afficherNotes, SIGNAL("clicked()"), self.agrandirNotesMjPlateau, Qt.UniqueConnection)
|
|
|
-
|
|
|
-
|
|
|
- #listes
|
|
|
- self.fenetre.connect(self.fenetre.ui.inf_listeOrdreJeu, SIGNAL("cellClicked(int,int)"), self.clicListOrdreJeu, Qt.UniqueConnection)
|
|
|
-
|
|
|
- self.fenetre.connect(self.fenetre.ui.cp_listeTerrains, SIGNAL("cellClicked(int,int)"), self.modeMajTerrainCase, Qt.UniqueConnection)
|
|
|
- self.fenetre.connect(self.fenetre.ui.cp_listeCreatures, SIGNAL("cellClicked(int,int)"), self.modeCreationCombattant, Qt.UniqueConnection)
|
|
|
- self.fenetre.connect(self.fenetre.ui.cp_listeDecors, SIGNAL("cellClicked(int,int)"), self.modeCreationDecor, Qt.UniqueConnection)
|
|
|
- self.fenetre.connect(self.fenetre.ui.cp_listeCaches, SIGNAL("cellClicked(int,int)"), self.mettreCacheEnEvidence, Qt.UniqueConnection)
|
|
|
-# self.fenetre.connect(self.fenetre.ui.cp_listeCaches, SIGNAL("cellChanged(int,int)"), self.majNomCache, Qt.UniqueConnection)
|
|
|
-
|
|
|
- self.fenetre.connect(self.fenetre.ui.cp_editerTerrain, SIGNAL("clicked()"), self.terrainEdit, Qt.UniqueConnection)
|
|
|
- self.fenetre.connect(self.fenetre.ui.cp_nouveauTerrain, SIGNAL("clicked()"), self.terrainNouveau, Qt.UniqueConnection)
|
|
|
- self.fenetre.connect(self.fenetre.ui.cp_editerCombattant, SIGNAL("clicked()"), self.creatureEdit, Qt.UniqueConnection)
|
|
|
- self.fenetre.connect(self.fenetre.ui.cp_nouveauCombattant, SIGNAL("clicked()"), self.creatureNouveau, Qt.UniqueConnection)
|
|
|
- self.fenetre.connect(self.fenetre.ui.cp_gommeCombattant, SIGNAL("clicked()"), self.majModeSupprimerCombattant, Qt.UniqueConnection)
|
|
|
- self.fenetre.connect(self.fenetre.ui.cp_editerDecor, SIGNAL("clicked()"), self.decorEdit, Qt.UniqueConnection)
|
|
|
- self.fenetre.connect(self.fenetre.ui.cp_nouveauDecor, SIGNAL("clicked()"), self.decorNouveau, Qt.UniqueConnection)
|
|
|
- self.fenetre.connect(self.fenetre.ui.cp_gommeDecor, SIGNAL("clicked()"), self.majModeSupprimerDecor, Qt.UniqueConnection)
|
|
|
- self.fenetre.connect(self.fenetre.ui.cp_editerCache, SIGNAL("clicked()"), self.activerModeEditionCache, Qt.UniqueConnection)
|
|
|
- self.fenetre.connect(self.fenetre.ui.cp_nouveauCache, SIGNAL("clicked()"), self.activerModeCreationCache, Qt.UniqueConnection)
|
|
|
- self.fenetre.connect(self.fenetre.ui.cp_supprimerCache, SIGNAL("clicked()"), self.supprimerCache, Qt.UniqueConnection)
|
|
|
-
|
|
|
- #creation
|
|
|
- self.fenetre.connect(self.fenetre.ui.cp_epaisseurPinceau, SIGNAL("valueChanged(int)"), self.majEpaisseurPinceau, Qt.UniqueConnection)
|
|
|
-## self.fenetre.connect(self.fenetre.ui.altitudeCase, SIGNAL("valueChanged(double)"), self.modeMajAltitudeCase, Qt.UniqueConnection)
|
|
|
-
|
|
|
- #autres:
|
|
|
- #ajouter effet
|
|
|
- self.fenetre.connect(self.fenetre.ui.cp_placerEntree, SIGNAL("clicked()"), self.majModeDefinirEntree, Qt.UniqueConnection)
|
|
|
- self.fenetre.connect(self.fenetre.ui.cp_placerSortie, SIGNAL("clicked()"), self.majModeDefinirSortie, Qt.UniqueConnection)
|
|
|
- self.fenetre.connect(self.fenetre.ui.cp_defPlacement, SIGNAL("clicked()"), self.majModeZonePlacement, Qt.UniqueConnection)
|
|
|
- self.fenetre.connect(self.fenetre.ui.pi_notes, SIGNAL("textChanged()"), self.majNotesCombattant, Qt.UniqueConnection)
|
|
|
-
|
|
|
- #formes (dessin)
|
|
|
- self.fenetre.connect(self.fenetre.ui.cp_formeSimple, SIGNAL("clicked()"), self.majModeForme, Qt.UniqueConnection)
|
|
|
- self.fenetre.connect(self.fenetre.ui.cp_formeLigne, SIGNAL("clicked()"), self.majModeForme, Qt.UniqueConnection)
|
|
|
- self.fenetre.connect(self.fenetre.ui.cp_formeLigneOrientee, SIGNAL("clicked()"), self.majModeForme, Qt.UniqueConnection)
|
|
|
- self.fenetre.connect(self.fenetre.ui.cp_formePot, SIGNAL("clicked()"), self.majModeForme, Qt.UniqueConnection)
|
|
|
- self.fenetre.connect(self.fenetre.ui.cp_formeRectVide, SIGNAL("clicked()"), self.majModeForme, Qt.UniqueConnection)
|
|
|
- self.fenetre.connect(self.fenetre.ui.cp_formeRectPlein, SIGNAL("clicked()"), self.majModeForme, Qt.UniqueConnection)
|
|
|
-
|
|
|
- self.fenetre.connect(self.fenetre.ui.pi_deplacement, SIGNAL("clicked()"), self.majModeCombatDeplacement, Qt.UniqueConnection)
|
|
|
- self.fenetre.connect(self.fenetre.ui.pi_vol, SIGNAL("clicked()"), self.majModeCombatVol, Qt.UniqueConnection)
|
|
|
- self.fenetre.connect(self.fenetre.ui.pi_attaqueCac, SIGNAL("clicked()"), self.majModeCombatAttaqueCaC, Qt.UniqueConnection)
|
|
|
- self.fenetre.connect(self.fenetre.ui.pi_attaqueDist, SIGNAL("clicked()"), self.majModeCombatAttaqueDist, Qt.UniqueConnection)
|
|
|
- self.fenetre.connect(self.fenetre.ui.pi_attaqueZone, SIGNAL("clicked()"), self.majModeCombatZone, Qt.UniqueConnection)
|
|
|
- self.fenetre.connect(self.fenetre.ui.pi_formeAttaqueZone, SIGNAL("activated (int)"), self.majModeCombatZone, Qt.UniqueConnection)
|
|
|
- self.fenetre.connect(self.fenetre.ui.pi_rayonAttaqueZone, SIGNAL("valueChanged(int)"), self.majRayonZone, Qt.UniqueConnection)
|
|
|
-
|
|
|
-
|
|
|
- self.fenetre.connect(self.fenetre.ui.pi_finTour, SIGNAL("clicked()"), self.pionSuivant, Qt.UniqueConnection)
|
|
|
-
|
|
|
- def initialisationGraphique(self):
|
|
|
- """cree la scene graphique et les parametres necessaires a son fonctionnement, et met a jour l'interface"""
|
|
|
- #on cree la scene graphique
|
|
|
- kx = 1
|
|
|
- if self.formeCases == "H":
|
|
|
- kx = 0.866
|
|
|
- marge = 240
|
|
|
- self.setSceneRect(0 - marge, 0 - marge, (kx*self.hCase*(self.nbCasesX+2)) + marge, (self.hCase*(self.nbCasesY+2)) + marge)
|
|
|
- self.vue().setScene(self)
|
|
|
- self.vue().scale(0.25, 0.25)
|
|
|
- self.vue().centerOn(QPointF(0,0))
|
|
|
- self.vue().setDragMode(1)
|
|
|
- self.setItemIndexMethod(QGraphicsScene.BspTreeIndex)
|
|
|
-
|
|
|
- self.polygoneZonePlacement = None
|
|
|
-
|
|
|
- #gestion du mode d'interaction avec le plateau
|
|
|
-
|
|
|
- self.pinceau = Pinceau(self)
|
|
|
- self.proj = ProjectionDep(self)
|
|
|
-
|
|
|
- #mise a jour de l'interface de creation
|
|
|
- self.fenetre.afficherPanneauxPlateau(True)
|
|
|
- self.fenetre.ui.cbt_nom.majTexte(self.nom)
|
|
|
- self.majBoutonsCouleursPerso()
|
|
|
- self.fenetre.ui.cp_listeTerrains.defFichier("lib\\biblio\\terrain")
|
|
|
- self.fenetre.ui.cp_listeTerrains.initAffichage()
|
|
|
- self.fenetre.ui.cp_listeCreatures.defFichier("lib\\biblio\\combattant")
|
|
|
- self.fenetre.ui.cp_listeCreatures.initAffichage()
|
|
|
- self.fenetre.ui.cp_listeDecors.defFichier("lib\\biblio\\decor")
|
|
|
- self.fenetre.ui.cp_listeDecors.initAffichage()
|
|
|
- self.majListeTerrains()
|
|
|
- self.majListeCreatures()
|
|
|
- self.majListeDecors()
|
|
|
- self.initListeCaches()
|
|
|
-
|
|
|
- self.initListeOrdreJeu()
|
|
|
- self.initListeAttaques()
|
|
|
-
|
|
|
- self.fenetre.ui.pi_deplacement.setCheckable(True)
|
|
|
- self.fenetre.ui.pi_attaqueCac.setCheckable(True)
|
|
|
- self.fenetre.ui.pi_attaqueDist.setCheckable(True)
|
|
|
- self.fenetre.ui.pi_attaqueZone.setCheckable(True)
|
|
|
-
|
|
|
- #mise a jour de l'interface d'informations
|
|
|
- self.majInfosCombattant(None)
|
|
|
- self.majInfosDecor(None)
|
|
|
-
|
|
|
- def estCree(self):
|
|
|
- """renvoie vrai si des cases ont ete creees"""
|
|
|
- return (len(self.cases) > 0)
|
|
|
-
|
|
|
- def majBoutonsCouleursPerso(self):
|
|
|
- """met a jour l'affichage des couleurs customisees dans la boite de dialogue de selection de couleur"""
|
|
|
- for i in range(0,18):
|
|
|
- couleur = QColor()
|
|
|
- r, g, b = m_couleursRapides[i]
|
|
|
- couleur.setRgb(r, g, b)
|
|
|
- bouton = self.fenetre.ui.cp_boiteCouleurs.findChild(QToolButton, "cp_couleur{}".format(i+1))
|
|
|
- if couleur.isValid():
|
|
|
- bouton.setStyleSheet("QToolButton {backGround:%s}"%(couleur.name()))
|
|
|
- self.fenetre.connect(bouton, SIGNAL("clicked()"), self.modePeintureCase_perso)
|
|
|
-
|
|
|
- def chercherCouleur(self):
|
|
|
- """ouvre la boite de dialogue de selection de couleur"""
|
|
|
- couleur = QColorDialog(self.vue()).getColor(QColor("white"), self.vue())
|
|
|
- return couleur
|
|
|
-
|
|
|
- def majListesPions(self, numCombattant = None):
|
|
|
- """met a jour les listes contenant des donnees liees aux pions"""
|
|
|
-## self.majListeOrdreJeu()
|
|
|
-##
|
|
|
-## if numCombattant == None or numCombattant == self.pionSelectionne().numero:
|
|
|
-## self.majListeAttributs()
|
|
|
-## QApplication.processEvents()
|
|
|
- pass
|
|
|
-
|
|
|
- def ajouterPj(self):
|
|
|
- """affiche la fenetre de selection des pj, et recupere l'eventuel pj selectionne"""
|
|
|
- self.ecranSelPj = EcranSelectionPj(self.fenetre)
|
|
|
- self.ecranSelPj.setAttribute(Qt.WA_DeleteOnClose)
|
|
|
- listePj = chargerUnique("parties\\{}\\groupe".format(self.fenetre.partie))
|
|
|
- self.ecranSelPj.charger(listePj)
|
|
|
- r = self.ecranSelPj.exec_()
|
|
|
- if r == 1:
|
|
|
- idPj = int(self.ecranSelPj.selection())
|
|
|
- if idPj != None:
|
|
|
- pj = listePj[idPj]
|
|
|
- self.activerMode(Modes.CreationPion, pj)
|
|
|
- self.ecranSelPj = None
|
|
|
-
|
|
|
- def agrandirNotesMjPlateau(self):
|
|
|
- """affiche les notes du plateau dans une QDialog, puis recupere les donnees qui y sont saisies"""
|
|
|
- affichageTexte = EcranAffichageTexte(self.notes)
|
|
|
- affichageTexte.setAttribute(Qt.WA_DeleteOnClose)
|
|
|
- affichageTexte.exec_()
|
|
|
- self.notes = affichageTexte.recupererTexte()
|
|
|
-
|
|
|
- ##### affichage de la liste des terrains enregistres, et fonctions d'acces aux donnees""""
|
|
|
- def afficheEcranEditionTerrains(self, terrain = None):
|
|
|
- """affiche l'ecran d'edition/creation de terrains"""
|
|
|
- self.editionTerrain = EcranEditionTerrain(terrain)
|
|
|
- self.editionTerrain.setAttribute(Qt.WA_DeleteOnClose)
|
|
|
- r = self.editionTerrain.exec_()
|
|
|
- if r == 1:
|
|
|
- self.majListeTerrains()
|
|
|
- self.activerMode(Modes.StandardCp)
|
|
|
-
|
|
|
- def majListeTerrains(self):
|
|
|
- """mise a jour de la liste des terrains depuis la sauvegarde"""
|
|
|
- self.fenetre.ui.cp_listeTerrains.maj()
|
|
|
-
|
|
|
- def terrainEdit(self):
|
|
|
- """ouvre la fenetre 'terrains' en mode edition"""
|
|
|
- index = self.fenetre.ui.cp_listeTerrains.item(self.fenetre.ui.cp_listeTerrains.currentRow(), 0)
|
|
|
- if index > 0:
|
|
|
- terrain = charger("lib\\biblio\\terrain", str(index.text().toUtf8()))
|
|
|
- self.afficheEcranEditionTerrains(terrain)
|
|
|
- self.activerMode(Modes.StandardCp)
|
|
|
-
|
|
|
- def terrainNouveau(self):
|
|
|
- """ouvre la fenetre 'terrains' en mode edition"""
|
|
|
- self.afficheEcranEditionTerrains()
|
|
|
- self.activerMode(Modes.StandardCp)
|
|
|
- ###############
|
|
|
-
|
|
|
- ##### affichage de la liste des creatures enregistrees, et fonctions d'acces aux donnees""""
|
|
|
- def afficheEcranEditionCombattants(self, creature = None):
|
|
|
- """affiche l'ecran d'edition/creation de creatures"""
|
|
|
- self.editionCreature = EcranEditionCombattant(creature, 0, self.formeCases)
|
|
|
- self.editionCreature.setAttribute(Qt.WA_DeleteOnClose)
|
|
|
- r = self.editionCreature.exec_()
|
|
|
- if r == 1:
|
|
|
- combattant = self.editionCreature.combattant
|
|
|
- enregistrer(combattant.id, combattant, "lib\\biblio\\combattant")
|
|
|
- self.majListeCreatures()
|
|
|
- self.activerMode(Modes.StandardCp)
|
|
|
- self.editionCreature = None
|
|
|
-
|
|
|
- def majListeCreatures(self):
|
|
|
- """mise a jour de la liste des creatures depuis la sauvegarde"""
|
|
|
- self.fenetre.ui.cp_listeCreatures.maj()
|
|
|
-
|
|
|
- def creatureEdit(self):
|
|
|
- """ouvre la fenetre 'creatures' en mode edition"""
|
|
|
- index = self.fenetre.ui.cp_listeCreatures.item(self.fenetre.ui.cp_listeCreatures.currentRow(), 0)
|
|
|
- if index > 0:
|
|
|
- creature = charger("lib\\biblio\\combattant", str(index.text().toUtf8()))
|
|
|
- self.afficheEcranEditionCombattants(creature)
|
|
|
- self.activerMode(Modes.StandardCp)
|
|
|
-
|
|
|
- def creatureNouveau(self):
|
|
|
- """ouvre la fenetre 'creatures' en mode edition"""
|
|
|
- self.afficheEcranEditionCombattants()
|
|
|
- self.activerMode(Modes.StandardCp)
|
|
|
-
|
|
|
- ###############
|
|
|
-
|
|
|
- ##### affichage de la liste des decors enregistrees, et fonctions d'acces aux donnees""""
|
|
|
- def afficheEcranEditionDecors(self, decor = None):
|
|
|
- """affiche l'ecran d'edition/creation de decors"""
|
|
|
- self.editionDecor = EcranEditionDecor(decor, 0, self.formeCases)
|
|
|
- self.editionDecor.setAttribute(Qt.WA_DeleteOnClose)
|
|
|
- r = self.editionDecor.exec_()
|
|
|
- if r == 1:
|
|
|
- decor = self.editionDecor.decor
|
|
|
- enregistrer(decor.id, decor, "lib\\biblio\\decor")
|
|
|
- self.majListeDecors()
|
|
|
- self.activerMode(Modes.StandardCp)
|
|
|
-
|
|
|
- def majListeDecors(self):
|
|
|
- """mise a jour de la liste des decors depuis la sauvegarde"""
|
|
|
- self.fenetre.ui.cp_listeDecors.maj()
|
|
|
-
|
|
|
- def decorEdit(self):
|
|
|
- """ouvre la fenetre 'decors' en mode edition"""
|
|
|
- self.afficheEcranEditionDecors(self.fenetre.ui.cp_listeDecors.actuel())
|
|
|
- self.activerMode(Modes.StandardCp)
|
|
|
-
|
|
|
- def decorNouveau(self):
|
|
|
- """ouvre la fenetre 'decors' en mode edition"""
|
|
|
- self.afficheEcranEditionDecors()
|
|
|
- self.activerMode(Modes.StandardCp)
|
|
|
-
|
|
|
- ###############
|
|
|
-
|
|
|
- ############### maj des infos du panneau Pi a la selection/deselection d'un pion
|
|
|
- #voir a balancer tout ca dans une classe a part
|
|
|
-
|
|
|
- def majPanneauPi(self):
|
|
|
-
|
|
|
- if self.pionSelectionne():
|
|
|
- estCombattant = (self.pionSelectionne().numero < 10000)
|
|
|
- #affichage
|
|
|
- self.fenetre.ui.pi_actions.setEnabled(estCombattant)
|
|
|
- self.fenetre.ui.pi_finTour.setEnabled(estCombattant)
|
|
|
- self.fenetre.ui.pi_ongletsListes.setTabEnabled(0, estCombattant)
|
|
|
- self.fenetre.ui.pi_ongletsListes.setTabEnabled(1, estCombattant)
|
|
|
-
|
|
|
- ### maj la selection dans la liste d'ordre de jeu
|
|
|
- if estCombattant:
|
|
|
- for i in range(0, self.fenetre.ui.inf_listeOrdreJeu.rowCount()):
|
|
|
- if str(self.fenetre.ui.inf_listeOrdreJeu.item(i, 0).text().toUtf8()) == str(self.pionSelectionne().numero):
|
|
|
- self.fenetre.ui.inf_listeOrdreJeu.setCurrentCell(i,0)
|
|
|
-
|
|
|
- ### maj des infos dans le panneau pi
|
|
|
- self.fenetre.ui.pi_nom.majTexte(self.pionSelectionne().txtId())
|
|
|
- self.fenetre.ui.pi_img.chargerImage(self.pionSelectionne().img.rimage)
|
|
|
-
|
|
|
- ### maj de la liste des attributs
|
|
|
- if estCombattant:
|
|
|
- self.fenetre.ui.pi_listeAttributs.setColumnWidth(0, 50)
|
|
|
- self.disconnect(self.fenetre.ui.pi_listeAttributs, SIGNAL("cellChanged(int,int)"), self.listeAttributCelluleModifiee)
|
|
|
-
|
|
|
- #on vide la liste
|
|
|
- while self.fenetre.ui.pi_listeAttributs.rowCount() > 0:
|
|
|
- self.fenetre.ui.pi_listeAttributs.removeRow(0)
|
|
|
-
|
|
|
- #creation des lignes de base
|
|
|
- lignesBase = ["Nom","Etat","Alt."] #attention: modifier aussi dans listeAttributCelluleModifiee
|
|
|
- for i in range(0, 10): #10 premieres colonnes reservees pour les infos de base
|
|
|
- self.fenetre.ui.pi_listeAttributs.insertRow(i)
|
|
|
- item = QTableWidgetItem()
|
|
|
- if i < len(lignesBase):
|
|
|
- item.setText(QString.fromUtf8(lignesBase[i]))
|
|
|
- item.setFlags(Qt.NoItemFlags)
|
|
|
- self.fenetre.ui.pi_listeAttributs.setItem(i, 0, item)
|
|
|
- self.fenetre.ui.pi_listeAttributs.setRowHidden(i, (i >= len(lignesBase)))
|
|
|
-
|
|
|
- #maj des donnees de base
|
|
|
- self.fenetre.ui.pi_listeAttributs.setItem(lignesBase.index("Nom"), 1, QTableWidgetItem(QString.fromUtf8(str(self.pionSelectionne().nom))))
|
|
|
- self.fenetre.ui.pi_listeAttributs.setItem(lignesBase.index("Etat"), 1, QTableWidgetItem(QString.fromUtf8(str(self.pionSelectionne().etat))))
|
|
|
- self.fenetre.ui.pi_listeAttributs.setItem(lignesBase.index("Alt."), 1, QTableWidgetItem(QString.fromUtf8(str(self.pionSelectionne().z))))
|
|
|
-
|
|
|
- #attributs issus des regles utilisees
|
|
|
- ordre = regles.ordreAttributs()
|
|
|
- for elt in ordre:
|
|
|
- ligne = 10 + ordre.index(elt)
|
|
|
- self.fenetre.ui.pi_listeAttributs.insertRow(ligne)
|
|
|
- item = QTableWidgetItem(QString.fromUtf8(elt))
|
|
|
- item.setFlags(Qt.NoItemFlags)
|
|
|
- self.fenetre.ui.pi_listeAttributs.setItem(ligne, 0, item)
|
|
|
- self.fenetre.ui.pi_listeAttributs.setItem(ligne, 1, QTableWidgetItem(QString.fromUtf8(str(self.pionSelectionne().listeAttributs[elt]))))
|
|
|
-
|
|
|
- self.connect(self.fenetre.ui.pi_listeAttributs, SIGNAL("cellChanged(int,int)"), self.listeAttributCelluleModifiee)
|
|
|
-
|
|
|
- ###affiche les notes du combattant
|
|
|
- self.fenetre.ui.pi_notes.majTexte(self.pionSelectionne().notes)
|
|
|
-
|
|
|
- ###maj la liste des attaques du pion
|
|
|
- if estCombattant:
|
|
|
- #on vide la liste
|
|
|
- while self.fenetre.ui.pi_listeAttaques.rowCount() > 0:
|
|
|
- self.fenetre.ui.pi_listeAttaques.removeRow(0)
|
|
|
-
|
|
|
- i = 0
|
|
|
- for attaque in self.pionSelectionne().attaques:
|
|
|
- self.fenetre.ui.pi_listeAttaques.insertRow(i)
|
|
|
- self.fenetre.ui.pi_listeAttaques.setItem(i, 0, QTableWidgetItem(QString.fromUtf8(str(self.pionSelectionne().attaques.index(attaque)))))
|
|
|
- icone = None
|
|
|
- if attaque.typ == "cac":
|
|
|
- icone = QIcon(":/interface/16/ressource/epee_16.png")
|
|
|
- if attaque.typ == "dist":
|
|
|
- icone = QIcon(":/interface/16/ressource/arc_16.png")
|
|
|
- if attaque.typ == "zone":
|
|
|
- icone = QIcon(":/interface/16/ressource/baguette_16.png")
|
|
|
- if icone != None:
|
|
|
- self.fenetre.ui.pi_listeAttaques.setItem(i, 1, QTableWidgetItem(icone, QString.fromUtf8("")))
|
|
|
- self.fenetre.ui.pi_listeAttaques.setItem(i, 2, QTableWidgetItem(QString.fromUtf8(attaque.nom)))
|
|
|
-
|
|
|
- else:
|
|
|
- #maj des infos dans le panneau pi
|
|
|
- self.fenetre.ui.pi_img.clear()
|
|
|
- self.fenetre.ui.pi_nom.majTexte("Pas de pion\nselectionné")
|
|
|
-
|
|
|
- #vide la liste des attributs
|
|
|
- self.disconnect(self.fenetre.ui.pi_listeAttributs, SIGNAL("cellChanged(int,int)"), self.listeAttributCelluleModifiee)
|
|
|
- while self.fenetre.ui.pi_listeAttributs.rowCount() > 0:
|
|
|
- self.fenetre.ui.pi_listeAttributs.removeRow(0)
|
|
|
-
|
|
|
- #vide la liste des attaques du pion
|
|
|
- while self.fenetre.ui.pi_listeAttaques.rowCount() > 0:
|
|
|
- self.fenetre.ui.pi_listeAttaques.removeRow(0)
|
|
|
-
|
|
|
- self.majInfosAttaqueEC()
|
|
|
-
|
|
|
- ##### activation des differents modes d'interaction avec le plateau et mises a jour des principaux parametres #######
|
|
|
- def plateauModeCreation(self):
|
|
|
- self.activerMode(Modes.StandardCp)
|
|
|
-
|
|
|
- def plateauModeCombat(self):
|
|
|
- self.activerMode(Modes.StandardPi)
|
|
|
-
|
|
|
- def activerMode(self, mode, param = None):
|
|
|
- """desactive le mode actif et active le nouveau a la place"""
|
|
|
- self.modeActif.desactiver()
|
|
|
- self.modeActif = mode(self)
|
|
|
- self.modeActif.activer(param)
|
|
|
-
|
|
|
-## def majModeAffichage(self, index):
|
|
|
-## """met a jour le mode d'affichage"""
|
|
|
-## nouveauMode = ""
|
|
|
-## if index == 0:
|
|
|
-## #passe a l'affichage standard
|
|
|
-## pass
|
|
|
-## elif index == 1:
|
|
|
-## #passe en mode affichage de l'altitude
|
|
|
-## nouveauMode = "altitude"
|
|
|
-## elif index == 2:
|
|
|
-## #affichage des terrains slt
|
|
|
-## nouveauMode = "terrain"
|
|
|
-## elif index == 3:
|
|
|
-## #affichage tactique
|
|
|
-## nouveauMode = "tactique"
|
|
|
-##
|
|
|
-## for coord in self.cases:
|
|
|
-## self.cases[coord].majAffichageSpecial(nouveauMode)
|
|
|
-
|
|
|
- def modePeintureCase(self):
|
|
|
- """enclenche le mode peinture de case a partir de la couleur selectionnee"""
|
|
|
- couleur = self.chercherCouleur()
|
|
|
- if couleur.isValid():
|
|
|
- terrain = Terrain()
|
|
|
- terrain.couleur = couleur
|
|
|
- self.activerMode(Modes.MajCases, terrain)
|
|
|
- else:
|
|
|
- self.activerMode(Modes.StandardCp)
|
|
|
-
|
|
|
- def modePeintureCase_perso(self):
|
|
|
- origine = self.sender().objectName()
|
|
|
- index = int(origine.replace("cp_couleur",""))-1
|
|
|
- couleur = QColor()
|
|
|
- r, g, b = m_couleursRapides[index]
|
|
|
- couleur.setRgb(r, g, b)
|
|
|
- if couleur.isValid():
|
|
|
- terrain = Terrain()
|
|
|
- terrain.couleur = couleur
|
|
|
- self.activerMode(Modes.MajCases, terrain)
|
|
|
- else:
|
|
|
- self.activerMode(Modes.StandardCp)
|
|
|
-
|
|
|
- def modeCopieTerrain(self):
|
|
|
- """enclenche le mode copie de case"""
|
|
|
- self.activerMode(Modes.Pipette)
|
|
|
-
|
|
|
- def modeCaseEffet(self, index):
|
|
|
- """enclenche le mode de mise a jour de l'effet actif des cases"""
|
|
|
- effets = ["brule", "eau", "glace", "poison", "aucun"]
|
|
|
- self.activerMode(Modes.MajCasesEffet, effets[index])
|
|
|
-
|
|
|
- def modeCreationPion(self):
|
|
|
- """enclenche le mode de creation de pions simples"""
|
|
|
- self.majMode("pionCreation")
|
|
|
-
|
|
|
- def majModeSupprimerDecor(self):
|
|
|
- """enclenche le mode suppression de pions sur clic gauche (creatures ou decors)"""
|
|
|
- self.activerMode(Modes.SuppressionPion, Decor)
|
|
|
-
|
|
|
- def majModeSupprimerCombattant(self):
|
|
|
- """enclenche le mode suppression de pions sur clic gauche (creatures ou decors)"""
|
|
|
- self.activerMode(Modes.SuppressionPion, Combattant)
|
|
|
-
|
|
|
- def modeCreationDecor(self, ligne, col):
|
|
|
- """enclenche le mode de creation de decors depuis la liste des decors"""
|
|
|
- index = self.fenetre.ui.cp_listeDecors.item(ligne, 0)
|
|
|
- decor = charger("lib\\biblio\\decor", str(index.text().toUtf8()))
|
|
|
- self.activerMode(Modes.CreationPion, decor)
|
|
|
-
|
|
|
- def modeCreationCombattant(self, ligne, col):
|
|
|
- """enclenche le mode de creation de pions depuis la liste des creatures"""
|
|
|
- index = self.fenetre.ui.cp_listeCreatures.item(ligne, 0)
|
|
|
- creature = charger("lib\\biblio\\combattant", str(index.text().toUtf8()))
|
|
|
- self.activerMode(Modes.CreationPion, creature)
|
|
|
-
|
|
|
- def modeMajTerrainCase(self, ligne, col):
|
|
|
- """enclenche le mode permettant la mise a jour du terrain des cases"""
|
|
|
- index = self.fenetre.ui.cp_listeTerrains.item(ligne, 0)
|
|
|
- terrain = charger("lib\\biblio\\terrain", str(index.text().toUtf8()))
|
|
|
- if terrain:
|
|
|
- self.activerMode(Modes.MajCases, terrain)
|
|
|
- else:
|
|
|
- print "terrain invalide"
|
|
|
-
|
|
|
- def majEpaisseurPinceau(self, epaisseur):
|
|
|
- """met a jour l'epaisseur du pinceau (en cases)"""
|
|
|
- self.fenetre.ui.cp_valeurEpaisseurPinceau.majTexte(str(epaisseur))
|
|
|
- self.pinceau.majEpaisseur(int(epaisseur))
|
|
|
-
|
|
|
- def modeMajAltitudeCase(self):
|
|
|
- self.majMode("caseMajAltitude")
|
|
|
-
|
|
|
- def majModeForme(self):
|
|
|
- """met a jour la forme utilisee pour la peinture"""
|
|
|
- formes = {"cp_formeSimple": "simple", \
|
|
|
- "cp_formeLigne": "ligne", \
|
|
|
- "cp_formeLigneOrientee": "frontiere", \
|
|
|
- "cp_formePot": "pot", \
|
|
|
- "cp_formeEllipseVide": "ellipseV", \
|
|
|
- "cp_formeEllipsePlein": "ellipseP", \
|
|
|
- "cp_formeRectVide": "rectV", \
|
|
|
- "cp_formeRectPlein": "rectP"}
|
|
|
- self.pinceau.majForme(formes[str(self.sender().objectName())])
|
|
|
-
|
|
|
- def majModeCombatDeplacement(self):
|
|
|
- """active le mode de combat 'deplacement' (mode standard)"""
|
|
|
- self.modeActif.nouvelleAction(Actions.Deplacement)
|
|
|
-
|
|
|
- def majModeCombatVol(self):
|
|
|
- """active le mode de combat 'vol'"""
|
|
|
- self.modeActif.nouvelleAction(Actions.Vol)
|
|
|
-
|
|
|
- def majModeCombatAttaqueCaC(self):
|
|
|
- """active le mode de combat 'corps-a-corps'"""
|
|
|
- self.modeActif.nouvelleAction(Actions.Cac)
|
|
|
-
|
|
|
- def majModeCombatAttaqueDist(self):
|
|
|
- """active le mode de combat 'attaque a distance'"""
|
|
|
- self.modeActif.nouvelleAction(Actions.Distance)
|
|
|
-
|
|
|
- def majModeCombatZone(self):
|
|
|
- if self.fenetre.ui.pi_formeAttaqueZone.currentIndex() == 0:
|
|
|
- action = Actions.Ligne
|
|
|
- elif self.fenetre.ui.pi_formeAttaqueZone.currentIndex() == 1:
|
|
|
- action = Actions.Disque
|
|
|
- elif self.fenetre.ui.pi_formeAttaqueZone.currentIndex() == 2:
|
|
|
- action = Actions.Cone
|
|
|
- if action:
|
|
|
- self.modeActif.nouvelleAction(action)
|
|
|
-
|
|
|
- def majRayonZone(self, val):
|
|
|
- action = self.modeActif.action()
|
|
|
- if action:
|
|
|
- action.majRayon(val)
|
|
|
-
|
|
|
- def majModeDefinirEntree(self):
|
|
|
- self.activerMode(Modes.CreationEntreeSortie, "E")
|
|
|
-
|
|
|
- def majModeDefinirSortie(self):
|
|
|
- self.activerMode(Modes.CreationEntreeSortie, "S")
|
|
|
-
|
|
|
- def majModeZonePlacement(self):
|
|
|
- self.activerMode(Modes.ZonePlacement)
|
|
|
-
|
|
|
-
|
|
|
- ###############
|
|
|
-
|
|
|
- ########## Gestion du combat ##############
|
|
|
- def majAffichageTour(self):
|
|
|
- """met a jour l'affichage du tour en cours"""
|
|
|
- self.fenetre.ui.cbt_tour.majTexte("Tour: {}".format(self.tour))
|
|
|
-
|
|
|
- def initListeOrdreJeu(self):
|
|
|
- """cree les colonnes et met en forme la table ordre jeu"""
|
|
|
- self.fenetre.ui.inf_listeOrdreJeu.setColumnWidth(2, 30)
|
|
|
- self.fenetre.ui.inf_listeOrdreJeu.hideColumn(0)
|
|
|
- self.fenetre.ui.inf_listeOrdreJeu.hideColumn(2)
|
|
|
- self.fenetre.ui.inf_listeOrdreJeu.setIconSize(QSize(30,20))
|
|
|
-
|
|
|
- def majListeOrdreJeu(self):
|
|
|
- """met a jour la liste des pions infoOrdreJeu"""
|
|
|
- while self.fenetre.ui.inf_listeOrdreJeu.rowCount() > 0:
|
|
|
- self.fenetre.ui.inf_listeOrdreJeu.removeRow(0)
|
|
|
- index = 0
|
|
|
- for num in self.ordreJeu:
|
|
|
- self.fenetre.ui.inf_listeOrdreJeu.insertRow(int(index))
|
|
|
- self.fenetre.ui.inf_listeOrdreJeu.setItem(int(index), 0, QTableWidgetItem(QString.fromUtf8(str(num))))
|
|
|
- icon = QIcon(self.combattants[num].logo.chemin())
|
|
|
- item = QTableWidgetItem(icon, QString.fromUtf8(self.combattants[num].txtId()))
|
|
|
- self.fenetre.ui.inf_listeOrdreJeu.setItem(int(index), 1, item)
|
|
|
- self.fenetre.ui.inf_listeOrdreJeu.setItem(int(index), 2, QTableWidgetItem(QString.fromUtf8(str(self.ordreJeu[num]))))
|
|
|
- index += 1
|
|
|
-
|
|
|
- self.fenetre.ui.inf_listeOrdreJeu.sizeHintForColumn(1)
|
|
|
-## trierTable(self.fenetre.ui.infoOrdreJeu, 2, 0)
|
|
|
-
|
|
|
- def clicListOrdreJeu(self, ligne, col):
|
|
|
- """on a clique dans la liste d'ordre de jeu, le pion correspondant est selectionne et centre sur la carte"""
|
|
|
- numCombattant = int(self.fenetre.ui.inf_listeOrdreJeu.item(ligne, 0).text().toUtf8())
|
|
|
- self.vue().centerOn(self.cases[self.combattants[numCombattant].position].centreGraphique)
|
|
|
- self.modeActif.clic_combattant(numCombattant)
|
|
|
-
|
|
|
- def pionSuivant(self):
|
|
|
- """selection du pion suivant dans la liste d'ordre de jeu"""
|
|
|
- if self.numPionEnCours in self.combattants:
|
|
|
- suivant = self.ordreJeu[self.numPionEnCours] + 1
|
|
|
- else:
|
|
|
- suivant = 1
|
|
|
- if suivant > len(self.ordreJeu):
|
|
|
- self.tour += 1
|
|
|
- self.majAffichageTour()
|
|
|
- suivant = 1
|
|
|
- for num in self.ordreJeu:
|
|
|
- if self.ordreJeu[num] == suivant:
|
|
|
- numCombattant = num
|
|
|
- break
|
|
|
-
|
|
|
- for ligne in range(0, self.fenetre.ui.inf_listeOrdreJeu.rowCount()):
|
|
|
- item = self.fenetre.ui.inf_listeOrdreJeu.item(ligne, 0)
|
|
|
- item.setSelected(int(self.fenetre.ui.inf_listeOrdreJeu.item(ligne, 0).text().toUtf8()) == numCombattant)
|
|
|
- if int(item.text().toUtf8()) == numCombattant:
|
|
|
- self.fenetre.ui.inf_listeOrdreJeu.scrollToItem(item)
|
|
|
-
|
|
|
- self.vue().centerOn(self.cases[self.combattants[numCombattant].position].centreGraphique)
|
|
|
- self.pionSaisir(numCombattant)
|
|
|
-
|
|
|
- def afficheEcranGestionCombat(self):
|
|
|
- """affiche l'ecran de gestion du combat"""
|
|
|
- self.gestionCombat = EcranGestionCombat(self)
|
|
|
- self.gestionCombat.show()
|
|
|
- self.connect(self.fenetre, SIGNAL("majListesPions"), self.majListesPions)
|
|
|
- self.connect(self.gestionCombat, SIGNAL("majListesPions"), self.majListesPions)
|
|
|
- QApplication.processEvents()
|
|
|
-## r = self.gestionCombat.exec_()
|
|
|
-
|
|
|
- def majOrdreJeu(self):
|
|
|
- """met a jour l'ordre de jeu des pions en fonction de l'attribut prevu par les regles s'il existe,
|
|
|
- ou en fonction de l'ordre de jeu parametre sinon"""
|
|
|
- attribut = regles.attributOrdreJeu()
|
|
|
- if attribut != None:
|
|
|
- dico = {}
|
|
|
- for numCombattant in self.combattants:
|
|
|
- dico[numCombattant] = int(self.combattants[numCombattant].listeAttributs[attribut])
|
|
|
- ordre = sorted(dico, key = dico.get, reverse=(regles.sensTriOrdreJeu() == 1))
|
|
|
- self.ordreJeu = {}
|
|
|
- for numCombattant in self.combattants:
|
|
|
- self.ordreJeu[numCombattant] = ordre.index(numCombattant) + 1
|
|
|
- self.majListeOrdreJeu()
|
|
|
-
|
|
|
- def pionDeplacerDansOrdreJeu(self, numCombattant, nouvellePosition):
|
|
|
- """deplace un pion dans le dictionnaire gerant l'ordre de jeu de maniere a assurer sa coherence
|
|
|
- nouvellePosition = 0 supprime le pion de la liste"""
|
|
|
- if numCombattant in self.ordreJeu:
|
|
|
- if nouvellePosition == 0:
|
|
|
- del self.ordreJeu[numCombattant]
|
|
|
- if len(self.ordreJeu) > 0:
|
|
|
- i = 0
|
|
|
- tmp = sorted(self.ordreJeu, key=self.ordreJeu.get)
|
|
|
- if numCombattant in tmp:
|
|
|
- tmp.remove(numCombattant)
|
|
|
- for num in tmp:
|
|
|
- i += 1
|
|
|
- if i == nouvellePosition:
|
|
|
- self.ordreJeu[numCombattant] = i
|
|
|
- i += 1
|
|
|
- self.ordreJeu[num] = i
|
|
|
- if i < nouvellePosition:
|
|
|
- self.ordreJeu[numCombattant] = i + 1
|
|
|
- elif nouvellePosition > 0:
|
|
|
- self.ordreJeu[numCombattant] = 1
|
|
|
- self.majOrdreJeu()
|
|
|
-
|
|
|
-
|
|
|
- def listeAttributCelluleModifiee(self, ligne, colonne):
|
|
|
- """une cellule de la liste des attributs a ete modifiee"""
|
|
|
- if colonne != 1:
|
|
|
- print("valeur non modifiable")
|
|
|
- else:
|
|
|
- #on verifie la validite de la donnee entree
|
|
|
- lignesBase = ["Nom","Etat","Alt."] #attention: modifier aussi dans majListeAttribut
|
|
|
- if ligne < len(lignesBase):
|
|
|
- pass
|
|
|
- elif ligne >= 10:
|
|
|
- attribut = regles.ordreAttributs()[(ligne - 10)]
|
|
|
- nouvelleVal = str(self.fenetre.ui.pi_listeAttributs.item(ligne, 1).text().toUtf8())
|
|
|
- valVerifiee = regles.listeControle()[attribut].controler(nouvelleVal)
|
|
|
- if valVerifiee != None:
|
|
|
- self.pionSelectionne().listeAttributs[attribut] = valVerifiee
|
|
|
- if attribut == regles.attributOrdreJeu():
|
|
|
- print("maj ordre (a implementer)")
|
|
|
- else:
|
|
|
- self.fenetre.ui.pi_listeAttributs.setItem(ligne, 1, QTableWidgetItem(QString.fromUtf8(str(self.pionSelectionne().listeAttributs[attribut]))))
|
|
|
-
|
|
|
- def initListeAttaques(self):
|
|
|
- """met en forme et connecte la liste des attaques du pion"""
|
|
|
- self.fenetre.ui.pi_listeAttaques.setColumnWidth(0, 0)
|
|
|
- self.fenetre.ui.pi_listeAttaques.setColumnWidth(1, (0.3*self.fenetre.ui.pi_listeAttaques.width()))
|
|
|
- self.fenetre.ui.pi_listeAttaques.setColumnWidth(2, (0.7*self.fenetre.ui.pi_listeAttaques.width()))
|
|
|
- self.connect(self.fenetre.ui.pi_listeAttaques, SIGNAL("itemSelectionChanged()"), self.majInfosAttaqueEC)
|
|
|
- self.connect(self.fenetre.ui.pi_listeAttaques, SIGNAL("cellClicked(int, int)"), self.listeAttaquesCelluleCliquee)
|
|
|
- self.connect(self.fenetre.ui.pi_notesAttaqueEC, SIGNAL("textChanged()"), self.majNotesAttaqueEC)
|
|
|
- self.fenetre.ui.pi_listeAttributsAttaqueEC.setColumnWidth(0, (0.49*self.fenetre.ui.pi_listeAttributsAttaqueEC.width()))
|
|
|
- self.fenetre.ui.pi_listeAttributsAttaqueEC.setColumnWidth(1, (0.5*self.fenetre.ui.pi_listeAttributsAttaqueEC.width()))
|
|
|
-
|
|
|
- def majListeAttaques(self):
|
|
|
- """met a jour la liste des attaques du pion dans le panneau de combat"""
|
|
|
- #on vide la liste
|
|
|
- while self.fenetre.ui.pi_listeAttaques.rowCount() > 0:
|
|
|
- self.fenetre.ui.pi_listeAttaques.removeRow(0)
|
|
|
-
|
|
|
- self.fenetre.ui.pi_listeAttaques.setVisible((self.pionSelectionne() != None))
|
|
|
-## self.fenetre.ui.editerAttaques.setVisible((self.pionSelectionne() != None))
|
|
|
- self.fenetre.ui.pi_panneauAttaqueEC.setVisible((self.pionSelectionne() != None))
|
|
|
-
|
|
|
- i = 0
|
|
|
- if self.pionSelectionne() != None:
|
|
|
- for attaque in self.pionSelectionne().attaques:
|
|
|
- self.fenetre.ui.pi_listeAttaques.insertRow(i)
|
|
|
- self.fenetre.ui.pi_listeAttaques.setItem(i, 0, QTableWidgetItem(QString.fromUtf8(str(self.pionSelectionne().attaques.index(attaque)))))
|
|
|
- icone = None
|
|
|
- if attaque.typ == "cac":
|
|
|
- icone = QIcon(":/interface/16/ressource/epee_16.png")
|
|
|
- if attaque.typ == "dist":
|
|
|
- icone = QIcon(":/interface/16/ressource/arc_16.png")
|
|
|
- if attaque.typ == "zone":
|
|
|
- icone = QIcon(":/interface/16/ressource/baguette_16.png")
|
|
|
- if icone != None:
|
|
|
- self.fenetre.ui.pi_listeAttaques.setItem(i, 1, QTableWidgetItem(icone, QString.fromUtf8("")))
|
|
|
- self.fenetre.ui.pi_listeAttaques.setItem(i, 2, QTableWidgetItem(QString.fromUtf8(attaque.nom)))
|
|
|
- self.majInfosAttaqueEC()
|
|
|
-
|
|
|
- def listeAttaquesCelluleCliquee(self, ligne, colonne):
|
|
|
- """on a clique sur une cellule de la liste des attaques"""
|
|
|
- numAttaque = int(str(self.fenetre.ui.pi_listeAttaques.item(ligne, 0).text().toUtf8()))
|
|
|
- if numAttaque >= 0:
|
|
|
- self.utiliserAttaque(numAttaque)
|
|
|
-
|
|
|
- def utiliserAttaque(self, numAttaque):
|
|
|
- """le pion selectionne utilise son attaque n"""
|
|
|
- if self.pionSelectionne() != None:
|
|
|
- if numAttaque < len(self.pionSelectionne().attaques):
|
|
|
- attaque = self.pionSelectionne().attaques[numAttaque]
|
|
|
- if attaque.typ == "cac":
|
|
|
- self.majModeCombat("combatAttaqueCaC")
|
|
|
- if attaque.typ == "dist":
|
|
|
- self.majModeCombat("combatAttaqueDist")
|
|
|
- if attaque.typ == "zone":
|
|
|
- self.modeParam["typeAttaqueZone"] = attaque.formeZone
|
|
|
- self.fenetre.ui.pi_rayonAttaqueZone.setValue(attaque.rayon)
|
|
|
- self.majModeCombat("combatAttaqueZone")
|
|
|
-
|
|
|
- def majInfosAttaqueEC(self):
|
|
|
- """met a jour les infos de l'attaque en cours (selectionnee)"""
|
|
|
- selection = self.fenetre.ui.pi_listeAttaques.selectedItems()
|
|
|
- self.fenetre.ui.pi_panneauAttaqueEC.setVisible(self.pionSelectionne() != None and len(selection) > 0)
|
|
|
-
|
|
|
- if self.pionSelectionne() != None and len(selection) > 0:
|
|
|
- ligne = selection[0].row()
|
|
|
- numAttaque = int(str(self.fenetre.ui.pi_listeAttaques.item(ligne, 0).text().toUtf8()))
|
|
|
- self.disconnect(self.fenetre.ui.pi_panneauAttaqueEC, SIGNAL("cellChanged(int,int)"), self.attaqueECCelluleModifiee)
|
|
|
- #on vide la liste
|
|
|
- while self.fenetre.ui.pi_listeAttributsAttaqueEC.rowCount() > 0:
|
|
|
- self.fenetre.ui.pi_listeAttributsAttaqueEC.removeRow(0)
|
|
|
-
|
|
|
- self.fenetre.ui.pi_listeAttributsAttaqueEC.insertRow(0)
|
|
|
- self.fenetre.ui.pi_listeAttributsAttaqueEC.setItem(0, 0, QTableWidgetItem(QString.fromUtf8("numAtt")))
|
|
|
- self.fenetre.ui.pi_listeAttributsAttaqueEC.setItem(0, 1, QTableWidgetItem(QString.fromUtf8(str(numAttaque))))
|
|
|
- self.fenetre.ui.pi_listeAttributsAttaqueEC.setRowHidden(0, True)
|
|
|
-
|
|
|
- #attributs issus des regles utilisees
|
|
|
- ordre = regles.ordreAttributsAttaques()
|
|
|
- for elt in ordre:
|
|
|
- ligne = 1 + ordre.index(elt)
|
|
|
- self.fenetre.ui.pi_listeAttributsAttaqueEC.insertRow(ligne)
|
|
|
- item = QTableWidgetItem(QString.fromUtf8(elt))
|
|
|
- item.setFlags(Qt.NoItemFlags)
|
|
|
- self.fenetre.ui.pi_listeAttributsAttaqueEC.setItem(ligne, 0, item)
|
|
|
- self.fenetre.ui.pi_listeAttributsAttaqueEC.setItem(ligne, 1, QTableWidgetItem(QString.fromUtf8(str(self.pionSelectionne().attaques[numAttaque].attributs[elt]))))
|
|
|
-
|
|
|
- self.connect(self.fenetre.ui.pi_listeAttributsAttaqueEC, SIGNAL("cellChanged(int,int)"), self.attaqueECCelluleModifiee)
|
|
|
- #maj des notes
|
|
|
- self.disconnect(self.fenetre.ui.pi_notesAttaqueEC, SIGNAL("textChanged()"), self.majNotesAttaqueEC)
|
|
|
- self.fenetre.ui.pi_notesAttaqueEC.majTexte(self.pionSelectionne().attaques[numAttaque].notes)
|
|
|
- self.connect(self.fenetre.ui.pi_notesAttaqueEC, SIGNAL("textChanged()"), self.majNotesAttaqueEC)
|
|
|
-
|
|
|
- def attaqueECCelluleModifiee(self, ligne, colonne):
|
|
|
- """une cellule de la liste d'attributs de l'attaque en cours a ete modifiee"""
|
|
|
- pass
|
|
|
-
|
|
|
- def majNotesAttaqueEC(self):
|
|
|
- """met a jour les notes de l'attaque en cours (selectionnee)"""
|
|
|
- selection = self.fenetre.ui.pi_listeAttaques.selectedItems()
|
|
|
- self.fenetre.ui.pi_panneauAttaqueEC.setVisible(self.pionSelectionne() != None and len(selection) > 0)
|
|
|
- if self.pionSelectionne() != None and len(selection) > 0:
|
|
|
- ligne = selection[0].row()
|
|
|
- numAttaque = int(str(self.fenetre.ui.pi_listeAttaques.item(ligne, 0).text().toUtf8()))
|
|
|
- self.pionSelectionne().attaques[numAttaque].notes = str(self.fenetre.ui.pi_notesAttaqueEC.toPlainText().toUtf8())
|
|
|
-
|
|
|
- def majNotesCombattant(self):
|
|
|
- """les notes du pion ont ete mises a jour"""
|
|
|
- if self.pionSelectionne() != None:
|
|
|
- self.pionSelectionne().notes = str(self.fenetre.ui.pi_notes.toPlainText().toUtf8())
|
|
|
- else:
|
|
|
- pass
|
|
|
-
|
|
|
- ###############
|
|
|
-
|
|
|
- ### panneau d'info
|
|
|
- def majInfosCombattant(self, combattant=None):
|
|
|
- self.fenetre.ui.inf_boitePion.maj(combattant)
|
|
|
-
|
|
|
- def majInfosDecor(self, decor=None):
|
|
|
- self.fenetre.ui.inf_boiteDecor.maj(decor)
|
|
|
-
|
|
|
- def majInfosCase(self, case=None):
|
|
|
- self.fenetre.ui.inf_boiteCase.maj(case)
|
|
|
-
|
|
|
- ############### fonctions de calcul ################
|
|
|
- def coordonneesValides(self, coord):
|
|
|
- """les coordonnees entrees en parametre sont elles celles d'une case du plateau"""
|
|
|
- return (coord[0] >= 0 and coord[1] >= 0 and coord[0] < self.nbCasesX and coord[1] < self.nbCasesY)
|
|
|
-
|
|
|
- def lstCoordAdjacentes(self, x, y):
|
|
|
- """renvoie la liste des coordonnees adjacentes, !!!! sans condition d'existence sur le plateau !!!!
|
|
|
- attention: l'ordre est important"""
|
|
|
- if self.formeCases == "H":
|
|
|
- if 1 == (x % 2):
|
|
|
- voisins = [(x, y-1), (x+1, y), (x+1, y+1), (x, y+1), (x-1, y+1), (x-1, y)]
|
|
|
- else:
|
|
|
- voisins = [(x, y-1), (x+1, y-1), (x+1, y), (x, y+1), (x-1, y), (x-1, y-1)]
|
|
|
- else:
|
|
|
- voisins = [(x, y-1), (x+1, y), (x, y+1), (x-1, y)]
|
|
|
- return voisins
|
|
|
-
|
|
|
- def zone(self, origine, rayon, z=0, conditionFranchissable = False, conditionVisible = False):
|
|
|
- """renvoie un dictionnaire representant la liste des coordonnees des cases comprises dans la zone
|
|
|
- la zone en question est la liste des cases situees a une distance d des coordonnees d'origine
|
|
|
- z = 0 -> hauteur z de l'origine par rapport a l'altitude de la case
|
|
|
- conditionFranchissable = Vrai -> les cases infranchissables ne sont pas prises en compte
|
|
|
- conditionVisible = Vrai -> les cases bloquant la visibilite ne sont pas prises en compte"""
|
|
|
- aVerifier = []
|
|
|
- aVerifier2 = []
|
|
|
- resultat = {}
|
|
|
- k = 0
|
|
|
- #on part de la premiere case, puis on itere a partir de chaque nouveau depart sur les voisins
|
|
|
- if origine in self.cases:
|
|
|
- aVerifier.append(origine)
|
|
|
- while k <= rayon:
|
|
|
- for depart in aVerifier:
|
|
|
- for coord in self.cases[depart].voisins:
|
|
|
- if not coord in aVerifier and not coord in aVerifier2 and not coord in resultat:
|
|
|
- if conditionFranchissable and not conditionVisible:
|
|
|
- if self.cases[coord].estFranchissable(z):
|
|
|
- aVerifier2.append(coord)
|
|
|
- elif not conditionFranchissable and conditionVisible:
|
|
|
- if self.cases[coord].terrain.visibilite:
|
|
|
- aVerifier2.append(coord)
|
|
|
- elif conditionFranchissable and conditionVisible:
|
|
|
- if self.cases[coord].estFranchissable(z) and self.cases[coord].terrain.visibilite:
|
|
|
- aVerifier2.append(coord)
|
|
|
- else:
|
|
|
- aVerifier2.append(coord)
|
|
|
- for elt in aVerifier:
|
|
|
- resultat[elt] = k
|
|
|
- aVerifier = aVerifier2
|
|
|
- aVerifier2 = []
|
|
|
- k += 1
|
|
|
-
|
|
|
- return resultat
|
|
|
-
|
|
|
- def zone3d(self, origine, rayon, zCible=0):
|
|
|
- """renvoie les cases de la zone au format (x, y, z)"""
|
|
|
- retour = []
|
|
|
- zone = self.zone(origine, rayon)
|
|
|
- for coord in zone:
|
|
|
- x, y = coord
|
|
|
- dz = rayon - zone[coord]
|
|
|
- for z in range(-dz, dz + 1):
|
|
|
- retour.append( (x, y, (zCible+z) ) )
|
|
|
- return retour
|
|
|
-
|
|
|
- def polygoneAgglo(self, listeCases):
|
|
|
- """renvoie un polygone contruit par agglomeration des polygones des cases de la liste
|
|
|
- les cases doivent etre adjacentes (cases hexagonales ou carrees)"""
|
|
|
- pointsPolygone = []
|
|
|
- segments = []
|
|
|
- case = Case(self)
|
|
|
-
|
|
|
- #on verifie que toutes les cases sont adjacentes les unes aux autres
|
|
|
- valide = True
|
|
|
- if len(listeCases) > 1:
|
|
|
- for coord in listeCases:
|
|
|
- if not len(set(listeCases).intersection(self.lstCoordAdjacentes(coord[0], coord[1]))) > 0: valide = False
|
|
|
- if not len(listeCases) > 0:
|
|
|
- valide = False
|
|
|
-
|
|
|
- if valide:
|
|
|
- #on parcourt les faces des polygones des cases, et on ne garde que ceux qui n'ont pas de case 'en face'
|
|
|
- for coord in listeCases:
|
|
|
- polygone = case.polygone(coord[0], coord[1])
|
|
|
- voisins = self.lstCoordAdjacentes(coord[0], coord[1])
|
|
|
-
|
|
|
- for i in range(0, len(voisins)):
|
|
|
- if not voisins[i] in listeCases:
|
|
|
- j = i+1
|
|
|
- if j > len(voisins) - 1:
|
|
|
- j = 0
|
|
|
- segments.append(QLineF(polygone[i], polygone[j]))
|
|
|
-
|
|
|
- #on 'accroche' les segments les uns aux autres, dans l'ordre
|
|
|
- segments2 = [segments[0]]
|
|
|
- for segment2 in segments2:
|
|
|
- for segment in segments:
|
|
|
- if not QLineF(segment.p1(), segment.p2()) in segments2 and not QLineF(segment.p2(), segment.p1()) in segments2:
|
|
|
- if sqrt((segment.p1().x()-segment2.p2().x())**2+(segment.p1().y()-segment2.p2().y())**2) < 1:
|
|
|
- segments2.append(QLineF(segment.p1(), segment.p2()))
|
|
|
- elif sqrt((segment.p2().x()-segment2.p2().x())**2+(segment.p2().y()-segment2.p2().y())**2) < 1:
|
|
|
- segments2.append(QLineF(segment.p2(), segment.p1()))
|
|
|
-
|
|
|
- pointsPolygone = []
|
|
|
- premierPoint = segments2[0].p1()
|
|
|
- pointsPolygone.append(premierPoint)
|
|
|
- for segment in segments2:
|
|
|
- pointSuivant = segment.p2()
|
|
|
- if pointSuivant != premierPoint:
|
|
|
- pointsPolygone.append(pointSuivant)
|
|
|
-
|
|
|
- #creation du polygone
|
|
|
- polygone = QPolygonF()
|
|
|
- for point in pointsPolygone:
|
|
|
- polygone.append(point)
|
|
|
- else:
|
|
|
- polygone = None
|
|
|
-
|
|
|
- return polygone
|
|
|
-
|
|
|
- def coordCentreListeCases(self, listeCases):
|
|
|
- """renvoie les coordonnees centrales d'une liste de cases"""
|
|
|
- retour = None
|
|
|
- if len(listeCases) > 0:
|
|
|
- listeTriee = sorted(listeCases)
|
|
|
- posMilieu = int(len(listeCases)/2)
|
|
|
- retour = listeTriee[posMilieu]
|
|
|
- return retour
|
|
|
-
|
|
|
- def coordonneesAuPoint(self, point):
|
|
|
- """renvoie les coordonnees de la case situee au QPointF entre en parametre"""
|
|
|
- coord = None
|
|
|
- if point != None:
|
|
|
- lstObjets = self.vue().scene().items(point)
|
|
|
- for objet in lstObjets:
|
|
|
- if objet:
|
|
|
- if objet.__class__.__name__ == "Case":
|
|
|
- coord = (objet.x, objet.y)
|
|
|
- break
|
|
|
- return coord
|
|
|
-
|
|
|
- def casesSousForme(self, forme, plein = True, epaisseur = 0):
|
|
|
- """renvoie la liste des cases en collision avec un QGraphicsItem en parametre
|
|
|
- plein = False: pas le contenu de la forme
|
|
|
- epaisseur = renvoie aussi les cases voisines jusqu'a la distance demandee"""
|
|
|
- tmp = []
|
|
|
- listeCases = []
|
|
|
- point1 = None
|
|
|
- point2 = None
|
|
|
- #point 1 et 2
|
|
|
- if forme.__class__.__name__ == "QGraphicsLineItem":
|
|
|
- point1 = forme.line().p1()
|
|
|
- point2 = forme.line().p2()
|
|
|
- elif forme.__class__.__name__ == "QGraphicsRectItem" or forme.__class__.__name__ == "QGraphicsEllipseItem":
|
|
|
- point1 = forme.rect().topLeft()
|
|
|
- point2 = forme.rect().bottomRight()
|
|
|
- else:
|
|
|
- point1 = forme.boundingRect().topLeft()
|
|
|
- point2 = forme.boundingRect().bottomRight()
|
|
|
-
|
|
|
- #preselection des cases (meilleures perf)
|
|
|
- if point1 != None and point2 != None and point1 != point2:
|
|
|
- preSelection = self.preSelectionCollision(point1, point2)
|
|
|
- else:
|
|
|
- preSelection = []
|
|
|
- for coord in self.cases:
|
|
|
- preSelection.append(coord)
|
|
|
-
|
|
|
- #on liste les cases en collision avec la forme
|
|
|
- for coord in preSelection:
|
|
|
- if self.cases[coord].collidesWithItem(forme, Qt.IntersectsItemShape):
|
|
|
- if plein:
|
|
|
- tmp.append(coord)
|
|
|
- else:
|
|
|
- contenu = True
|
|
|
- for i in range(0,len(self.cases[coord].polygon())):
|
|
|
- if not forme.contains(self.cases[coord].polygon().at(i)):
|
|
|
- contenu = False
|
|
|
- break
|
|
|
- if contenu == False:
|
|
|
- tmp.append(coord)
|
|
|
- #on applique l'epaisseur du pinceau (lignes ou formes vides seulement) si necessaire
|
|
|
- if not plein and epaisseur > 0:
|
|
|
- for coord in tmp:
|
|
|
- zone = self.zone(coord, epaisseur)
|
|
|
- for coord2 in zone:
|
|
|
- if not coord2 in listeCases:
|
|
|
- listeCases.append(coord2)
|
|
|
- else:
|
|
|
- listeCases = tmp
|
|
|
- #si la liste est vide, on ajoute l'origine de la forme
|
|
|
- if len(listeCases) == 0:
|
|
|
- listeCases = [self.coordonneesAuPoint(point1)]
|
|
|
- return listeCases
|
|
|
-
|
|
|
- def preSelectionCollision(self, point1, point2):
|
|
|
- """renvoie une liste des cases qui peuvent etre concernees par une collision avec
|
|
|
- un graphicsItem (pour des raisons de performance)"""
|
|
|
- preSelection = []
|
|
|
- coord1 = self.coordonneesAuPoint(point1)
|
|
|
- coord2 = self.coordonneesAuPoint(point2)
|
|
|
- if coord1 != None and coord2 != None:
|
|
|
- minX = min(coord1[0], coord2[0]) - 1
|
|
|
- maxX = max(coord1[0], coord2[0]) + 1
|
|
|
- minY = min(coord1[1], coord2[1]) - 1
|
|
|
- maxY = max(coord1[1], coord2[1]) + 1
|
|
|
- for coord in self.cases:
|
|
|
- if coord[0] >= minX and coord[0] <= maxX and coord[1] >= minY and coord[1] <= maxY :
|
|
|
- preSelection.append(coord)
|
|
|
- else:
|
|
|
- preSelection = self.cases
|
|
|
- return preSelection
|
|
|
-
|
|
|
- def listeZCible(self, coord):
|
|
|
- """retourne l'altitude absolue a prendre en compte en fonction de la case ciblee
|
|
|
- c'est l'altitude la case si aucun pion n'occupe la case
|
|
|
- c'est la liste des cases occupees en hauteur par le pion sinon
|
|
|
- 'coord' est de la forme (x, y)"""
|
|
|
- if self.cases[coord].estOccupee():
|
|
|
- retour = range(self.cases[coord].occupant().zAbs(), \
|
|
|
- self.cases[coord].occupant().zAbs() + self.cases[coord].occupant().hauteur)
|
|
|
- else:
|
|
|
- retour = [self.cases[coord].altitude]
|
|
|
- return retour
|
|
|
-
|
|
|
- def estCibleAttaqueDistValide(self, coordCible):
|
|
|
- """la case cible est elle valide pour une attaque a distance depuis la position et hauteur
|
|
|
- du pion selectionne
|
|
|
- les coord sont de la forme (x, y)"""
|
|
|
- valide = False
|
|
|
- x1, y1 = self.pionSelectionne().position
|
|
|
- coordOrigine = (x1, y1, (self.pionSelectionne().zAbs() + self.pionSelectionne().hauteur))
|
|
|
-
|
|
|
- x2, y2 = coordCible
|
|
|
- cible = self.cases[coordCible].occupant()
|
|
|
- listeZ2 = self.listeZCible(coordCible)
|
|
|
- if coordOrigine[0] != coordCible[0] or coordOrigine[1] != coordCible[1]:
|
|
|
- for z2 in listeZ2:
|
|
|
- zValide = True
|
|
|
- casesLigneMire = br.ligne(coordOrigine, (x2, y2, z2), self.formeCases)
|
|
|
- casesLigneMire.remove(coordOrigine)
|
|
|
- casesLigneMire.remove((x2, y2, z2))
|
|
|
- for coord in casesLigneMire:
|
|
|
- if zValide:
|
|
|
- x, y, z = coord
|
|
|
- if self.cases[(x,y)].estOccupee(z):
|
|
|
- if self.cases[(x,y)].occupant(z) not in [self.pionSelectionne(), cible]:
|
|
|
- zValide = False
|
|
|
- if zValide:
|
|
|
- valide = True #si au moins un des z cibles est valide, la ligne de mire est valide
|
|
|
- break
|
|
|
-
|
|
|
- return valide
|
|
|
-
|
|
|
- def pionSurCase(self, coord):
|
|
|
- """renvoie le pion present sur la case, none sinon"""
|
|
|
- retour = None
|
|
|
- for num in self.combattants:
|
|
|
- if self.combattants[num].position == coord:
|
|
|
- retour = num
|
|
|
- return retour
|
|
|
-
|
|
|
- def pionsSurListeCase(self, listeCases):
|
|
|
- """renvoie la liste des num des pions presents sur la liste de cases"""
|
|
|
- retour = []
|
|
|
- for coord in listeCases:
|
|
|
- pion = self.cases[coord].occupant()
|
|
|
- if pion != None and not pion.numero in retour:
|
|
|
- retour.append(pion.numero)
|
|
|
- return retour
|
|
|
-
|
|
|
- def majZonePlacement(self, listeCases):
|
|
|
- """met a jour la forme et l'affichage de la zone de placement initale des joueurs"""
|
|
|
- if len(listeCases) > 0:
|
|
|
- if self.polygoneZonePlacement == None:
|
|
|
- self.polygoneZonePlacement = QGraphicsPolygonItem(scene=self)
|
|
|
- self.polygoneZonePlacement.setZValue(0)
|
|
|
- qCouleurFond = QColor("white")
|
|
|
- qCouleurFond.setAlpha(50)
|
|
|
- self.polygoneZonePlacement.setBrush(qCouleurFond)
|
|
|
- pinceau = QPen(QColor("orange"))
|
|
|
- pinceau.setWidth(20)
|
|
|
- self.polygoneZonePlacement.setPen(pinceau)
|
|
|
- self.polygoneZonePlacement.setAcceptedMouseButtons(Qt.NoButton)
|
|
|
- self.polygoneZonePlacement.setAcceptHoverEvents(False)
|
|
|
- self.addItem(self.polygoneZonePlacement)
|
|
|
- listeCases2 = []
|
|
|
- for coord in listeCases:
|
|
|
- if self.cases[coord].estFranchissable():
|
|
|
- listeCases2.append(coord)
|
|
|
- self.polygoneZonePlacement.setPolygon(self.polygoneAgglo(listeCases2))
|
|
|
- self.listeCasesZonePlacement = listeCases
|
|
|
-
|
|
|
- def materialiserPions(self,actif):
|
|
|
- """avtive/desactive la reception par les pions (autres que le pion selectionne) des hover events"""
|
|
|
- for numCombattant in self.combattants:
|
|
|
- if numCombattant != self.modeParam["numPionSelectionne"]:
|
|
|
- self.combattants[numCombattant].setAcceptsHoverEvents(actif)
|
|
|
- self.combattants[numCombattant].polygoneGraphique.setAcceptsHoverEvents(actif)
|
|
|
- for numCombattant in self.decors:
|
|
|
- self.decors[numCombattant].setAcceptsHoverEvents(actif)
|
|
|
- self.decors[numCombattant].polygoneGraphique.setAcceptsHoverEvents(actif)
|
|
|
-
|
|
|
- #######################
|
|
|
-
|
|
|
- ######## interaction avec les cases, decors et pions #############
|
|
|
- def pionSelectionne(self):
|
|
|
- """renvoie le pion actuellement selectionne"""
|
|
|
- retour = None
|
|
|
- if self.modeActif.__class__.__name__ == "PionSelectionne":
|
|
|
- retour = self.modeActif.pion()
|
|
|
- return retour
|
|
|
-
|
|
|
- def caseCliquee(self, x, y):
|
|
|
- """on a clique sur la case (clic gauche)"""
|
|
|
- coord = (x, y)
|
|
|
- self.modeActif.clic_case(coord)
|
|
|
-
|
|
|
- def caseSurvolClicEnfonce(self, coord):
|
|
|
- """une case est survolee par le curseur (le clic gauche est enfonce)"""
|
|
|
- self.modeActif.survolClic_case(coord)
|
|
|
-
|
|
|
- def caseSurvol(self, x, y):
|
|
|
- """une case est survole par le curseur, on affiche ses informations dans la zone prevue"""
|
|
|
- self.majInfosCase(self.cases[(x,y)])
|
|
|
- self.modeActif.survol_case((x,y))
|
|
|
-
|
|
|
- def afficherListeCases(self, listeCases, actif):
|
|
|
- """met ou non en evidence les cases selectionnees"""
|
|
|
- for coord in listeCases:
|
|
|
- self.cases[coord].majEstCibleCurseur(actif)
|
|
|
-
|
|
|
- def pionClique(self, num):
|
|
|
- """on a clique sur ce pion"""
|
|
|
- if num < 10000:
|
|
|
- self.modeActif.clic_combattant(num)
|
|
|
- else:
|
|
|
- self.modeActif.clic_decor(num)
|
|
|
-
|
|
|
- def combattantSurvol(self, num):
|
|
|
- """le pion est survole par le curseur, on affiche ses informations dans la zone prevue"""
|
|
|
- self.modeActif.survol_combattant(num)
|
|
|
- pion = self.combattants[num]
|
|
|
- self.majInfosCombattant(pion)
|
|
|
- self.caseSurvol(pion.position[0], pion.position[1])
|
|
|
-
|
|
|
- def combattantFinSurvol(self, num):
|
|
|
- """le pion est survole par le curseur, on affiche ses informations dans la zone prevue"""
|
|
|
- self.modeActif.finSurvol_combattant(num)
|
|
|
- self.majInfosCombattant(None)
|
|
|
-
|
|
|
- def decorSurvol(self, num):
|
|
|
- """le pion est survole par le curseur, on affiche ses informations dans la zone prevue"""
|
|
|
- self.modeActif.survol_decor(num)
|
|
|
- pion = self.decors[num]
|
|
|
- self.majInfosDecor(pion)
|
|
|
- self.caseSurvol(pion.position[0], pion.position[1])
|
|
|
-
|
|
|
- def decorFinSurvol(self, num):
|
|
|
- """le pion est survole par le curseur, on affiche ses informations dans la zone prevue"""
|
|
|
- self.modeActif.finSurvol_decor(num)
|
|
|
- self.majInfosDecor(None)
|
|
|
-
|
|
|
- def pionDoubleClic(self, numCombattant):
|
|
|
- """on a double-clique sur le pion"""
|
|
|
- self.modeActif.doubleClic_combattant(numCombattant)
|
|
|
-
|
|
|
- def creerPion(self, pionModele):
|
|
|
- """creer un pion (combattant ou decor) aux coordonnees indiquees"""
|
|
|
- cree = False
|
|
|
- if self.proj.projectionValide():
|
|
|
-
|
|
|
- if pionModele.__class__.__name__ == "Combattant":
|
|
|
- pion = Combattant()
|
|
|
- elif pionModele.__class__.__name__ == "Decor":
|
|
|
- pion = Decor()
|
|
|
-
|
|
|
- for elt in pionModele.__dict__:
|
|
|
- pion.__dict__[elt] = pionModele.__dict__[elt]
|
|
|
-
|
|
|
- if pionModele.__class__.__name__ == "Combattant":
|
|
|
- numero = 1
|
|
|
- if len(self.combattants) > 0:
|
|
|
- numero = max(self.combattants) + 1
|
|
|
- pion.numero = numero
|
|
|
- pion.numComplementaire = self.numeroterNom(pion.nom)
|
|
|
- self.combattants[numero] = pion
|
|
|
- self.pionDeplacerDansOrdreJeu(numero, len(self.ordreJeu) + 2)
|
|
|
-
|
|
|
- elif pionModele.__class__.__name__ == "Decor":
|
|
|
- numero = 10001
|
|
|
- if len(self.decors) > 0:
|
|
|
- numero = max(self.decors) + 10001
|
|
|
- pion.numero = numero
|
|
|
- self.decors[numero] = pion
|
|
|
-
|
|
|
- pion.position = self.proj.coord()
|
|
|
- pion.nbRotations = self.proj.nbRotations()
|
|
|
- pion.ajouterAuPlateau(self)
|
|
|
-
|
|
|
- cree = True
|
|
|
- return cree
|
|
|
-
|
|
|
- def numeroterNom(self, nom):
|
|
|
- """renvoie le nom du pion avec un numero complementaire si necessaire """
|
|
|
- i = 1
|
|
|
- for numCombattant in self.combattants:
|
|
|
- if self.combattants[numCombattant].nom == nom:
|
|
|
- i += 1
|
|
|
- if i == 1:
|
|
|
- retour = ""
|
|
|
- else:
|
|
|
- retour = str(i)
|
|
|
- return retour
|
|
|
-
|
|
|
- def pionDeposer(self, coordCase):
|
|
|
- """on depose le pion sur la case voulue"""
|
|
|
- if self.pionSelectionne() != None:
|
|
|
- pion = self.pionSelectionne()
|
|
|
-
|
|
|
- if pion != None:
|
|
|
- if self.proj.projectionValide():
|
|
|
- pion.majPosition(self.proj.coord(), self.proj.nbRotations())
|
|
|
-
|
|
|
- def majZPion(self, valeur):
|
|
|
- """met a jour l'altitude du pion selectionne"""
|
|
|
- if self.pionSelectionne() != None:
|
|
|
- self.pionSelectionne().majZ(valeur)
|
|
|
-
|
|
|
- def dialogueVol(self, actuelle):
|
|
|
- ecran = EcranVol(actuelle)
|
|
|
- ecran.exec_()
|
|
|
- nouvelle = ecran.resultat()
|
|
|
- del ecran
|
|
|
- return nouvelle
|
|
|
-
|
|
|
- def pionSupprimer(self, num):
|
|
|
- """supprime le pion entre en parametre"""
|
|
|
- #settrace(trace_calls)
|
|
|
- if num in self.combattants:
|
|
|
- self.pionDeplacerDansOrdreJeu(num, 0)
|
|
|
- pionSuppr = self.combattants.pop(num)
|
|
|
- elif num in self.decors:
|
|
|
- pionSuppr = self.decors.pop(num)
|
|
|
-
|
|
|
- pionSuppr.retirerDuPlateau()
|
|
|
-
|
|
|
- ###############
|
|
|
-
|
|
|
- ######### caches ###############
|
|
|
- def activerModeCreationCache(self):
|
|
|
- self.activerMode(Modes.EditerCaches)
|
|
|
-
|
|
|
- def activerModeEditionCache(self):
|
|
|
- idCache = int(self.fenetre.ui.cp_listeCaches.texte(self.fenetre.ui.cp_listeCaches.currentRow(), 0))
|
|
|
- self.activerMode(Modes.EditerCaches, idCache)
|
|
|
-
|
|
|
- def initListeCaches(self):
|
|
|
- """charge la liste des caches avec les donnees en memoire"""
|
|
|
- self.fenetre.ui.cp_listeCaches.setColumnWidth(0, 10)
|
|
|
- self.fenetre.ui.cp_listeCaches.setColumnWidth(1, 100)
|
|
|
- self.fenetre.ui.cp_listeCaches.setColumnWidth(2, 18)
|
|
|
- for idCache in self.caches:
|
|
|
- self.ajouterCacheATable(self.caches[idCache])
|
|
|
-
|
|
|
- def nouveauCache(self, listeCases):
|
|
|
- nouvelId = 0
|
|
|
- if len(self.caches) > 0:
|
|
|
- nouvelId = max(self.caches) + 1
|
|
|
- cache = Cache(nouvelId)
|
|
|
- cache.activer(True)
|
|
|
- cache.nom = "Cache {}".format(nouvelId + 1)
|
|
|
- self.caches[nouvelId] = cache
|
|
|
- self.ajouterCacheATable(cache)
|
|
|
- for coord in listeCases:
|
|
|
- self.cases[coord].ajouterCache(nouvelId)
|
|
|
-
|
|
|
- def editerFormeCache(self, idCache, listeCases):
|
|
|
- """edite le cache avec la liste des cases en param"""
|
|
|
- actif = self.caches[idCache].actif()
|
|
|
- for coord in self.cases:
|
|
|
- if coord in listeCases:
|
|
|
- self.cases[coord].ajouterCache(idCache, actif)
|
|
|
- else:
|
|
|
- self.cases[coord].supprimerCache(idCache)
|
|
|
-
|
|
|
- def majEtatCache(self, actif):
|
|
|
- emetteur = self.sender().objectName()
|
|
|
- idCache = int(emetteur.replace("afficherCache_", ""))
|
|
|
- self.caches[idCache].activer(actif)
|
|
|
- if actif:
|
|
|
- nomImg = "oeilBarre2_32.png"
|
|
|
- else:
|
|
|
- nomImg = "oeil_32.png"
|
|
|
- self.fenetre.ui.cp_listeCaches.item(idCache, 1).setIcon(QIcon(":/interface/32/ressource/{}".format(nomImg)))
|
|
|
- for coord in self.cases:
|
|
|
- self.cases[coord].activerCache(idCache, actif)
|
|
|
-
|
|
|
- def majNomCache(self, ligne, colonne):
|
|
|
- idCache = int(self.fenetre.ui.cp_listeCaches.texte(ligne, 0))
|
|
|
- nouveauNom = self.fenetre.ui.cp_listeCaches.texte(ligne, 1)
|
|
|
- if nouveauNom != self.caches[idCache].nom:
|
|
|
- self.caches[idCache].nom = nouveauNom
|
|
|
-
|
|
|
- def supprimerCache(self):
|
|
|
- ligne = self.fenetre.ui.cp_listeCaches.currentRow()
|
|
|
- idCache = int(self.fenetre.ui.cp_listeCaches.texte(ligne, 0))
|
|
|
- for coord in self.cases:
|
|
|
- self.cases[coord].supprimerCache(idCache)
|
|
|
- self.fenetre.ui.cp_listeCaches.removeRow(idCache)
|
|
|
- del self.caches[idCache]
|
|
|
-
|
|
|
- def mettreCacheEnEvidence(self, ligne, colonne):
|
|
|
- idCache = int(self.fenetre.ui.cp_listeCaches.texte(ligne, 0))
|
|
|
- for coord in self.cases:
|
|
|
- if len(self.cases[coord].cachesActifs) > 0:
|
|
|
- self.cases[coord].polygoneCache.activerSurbrillance((idCache in self.cases[coord].cachesActifs))
|
|
|
-
|
|
|
- def ajouterCacheATable(self, cache):
|
|
|
- """ajoute le cache a la table des caches"""
|
|
|
- self.fenetre.disconnect(self.fenetre.ui.cp_listeCaches, SIGNAL("cellChanged(int,int)"), self.majNomCache)
|
|
|
- ligne = self.fenetre.ui.cp_listeCaches.nouvelleLigneFin()
|
|
|
- if cache.actif():
|
|
|
- nomImg = "oeilBarre2_32.png"
|
|
|
- else:
|
|
|
- nomImg = "oeil_32.png"
|
|
|
- self.fenetre.ui.cp_listeCaches.majTexte(ligne, 0, str(cache.numero))
|
|
|
-
|
|
|
- item = QTableWidgetItem(QIcon(":/interface/32/ressource/{}".format(nomImg)), cache.nom)
|
|
|
- item.setFlags(Qt.ItemIsEnabled | Qt.ItemIsSelectable | Qt.ItemIsEditable)
|
|
|
- self.fenetre.ui.cp_listeCaches.setItem(ligne, 1, item)
|
|
|
-
|
|
|
- widget = QCheckBox(QString(""))
|
|
|
- widget.setChecked(cache.actif())
|
|
|
- widget.setObjectName(QString("afficherCache_{}".format(ligne)))
|
|
|
- self.connect(widget, SIGNAL("toggled(bool)"), self.majEtatCache)
|
|
|
- self.fenetre.ui.cp_listeCaches.setCellWidget(ligne, 2, widget)
|
|
|
-
|
|
|
- self.fenetre.connect(self.fenetre.ui.cp_listeCaches, SIGNAL("cellChanged(int,int)"), self.majNomCache, Qt.UniqueConnection)
|
|
|
- ###############"
|
|
|
-
|
|
|
- ######### gestion des evenements souris et clavier ###############
|
|
|
- def mouseMoveEvent(self, event):
|
|
|
- super(Plateau, self).mouseMoveEvent(event)
|
|
|
- if event.buttons() == Qt.LeftButton and self.vue().dragMode() != QGraphicsView.ScrollHandDrag:
|
|
|
- coord = self.coordonneesAuPoint(event.scenePos())
|
|
|
- if coord != None:
|
|
|
- self.caseSurvolClicEnfonce(coord)
|
|
|
- else:
|
|
|
- self.modeActif.mouvementSouris(event)
|
|
|
- event.ignore()
|
|
|
-
|
|
|
- def mousePressEvent(self, event):
|
|
|
- super(Plateau, self).mousePressEvent(event)
|
|
|
- if event.button() == 1:
|
|
|
- self.modeActif.clicGauche(event)
|
|
|
- elif event.button() == 2:
|
|
|
- self.modeActif.clicDroit(event)
|
|
|
- event.accept()
|
|
|
-
|
|
|
- def mouseReleaseEvent(self, event):
|
|
|
- super(Plateau, self).mouseReleaseEvent(event)
|
|
|
- self.modeActif.finClicGauche(event)
|
|
|
-
|
|
|
- def keyPressEvent(self, event):
|
|
|
- """gestion des evenements clavier"""
|
|
|
- self.modeActif.toucheClavier(event)
|
|
|
-
|
|
|
- ################
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
+#from __future__ import unicode_literals
|
|
|
+# -*- coding: utf-8 -*-
|
|
|
+from __future__ import division
|
|
|
+
|
|
|
+from PyQt4.QtCore import *
|
|
|
+from PyQt4.QtGui import *
|
|
|
+
|
|
|
+##from ui.ecran_editionAttaques import Ui_editionAttaques
|
|
|
+
|
|
|
+import Modes
|
|
|
+import Actions
|
|
|
+from Case import Case
|
|
|
+from Combattant import Combattant
|
|
|
+from Decor import Decor
|
|
|
+from Pinceau import Pinceau
|
|
|
+from ProjectionDep import ProjectionDep
|
|
|
+from Cache import Cache
|
|
|
+from Terrain import Terrain
|
|
|
+
|
|
|
+from EcranEditionCombattant import EcranEditionCombattant
|
|
|
+from EcranEditionDecor import EcranEditionDecor
|
|
|
+from EcranEditionTerrain import EcranEditionTerrain
|
|
|
+from EcranAffichageTexte import EcranAffichageTexte
|
|
|
+from EcranGestionCombat import EcranGestionCombat
|
|
|
+from EcranSelectionPj import EcranSelectionPj
|
|
|
+from EcranVol import EcranVol
|
|
|
+
|
|
|
+import regles as regles
|
|
|
+from outilsSvg import enregistrer, charger, chargerUnique
|
|
|
+from time import time
|
|
|
+import br
|
|
|
+
|
|
|
+from math import sqrt
|
|
|
+
|
|
|
+m_couleursRapides = [(255,255,255), (200,200,200), (130,130,130), (90,90,90), (15,15,15), \
|
|
|
+ (0,85,0), (170,255,0), (170,255,127), (85,85,0), (85,0,0), (170,85,0), (100,50,0), \
|
|
|
+ (255,255,127), (240,80,0), (85,170,255), (85,85,255), (85,0,255), (0,255,255)]
|
|
|
+
|
|
|
+class Plateau(QGraphicsScene):
|
|
|
+ """plateau de jeu contenant les cases, decors et pions"""
|
|
|
+ def __init__(self, fenetre, parent=None):
|
|
|
+ super(Plateau, self).__init__()
|
|
|
+ #parametres et variables
|
|
|
+
|
|
|
+ self.fenetre = fenetre
|
|
|
+
|
|
|
+ self.id = ""
|
|
|
+ ##partie et infos plateau
|
|
|
+ self.nom = ""
|
|
|
+ self.chapitre = 0
|
|
|
+ self.tour = 1
|
|
|
+
|
|
|
+ self.enCours = False
|
|
|
+ self.public = False
|
|
|
+ self.dateCreation = ""
|
|
|
+ self.dateSvg = ""
|
|
|
+ self.notes = ""
|
|
|
+
|
|
|
+ #carac
|
|
|
+ self.nbCasesX = 0
|
|
|
+ self.nbCasesY = 0
|
|
|
+ self.hCase = 0
|
|
|
+
|
|
|
+ #objets
|
|
|
+ self.pinceau = Pinceau(self)
|
|
|
+ self.cases = {} #dict des cases du plateau (coordonnées: case)
|
|
|
+ self.combattants = {} #liste de combattants positionnes sur le plateau
|
|
|
+ self.decors = {} #liste des decors places sur le plateau
|
|
|
+ self.caches = {}
|
|
|
+ self.listeCasesZonePlacement = []
|
|
|
+ self.polygoneZonePlacement = None
|
|
|
+ self.entreesSorties = []
|
|
|
+
|
|
|
+ #infos combat
|
|
|
+ self.numCombattantEnCours = 0
|
|
|
+ self.ordreJeu = {} #numero du pion: ordre de jeu
|
|
|
+
|
|
|
+ #note: la hauteur Z (qui gere l'empilement des objets graphiques est distribuee de cette maniere:
|
|
|
+ #cases : 0 a 9
|
|
|
+ #pions : 10 et +
|
|
|
+
|
|
|
+ def __getstate__(self):
|
|
|
+ self.dateSvg = time()
|
|
|
+ state = {key:value for key, value in self.__dict__.items() if not key in ["fenetre", "modeActif", \
|
|
|
+ "editionTerrain", "editionCreature", "editionDecor", \
|
|
|
+ "polygoneZonePlacement", "gestionCombat", \
|
|
|
+ "editionAttaques", "pinceau"]}
|
|
|
+ return (state)
|
|
|
+
|
|
|
+ def __setstate__(self, state):
|
|
|
+ self.__dict__ = state
|
|
|
+
|
|
|
+ def vue(self):
|
|
|
+ return self.fenetre.ui.cbt_vue
|
|
|
+
|
|
|
+ def creer(self, idPlateau, nom, chapitre, formeCases, nbCasesX, nbCasesY, couleur = QColor(0, 255, 0, 80)):
|
|
|
+ """cree le plateau"""
|
|
|
+ self.id = idPlateau
|
|
|
+ self.nom = nom
|
|
|
+ self.chapitre = chapitre
|
|
|
+ self.dateCreation = time()
|
|
|
+ self.hCase = 120 #hauteur d'une case
|
|
|
+ self.nbCasesX = nbCasesX #nb cases en x
|
|
|
+ self.nbCasesY = nbCasesY #nb cases en y
|
|
|
+ self.formeCases = formeCases
|
|
|
+ self.modeActif = Modes.ModeBase(self)
|
|
|
+ self.gestionCombat = None
|
|
|
+ self.initialisationGraphique()
|
|
|
+ self.connexions()
|
|
|
+
|
|
|
+ #cree les cases hexagonales
|
|
|
+ for x in range(nbCasesX):
|
|
|
+ for y in range(nbCasesY):
|
|
|
+ c = Case(self)
|
|
|
+ c.creer(x, y, couleur)
|
|
|
+ self.cases[(x,y)] = c
|
|
|
+
|
|
|
+ self.plateauModeCreation()
|
|
|
+
|
|
|
+ def recreer(self, fenetre):
|
|
|
+ self.fenetre = fenetre
|
|
|
+ self.gestionCombat = None
|
|
|
+ super(Plateau, self).__init__()
|
|
|
+ self.modeActif = Modes.ModeBase(self)
|
|
|
+ self.connexions()
|
|
|
+ self.initialisationGraphique()
|
|
|
+
|
|
|
+ #recreation des cases
|
|
|
+ for coord in self.cases:
|
|
|
+ self.cases[coord].recreer(self)
|
|
|
+
|
|
|
+ #recreation des caches
|
|
|
+ self.initListeCaches()
|
|
|
+
|
|
|
+ #recreation des pions
|
|
|
+ for numCombattant in self.combattants:
|
|
|
+ self.combattants[numCombattant].ajouterAuPlateau(self)
|
|
|
+ self.majOrdreJeu()
|
|
|
+
|
|
|
+ #recreation des decors
|
|
|
+ for num in self.decors:
|
|
|
+ self.decors[num].ajouterAuPlateau(self)
|
|
|
+
|
|
|
+ #recreation des marqueurs entree/sortie
|
|
|
+ for entreeSortie in self.entreesSorties:
|
|
|
+ entreeSortie.recreer(self)
|
|
|
+
|
|
|
+ #recreation de la zone de placement:
|
|
|
+ if len(self.listeCasesZonePlacement) > 0:
|
|
|
+ self.polygoneZonePlacement = None
|
|
|
+ self.majZonePlacement(self.listeCasesZonePlacement)
|
|
|
+
|
|
|
+ self.plateauModeCombat()
|
|
|
+
|
|
|
+ def fermer(self):
|
|
|
+ """ferme le plateau 'proprement'"""
|
|
|
+ self.miniature()
|
|
|
+ self.pinceau = None
|
|
|
+ for item in self.items():
|
|
|
+ item.prepareGeometryChange()
|
|
|
+ self.removeItem(item)
|
|
|
+ if self.gestionCombat != None:
|
|
|
+ del self.gestionCombat
|
|
|
+ self.fenetre.reinitialiserPanneauxPlateau()
|
|
|
+
|
|
|
+ def miniature(self):
|
|
|
+ """renvoie une miniature du plateau (QPixMap compresse) qui sera enregistree avec les infos de la sauvegarde"""
|
|
|
+## img = QImage(128, 128, QImage.Format_ARGB32_Premultiplied)
|
|
|
+ img = QPixmap(1024, 768)
|
|
|
+ img.fill(QColor("white"))
|
|
|
+ peintre = QPainter(img)
|
|
|
+ self.render(peintre)
|
|
|
+ peintre.end()
|
|
|
+ img.scaledToHeight(128, Qt.FastTransformation)
|
|
|
+
|
|
|
+ def connexions(self):
|
|
|
+ """connecte le plateau aux differents widgets de la fenetre principale"""
|
|
|
+ #modes d'interaction
|
|
|
+ self.fenetre.connect(self.fenetre.ui.cbt_modeCreation, SIGNAL("clicked()"), self.plateauModeCreation, Qt.UniqueConnection)
|
|
|
+ self.fenetre.connect(self.fenetre.ui.cbt_modeCombat, SIGNAL("clicked()"), self.plateauModeCombat, Qt.UniqueConnection)
|
|
|
+## self.fenetre.connect(self.fenetre.ui.modeAffichagePlateau, SIGNAL("currentIndexChanged(int)"), self.majModeAffichage, Qt.UniqueConnection)
|
|
|
+
|
|
|
+
|
|
|
+ #affichage de fenetres
|
|
|
+ self.fenetre.connect(self.fenetre.ui.cbt_afficherGestion, SIGNAL("clicked()"), self.afficheEcranGestionCombat, Qt.UniqueConnection)
|
|
|
+ self.fenetre.connect(self.fenetre.ui.cbt_ajouterPj, SIGNAL("clicked()"), self.ajouterPj, Qt.UniqueConnection)
|
|
|
+ self.fenetre.connect(self.fenetre.ui.pi_listeAttributs, SIGNAL("cellChanged(int,int)"), self.listeAttributCelluleModifiee, Qt.UniqueConnection)
|
|
|
+
|
|
|
+ self.fenetre.connect(self.fenetre.ui.cp_dialogueCouleurs, SIGNAL("clicked()"), self.modePeintureCase, Qt.UniqueConnection)
|
|
|
+ self.fenetre.connect(self.fenetre.ui.cp_pipetteCouleur, SIGNAL("clicked()"), self.modeCopieTerrain, Qt.UniqueConnection)
|
|
|
+ self.fenetre.connect(self.fenetre.ui.cp_afficherNotes, SIGNAL("clicked()"), self.agrandirNotesMjPlateau, Qt.UniqueConnection)
|
|
|
+
|
|
|
+
|
|
|
+ #listes
|
|
|
+ self.fenetre.connect(self.fenetre.ui.inf_listeOrdreJeu, SIGNAL("cellClicked(int,int)"), self.clicListOrdreJeu, Qt.UniqueConnection)
|
|
|
+
|
|
|
+ self.fenetre.connect(self.fenetre.ui.cp_listeTerrains, SIGNAL("cellClicked(int,int)"), self.modeMajTerrainCase, Qt.UniqueConnection)
|
|
|
+ self.fenetre.connect(self.fenetre.ui.cp_listeCreatures, SIGNAL("cellClicked(int,int)"), self.modeCreationCombattant, Qt.UniqueConnection)
|
|
|
+ self.fenetre.connect(self.fenetre.ui.cp_listeDecors, SIGNAL("cellClicked(int,int)"), self.modeCreationDecor, Qt.UniqueConnection)
|
|
|
+ self.fenetre.connect(self.fenetre.ui.cp_listeCaches, SIGNAL("cellClicked(int,int)"), self.mettreCacheEnEvidence, Qt.UniqueConnection)
|
|
|
+# self.fenetre.connect(self.fenetre.ui.cp_listeCaches, SIGNAL("cellChanged(int,int)"), self.majNomCache, Qt.UniqueConnection)
|
|
|
+
|
|
|
+ self.fenetre.connect(self.fenetre.ui.cp_editerTerrain, SIGNAL("clicked()"), self.terrainEdit, Qt.UniqueConnection)
|
|
|
+ self.fenetre.connect(self.fenetre.ui.cp_nouveauTerrain, SIGNAL("clicked()"), self.terrainNouveau, Qt.UniqueConnection)
|
|
|
+ self.fenetre.connect(self.fenetre.ui.cp_editerCombattant, SIGNAL("clicked()"), self.creatureEdit, Qt.UniqueConnection)
|
|
|
+ self.fenetre.connect(self.fenetre.ui.cp_nouveauCombattant, SIGNAL("clicked()"), self.creatureNouveau, Qt.UniqueConnection)
|
|
|
+ self.fenetre.connect(self.fenetre.ui.cp_gommeCombattant, SIGNAL("clicked()"), self.majModeSupprimerCombattant, Qt.UniqueConnection)
|
|
|
+ self.fenetre.connect(self.fenetre.ui.cp_editerDecor, SIGNAL("clicked()"), self.decorEdit, Qt.UniqueConnection)
|
|
|
+ self.fenetre.connect(self.fenetre.ui.cp_nouveauDecor, SIGNAL("clicked()"), self.decorNouveau, Qt.UniqueConnection)
|
|
|
+ self.fenetre.connect(self.fenetre.ui.cp_gommeDecor, SIGNAL("clicked()"), self.majModeSupprimerDecor, Qt.UniqueConnection)
|
|
|
+ self.fenetre.connect(self.fenetre.ui.cp_editerCache, SIGNAL("clicked()"), self.activerModeEditionCache, Qt.UniqueConnection)
|
|
|
+ self.fenetre.connect(self.fenetre.ui.cp_nouveauCache, SIGNAL("clicked()"), self.activerModeCreationCache, Qt.UniqueConnection)
|
|
|
+ self.fenetre.connect(self.fenetre.ui.cp_supprimerCache, SIGNAL("clicked()"), self.supprimerCache, Qt.UniqueConnection)
|
|
|
+
|
|
|
+ #creation
|
|
|
+ self.fenetre.connect(self.fenetre.ui.cp_epaisseurPinceau, SIGNAL("valueChanged(int)"), self.majEpaisseurPinceau, Qt.UniqueConnection)
|
|
|
+## self.fenetre.connect(self.fenetre.ui.altitudeCase, SIGNAL("valueChanged(double)"), self.modeMajAltitudeCase, Qt.UniqueConnection)
|
|
|
+
|
|
|
+ #autres:
|
|
|
+ #ajouter effet
|
|
|
+ self.fenetre.connect(self.fenetre.ui.cp_placerEntree, SIGNAL("clicked()"), self.majModeDefinirEntree, Qt.UniqueConnection)
|
|
|
+ self.fenetre.connect(self.fenetre.ui.cp_placerSortie, SIGNAL("clicked()"), self.majModeDefinirSortie, Qt.UniqueConnection)
|
|
|
+ self.fenetre.connect(self.fenetre.ui.cp_defPlacement, SIGNAL("clicked()"), self.majModeZonePlacement, Qt.UniqueConnection)
|
|
|
+ self.fenetre.connect(self.fenetre.ui.pi_notes, SIGNAL("textChanged()"), self.majNotesCombattant, Qt.UniqueConnection)
|
|
|
+
|
|
|
+ #formes (dessin)
|
|
|
+ self.fenetre.connect(self.fenetre.ui.cp_formeSimple, SIGNAL("clicked()"), self.majModeForme, Qt.UniqueConnection)
|
|
|
+ self.fenetre.connect(self.fenetre.ui.cp_formeLigne, SIGNAL("clicked()"), self.majModeForme, Qt.UniqueConnection)
|
|
|
+ self.fenetre.connect(self.fenetre.ui.cp_formeLigneOrientee, SIGNAL("clicked()"), self.majModeForme, Qt.UniqueConnection)
|
|
|
+ self.fenetre.connect(self.fenetre.ui.cp_formePot, SIGNAL("clicked()"), self.majModeForme, Qt.UniqueConnection)
|
|
|
+ self.fenetre.connect(self.fenetre.ui.cp_formeRectVide, SIGNAL("clicked()"), self.majModeForme, Qt.UniqueConnection)
|
|
|
+ self.fenetre.connect(self.fenetre.ui.cp_formeRectPlein, SIGNAL("clicked()"), self.majModeForme, Qt.UniqueConnection)
|
|
|
+
|
|
|
+ self.fenetre.connect(self.fenetre.ui.pi_deplacement, SIGNAL("clicked()"), self.majModeCombatDeplacement, Qt.UniqueConnection)
|
|
|
+ self.fenetre.connect(self.fenetre.ui.pi_vol, SIGNAL("clicked()"), self.majModeCombatVol, Qt.UniqueConnection)
|
|
|
+ self.fenetre.connect(self.fenetre.ui.pi_attaqueCac, SIGNAL("clicked()"), self.majModeCombatAttaqueCaC, Qt.UniqueConnection)
|
|
|
+ self.fenetre.connect(self.fenetre.ui.pi_attaqueDist, SIGNAL("clicked()"), self.majModeCombatAttaqueDist, Qt.UniqueConnection)
|
|
|
+ self.fenetre.connect(self.fenetre.ui.pi_attaqueZone, SIGNAL("clicked()"), self.majModeCombatZone, Qt.UniqueConnection)
|
|
|
+ self.fenetre.connect(self.fenetre.ui.pi_formeAttaqueZone, SIGNAL("activated (int)"), self.majModeCombatZone, Qt.UniqueConnection)
|
|
|
+ self.fenetre.connect(self.fenetre.ui.pi_rayonAttaqueZone, SIGNAL("valueChanged(int)"), self.majRayonZone, Qt.UniqueConnection)
|
|
|
+
|
|
|
+
|
|
|
+ self.fenetre.connect(self.fenetre.ui.pi_finTour, SIGNAL("clicked()"), self.pionSuivant, Qt.UniqueConnection)
|
|
|
+
|
|
|
+ def initialisationGraphique(self):
|
|
|
+ """cree la scene graphique et les parametres necessaires a son fonctionnement, et met a jour l'interface"""
|
|
|
+ #on cree la scene graphique
|
|
|
+ kx = 1
|
|
|
+ if self.formeCases == "H":
|
|
|
+ kx = 0.866
|
|
|
+ marge = 240
|
|
|
+ self.setSceneRect(0 - marge, 0 - marge, (kx*self.hCase*(self.nbCasesX+2)) + marge, (self.hCase*(self.nbCasesY+2)) + marge)
|
|
|
+ self.vue().setScene(self)
|
|
|
+ self.vue().scale(0.25, 0.25)
|
|
|
+ self.vue().centerOn(QPointF(0,0))
|
|
|
+ self.vue().setDragMode(1)
|
|
|
+ self.setItemIndexMethod(QGraphicsScene.BspTreeIndex)
|
|
|
+
|
|
|
+ self.polygoneZonePlacement = None
|
|
|
+
|
|
|
+ #gestion du mode d'interaction avec le plateau
|
|
|
+
|
|
|
+ self.pinceau = Pinceau(self)
|
|
|
+ self.proj = ProjectionDep(self)
|
|
|
+
|
|
|
+ #mise a jour de l'interface de creation
|
|
|
+ self.fenetre.afficherPanneauxPlateau(True)
|
|
|
+ self.fenetre.ui.cbt_nom.majTexte(self.nom)
|
|
|
+ self.majBoutonsCouleursPerso()
|
|
|
+ self.fenetre.ui.cp_listeTerrains.defFichier("lib\\biblio\\terrain")
|
|
|
+ self.fenetre.ui.cp_listeTerrains.initAffichage()
|
|
|
+ self.fenetre.ui.cp_listeCreatures.defFichier("lib\\biblio\\combattant")
|
|
|
+ self.fenetre.ui.cp_listeCreatures.initAffichage()
|
|
|
+ self.fenetre.ui.cp_listeDecors.defFichier("lib\\biblio\\decor")
|
|
|
+ self.fenetre.ui.cp_listeDecors.initAffichage()
|
|
|
+ self.majListeTerrains()
|
|
|
+ self.majListeCreatures()
|
|
|
+ self.majListeDecors()
|
|
|
+ self.initListeCaches()
|
|
|
+
|
|
|
+ self.initListeOrdreJeu()
|
|
|
+ self.initListeAttaques()
|
|
|
+
|
|
|
+ self.fenetre.ui.pi_deplacement.setCheckable(True)
|
|
|
+ self.fenetre.ui.pi_attaqueCac.setCheckable(True)
|
|
|
+ self.fenetre.ui.pi_attaqueDist.setCheckable(True)
|
|
|
+ self.fenetre.ui.pi_attaqueZone.setCheckable(True)
|
|
|
+
|
|
|
+ #mise a jour de l'interface d'informations
|
|
|
+ self.majInfosCombattant(None)
|
|
|
+ self.majInfosDecor(None)
|
|
|
+
|
|
|
+ def estCree(self):
|
|
|
+ """renvoie vrai si des cases ont ete creees"""
|
|
|
+ return (len(self.cases) > 0)
|
|
|
+
|
|
|
+ def majBoutonsCouleursPerso(self):
|
|
|
+ """met a jour l'affichage des couleurs customisees dans la boite de dialogue de selection de couleur"""
|
|
|
+ for i in range(0,18):
|
|
|
+ couleur = QColor()
|
|
|
+ r, g, b = m_couleursRapides[i]
|
|
|
+ couleur.setRgb(r, g, b)
|
|
|
+ bouton = self.fenetre.ui.cp_boiteCouleurs.findChild(QToolButton, "cp_couleur{}".format(i+1))
|
|
|
+ if couleur.isValid():
|
|
|
+ bouton.setStyleSheet("QToolButton {backGround:%s}"%(couleur.name()))
|
|
|
+ self.fenetre.connect(bouton, SIGNAL("clicked()"), self.modePeintureCase_perso)
|
|
|
+
|
|
|
+ def chercherCouleur(self):
|
|
|
+ """ouvre la boite de dialogue de selection de couleur"""
|
|
|
+ couleur = QColorDialog(self.vue()).getColor(QColor("white"), self.vue())
|
|
|
+ return couleur
|
|
|
+
|
|
|
+ def majListesPions(self, numCombattant = None):
|
|
|
+ """met a jour les listes contenant des donnees liees aux pions"""
|
|
|
+## self.majListeOrdreJeu()
|
|
|
+##
|
|
|
+## if numCombattant == None or numCombattant == self.pionSelectionne().numero:
|
|
|
+## self.majListeAttributs()
|
|
|
+## QApplication.processEvents()
|
|
|
+ pass
|
|
|
+
|
|
|
+ def ajouterPj(self):
|
|
|
+ """affiche la fenetre de selection des pj, et recupere l'eventuel pj selectionne"""
|
|
|
+ self.ecranSelPj = EcranSelectionPj(self.fenetre)
|
|
|
+ self.ecranSelPj.setAttribute(Qt.WA_DeleteOnClose)
|
|
|
+ listePj = chargerUnique("parties\\{}\\groupe".format(self.fenetre.partie))
|
|
|
+ self.ecranSelPj.charger(listePj)
|
|
|
+ r = self.ecranSelPj.exec_()
|
|
|
+ if r == 1:
|
|
|
+ idPj = int(self.ecranSelPj.selection())
|
|
|
+ if idPj != None:
|
|
|
+ pj = listePj[idPj]
|
|
|
+ self.activerMode(Modes.CreationPion, pj)
|
|
|
+ self.ecranSelPj = None
|
|
|
+
|
|
|
+ def agrandirNotesMjPlateau(self):
|
|
|
+ """affiche les notes du plateau dans une QDialog, puis recupere les donnees qui y sont saisies"""
|
|
|
+ affichageTexte = EcranAffichageTexte(self.notes)
|
|
|
+ affichageTexte.setAttribute(Qt.WA_DeleteOnClose)
|
|
|
+ affichageTexte.exec_()
|
|
|
+ self.notes = affichageTexte.recupererTexte()
|
|
|
+
|
|
|
+ ##### affichage de la liste des terrains enregistres, et fonctions d'acces aux donnees""""
|
|
|
+ def afficheEcranEditionTerrains(self, terrain = None):
|
|
|
+ """affiche l'ecran d'edition/creation de terrains"""
|
|
|
+ self.editionTerrain = EcranEditionTerrain(terrain)
|
|
|
+ self.editionTerrain.setAttribute(Qt.WA_DeleteOnClose)
|
|
|
+ r = self.editionTerrain.exec_()
|
|
|
+ if r == 1:
|
|
|
+ self.majListeTerrains()
|
|
|
+ self.activerMode(Modes.StandardCp)
|
|
|
+
|
|
|
+ def majListeTerrains(self):
|
|
|
+ """mise a jour de la liste des terrains depuis la sauvegarde"""
|
|
|
+ self.fenetre.ui.cp_listeTerrains.maj()
|
|
|
+
|
|
|
+ def terrainEdit(self):
|
|
|
+ """ouvre la fenetre 'terrains' en mode edition"""
|
|
|
+ index = self.fenetre.ui.cp_listeTerrains.item(self.fenetre.ui.cp_listeTerrains.currentRow(), 0)
|
|
|
+ if index > 0:
|
|
|
+ terrain = charger("lib\\biblio\\terrain", str(index.text().toUtf8()))
|
|
|
+ self.afficheEcranEditionTerrains(terrain)
|
|
|
+ self.activerMode(Modes.StandardCp)
|
|
|
+
|
|
|
+ def terrainNouveau(self):
|
|
|
+ """ouvre la fenetre 'terrains' en mode edition"""
|
|
|
+ self.afficheEcranEditionTerrains()
|
|
|
+ self.activerMode(Modes.StandardCp)
|
|
|
+ ###############
|
|
|
+
|
|
|
+ ##### affichage de la liste des creatures enregistrees, et fonctions d'acces aux donnees""""
|
|
|
+ def afficheEcranEditionCombattants(self, creature = None):
|
|
|
+ """affiche l'ecran d'edition/creation de creatures"""
|
|
|
+ self.editionCreature = EcranEditionCombattant(creature, 0, self.formeCases)
|
|
|
+ self.editionCreature.setAttribute(Qt.WA_DeleteOnClose)
|
|
|
+ r = self.editionCreature.exec_()
|
|
|
+ if r == 1:
|
|
|
+ combattant = self.editionCreature.combattant
|
|
|
+ enregistrer(combattant.id, combattant, "lib\\biblio\\combattant")
|
|
|
+ self.majListeCreatures()
|
|
|
+ self.activerMode(Modes.StandardCp)
|
|
|
+ self.editionCreature = None
|
|
|
+
|
|
|
+ def majListeCreatures(self):
|
|
|
+ """mise a jour de la liste des creatures depuis la sauvegarde"""
|
|
|
+ self.fenetre.ui.cp_listeCreatures.maj()
|
|
|
+
|
|
|
+ def creatureEdit(self):
|
|
|
+ """ouvre la fenetre 'creatures' en mode edition"""
|
|
|
+ index = self.fenetre.ui.cp_listeCreatures.item(self.fenetre.ui.cp_listeCreatures.currentRow(), 0)
|
|
|
+ if index > 0:
|
|
|
+ creature = charger("lib\\biblio\\combattant", str(index.text().toUtf8()))
|
|
|
+ self.afficheEcranEditionCombattants(creature)
|
|
|
+ self.activerMode(Modes.StandardCp)
|
|
|
+
|
|
|
+ def creatureNouveau(self):
|
|
|
+ """ouvre la fenetre 'creatures' en mode edition"""
|
|
|
+ self.afficheEcranEditionCombattants()
|
|
|
+ self.activerMode(Modes.StandardCp)
|
|
|
+
|
|
|
+ ###############
|
|
|
+
|
|
|
+ ##### affichage de la liste des decors enregistrees, et fonctions d'acces aux donnees""""
|
|
|
+ def afficheEcranEditionDecors(self, decor = None):
|
|
|
+ """affiche l'ecran d'edition/creation de decors"""
|
|
|
+ self.editionDecor = EcranEditionDecor(decor, 0, self.formeCases)
|
|
|
+ self.editionDecor.setAttribute(Qt.WA_DeleteOnClose)
|
|
|
+ r = self.editionDecor.exec_()
|
|
|
+ if r == 1:
|
|
|
+ decor = self.editionDecor.decor
|
|
|
+ enregistrer(decor.id, decor, "lib\\biblio\\decor")
|
|
|
+ self.majListeDecors()
|
|
|
+ self.activerMode(Modes.StandardCp)
|
|
|
+
|
|
|
+ def majListeDecors(self):
|
|
|
+ """mise a jour de la liste des decors depuis la sauvegarde"""
|
|
|
+ self.fenetre.ui.cp_listeDecors.maj()
|
|
|
+
|
|
|
+ def decorEdit(self):
|
|
|
+ """ouvre la fenetre 'decors' en mode edition"""
|
|
|
+ self.afficheEcranEditionDecors(self.fenetre.ui.cp_listeDecors.actuel())
|
|
|
+ self.activerMode(Modes.StandardCp)
|
|
|
+
|
|
|
+ def decorNouveau(self):
|
|
|
+ """ouvre la fenetre 'decors' en mode edition"""
|
|
|
+ self.afficheEcranEditionDecors()
|
|
|
+ self.activerMode(Modes.StandardCp)
|
|
|
+
|
|
|
+ ###############
|
|
|
+
|
|
|
+ ############### maj des infos du panneau Pi a la selection/deselection d'un pion
|
|
|
+ #voir a balancer tout ca dans une classe a part
|
|
|
+
|
|
|
+ def majPanneauPi(self):
|
|
|
+
|
|
|
+ if self.pionSelectionne():
|
|
|
+ estCombattant = (self.pionSelectionne().numero < 10000)
|
|
|
+ #affichage
|
|
|
+ self.fenetre.ui.pi_actions.setEnabled(estCombattant)
|
|
|
+ self.fenetre.ui.pi_finTour.setEnabled(estCombattant)
|
|
|
+ self.fenetre.ui.pi_ongletsListes.setTabEnabled(0, estCombattant)
|
|
|
+ self.fenetre.ui.pi_ongletsListes.setTabEnabled(1, estCombattant)
|
|
|
+
|
|
|
+ ### maj la selection dans la liste d'ordre de jeu
|
|
|
+ if estCombattant:
|
|
|
+ for i in range(0, self.fenetre.ui.inf_listeOrdreJeu.rowCount()):
|
|
|
+ if str(self.fenetre.ui.inf_listeOrdreJeu.item(i, 0).text().toUtf8()) == str(self.pionSelectionne().numero):
|
|
|
+ self.fenetre.ui.inf_listeOrdreJeu.setCurrentCell(i,0)
|
|
|
+
|
|
|
+ ### maj des infos dans le panneau pi
|
|
|
+ self.fenetre.ui.pi_nom.majTexte(self.pionSelectionne().txtId())
|
|
|
+ self.fenetre.ui.pi_img.chargerImage(self.pionSelectionne().img.rimage)
|
|
|
+
|
|
|
+ ### maj de la liste des attributs
|
|
|
+ if estCombattant:
|
|
|
+ self.fenetre.ui.pi_listeAttributs.setColumnWidth(0, 50)
|
|
|
+ self.disconnect(self.fenetre.ui.pi_listeAttributs, SIGNAL("cellChanged(int,int)"), self.listeAttributCelluleModifiee)
|
|
|
+
|
|
|
+ #on vide la liste
|
|
|
+ while self.fenetre.ui.pi_listeAttributs.rowCount() > 0:
|
|
|
+ self.fenetre.ui.pi_listeAttributs.removeRow(0)
|
|
|
+
|
|
|
+ #creation des lignes de base
|
|
|
+ lignesBase = ["Nom","Etat","Alt."] #attention: modifier aussi dans listeAttributCelluleModifiee
|
|
|
+ for i in range(0, 10): #10 premieres colonnes reservees pour les infos de base
|
|
|
+ self.fenetre.ui.pi_listeAttributs.insertRow(i)
|
|
|
+ item = QTableWidgetItem()
|
|
|
+ if i < len(lignesBase):
|
|
|
+ item.setText(QString.fromUtf8(lignesBase[i]))
|
|
|
+ item.setFlags(Qt.NoItemFlags)
|
|
|
+ self.fenetre.ui.pi_listeAttributs.setItem(i, 0, item)
|
|
|
+ self.fenetre.ui.pi_listeAttributs.setRowHidden(i, (i >= len(lignesBase)))
|
|
|
+
|
|
|
+ #maj des donnees de base
|
|
|
+ self.fenetre.ui.pi_listeAttributs.setItem(lignesBase.index("Nom"), 1, QTableWidgetItem(QString.fromUtf8(str(self.pionSelectionne().nom))))
|
|
|
+ self.fenetre.ui.pi_listeAttributs.setItem(lignesBase.index("Etat"), 1, QTableWidgetItem(QString.fromUtf8(str(self.pionSelectionne().etat))))
|
|
|
+ self.fenetre.ui.pi_listeAttributs.setItem(lignesBase.index("Alt."), 1, QTableWidgetItem(QString.fromUtf8(str(self.pionSelectionne().z))))
|
|
|
+
|
|
|
+ #attributs issus des regles utilisees
|
|
|
+ ordre = regles.ordreAttributs()
|
|
|
+ for elt in ordre:
|
|
|
+ ligne = 10 + ordre.index(elt)
|
|
|
+ self.fenetre.ui.pi_listeAttributs.insertRow(ligne)
|
|
|
+ item = QTableWidgetItem(QString.fromUtf8(elt))
|
|
|
+ item.setFlags(Qt.NoItemFlags)
|
|
|
+ self.fenetre.ui.pi_listeAttributs.setItem(ligne, 0, item)
|
|
|
+ self.fenetre.ui.pi_listeAttributs.setItem(ligne, 1, QTableWidgetItem(QString.fromUtf8(str(self.pionSelectionne().listeAttributs[elt]))))
|
|
|
+
|
|
|
+ self.connect(self.fenetre.ui.pi_listeAttributs, SIGNAL("cellChanged(int,int)"), self.listeAttributCelluleModifiee)
|
|
|
+
|
|
|
+ ###affiche les notes du combattant
|
|
|
+ self.fenetre.ui.pi_notes.majTexte(self.pionSelectionne().notes)
|
|
|
+
|
|
|
+ ###maj la liste des attaques du pion
|
|
|
+ if estCombattant:
|
|
|
+ #on vide la liste
|
|
|
+ while self.fenetre.ui.pi_listeAttaques.rowCount() > 0:
|
|
|
+ self.fenetre.ui.pi_listeAttaques.removeRow(0)
|
|
|
+
|
|
|
+ i = 0
|
|
|
+ for attaque in self.pionSelectionne().attaques:
|
|
|
+ self.fenetre.ui.pi_listeAttaques.insertRow(i)
|
|
|
+ self.fenetre.ui.pi_listeAttaques.setItem(i, 0, QTableWidgetItem(QString.fromUtf8(str(self.pionSelectionne().attaques.index(attaque)))))
|
|
|
+ icone = None
|
|
|
+ if attaque.typ == "cac":
|
|
|
+ icone = QIcon(":/interface/16/ressource/epee_16.png")
|
|
|
+ if attaque.typ == "dist":
|
|
|
+ icone = QIcon(":/interface/16/ressource/arc_16.png")
|
|
|
+ if attaque.typ == "zone":
|
|
|
+ icone = QIcon(":/interface/16/ressource/baguette_16.png")
|
|
|
+ if icone != None:
|
|
|
+ self.fenetre.ui.pi_listeAttaques.setItem(i, 1, QTableWidgetItem(icone, QString.fromUtf8("")))
|
|
|
+ self.fenetre.ui.pi_listeAttaques.setItem(i, 2, QTableWidgetItem(QString.fromUtf8(attaque.nom)))
|
|
|
+
|
|
|
+ else:
|
|
|
+ #maj des infos dans le panneau pi
|
|
|
+ self.fenetre.ui.pi_img.clear()
|
|
|
+ self.fenetre.ui.pi_nom.majTexte("Pas de pion\nselectionné")
|
|
|
+
|
|
|
+ #vide la liste des attributs
|
|
|
+ self.disconnect(self.fenetre.ui.pi_listeAttributs, SIGNAL("cellChanged(int,int)"), self.listeAttributCelluleModifiee)
|
|
|
+ while self.fenetre.ui.pi_listeAttributs.rowCount() > 0:
|
|
|
+ self.fenetre.ui.pi_listeAttributs.removeRow(0)
|
|
|
+
|
|
|
+ #vide la liste des attaques du pion
|
|
|
+ while self.fenetre.ui.pi_listeAttaques.rowCount() > 0:
|
|
|
+ self.fenetre.ui.pi_listeAttaques.removeRow(0)
|
|
|
+
|
|
|
+ self.majInfosAttaqueEC()
|
|
|
+
|
|
|
+ ##### activation des differents modes d'interaction avec le plateau et mises a jour des principaux parametres #######
|
|
|
+ def plateauModeCreation(self):
|
|
|
+ self.activerMode(Modes.StandardCp)
|
|
|
+
|
|
|
+ def plateauModeCombat(self):
|
|
|
+ self.activerMode(Modes.StandardPi)
|
|
|
+
|
|
|
+ def activerMode(self, mode, param = None):
|
|
|
+ """desactive le mode actif et active le nouveau a la place"""
|
|
|
+ self.modeActif.desactiver()
|
|
|
+ self.modeActif = mode(self)
|
|
|
+ self.modeActif.activer(param)
|
|
|
+
|
|
|
+## def majModeAffichage(self, index):
|
|
|
+## """met a jour le mode d'affichage"""
|
|
|
+## nouveauMode = ""
|
|
|
+## if index == 0:
|
|
|
+## #passe a l'affichage standard
|
|
|
+## pass
|
|
|
+## elif index == 1:
|
|
|
+## #passe en mode affichage de l'altitude
|
|
|
+## nouveauMode = "altitude"
|
|
|
+## elif index == 2:
|
|
|
+## #affichage des terrains slt
|
|
|
+## nouveauMode = "terrain"
|
|
|
+## elif index == 3:
|
|
|
+## #affichage tactique
|
|
|
+## nouveauMode = "tactique"
|
|
|
+##
|
|
|
+## for coord in self.cases:
|
|
|
+## self.cases[coord].majAffichageSpecial(nouveauMode)
|
|
|
+
|
|
|
+ def modePeintureCase(self):
|
|
|
+ """enclenche le mode peinture de case a partir de la couleur selectionnee"""
|
|
|
+ couleur = self.chercherCouleur()
|
|
|
+ if couleur.isValid():
|
|
|
+ terrain = Terrain()
|
|
|
+ terrain.couleur = couleur
|
|
|
+ self.activerMode(Modes.MajCases, terrain)
|
|
|
+ else:
|
|
|
+ self.activerMode(Modes.StandardCp)
|
|
|
+
|
|
|
+ def modePeintureCase_perso(self):
|
|
|
+ origine = self.sender().objectName()
|
|
|
+ index = int(origine.replace("cp_couleur",""))-1
|
|
|
+ couleur = QColor()
|
|
|
+ r, g, b = m_couleursRapides[index]
|
|
|
+ couleur.setRgb(r, g, b)
|
|
|
+ if couleur.isValid():
|
|
|
+ terrain = Terrain()
|
|
|
+ terrain.couleur = couleur
|
|
|
+ self.activerMode(Modes.MajCases, terrain)
|
|
|
+ else:
|
|
|
+ self.activerMode(Modes.StandardCp)
|
|
|
+
|
|
|
+ def modeCopieTerrain(self):
|
|
|
+ """enclenche le mode copie de case"""
|
|
|
+ self.activerMode(Modes.Pipette)
|
|
|
+
|
|
|
+ def modeCaseEffet(self, index):
|
|
|
+ """enclenche le mode de mise a jour de l'effet actif des cases"""
|
|
|
+ effets = ["brule", "eau", "glace", "poison", "aucun"]
|
|
|
+ self.activerMode(Modes.MajCasesEffet, effets[index])
|
|
|
+
|
|
|
+ def modeCreationPion(self):
|
|
|
+ """enclenche le mode de creation de pions simples"""
|
|
|
+ self.majMode("pionCreation")
|
|
|
+
|
|
|
+ def majModeSupprimerDecor(self):
|
|
|
+ """enclenche le mode suppression de pions sur clic gauche (creatures ou decors)"""
|
|
|
+ self.activerMode(Modes.SuppressionPion, Decor)
|
|
|
+
|
|
|
+ def majModeSupprimerCombattant(self):
|
|
|
+ """enclenche le mode suppression de pions sur clic gauche (creatures ou decors)"""
|
|
|
+ self.activerMode(Modes.SuppressionPion, Combattant)
|
|
|
+
|
|
|
+ def modeCreationDecor(self, ligne, col):
|
|
|
+ """enclenche le mode de creation de decors depuis la liste des decors"""
|
|
|
+ index = self.fenetre.ui.cp_listeDecors.item(ligne, 0)
|
|
|
+ decor = charger("lib\\biblio\\decor", str(index.text().toUtf8()))
|
|
|
+ self.activerMode(Modes.CreationPion, decor)
|
|
|
+
|
|
|
+ def modeCreationCombattant(self, ligne, col):
|
|
|
+ """enclenche le mode de creation de pions depuis la liste des creatures"""
|
|
|
+ index = self.fenetre.ui.cp_listeCreatures.item(ligne, 0)
|
|
|
+ creature = charger("lib\\biblio\\combattant", str(index.text().toUtf8()))
|
|
|
+ self.activerMode(Modes.CreationPion, creature)
|
|
|
+
|
|
|
+ def modeMajTerrainCase(self, ligne, col):
|
|
|
+ """enclenche le mode permettant la mise a jour du terrain des cases"""
|
|
|
+ index = self.fenetre.ui.cp_listeTerrains.item(ligne, 0)
|
|
|
+ terrain = charger("lib\\biblio\\terrain", str(index.text().toUtf8()))
|
|
|
+ if terrain:
|
|
|
+ self.activerMode(Modes.MajCases, terrain)
|
|
|
+ else:
|
|
|
+ print "terrain invalide"
|
|
|
+
|
|
|
+ def majEpaisseurPinceau(self, epaisseur):
|
|
|
+ """met a jour l'epaisseur du pinceau (en cases)"""
|
|
|
+ self.fenetre.ui.cp_valeurEpaisseurPinceau.majTexte(str(epaisseur))
|
|
|
+ self.pinceau.majEpaisseur(int(epaisseur))
|
|
|
+
|
|
|
+ def modeMajAltitudeCase(self):
|
|
|
+ self.majMode("caseMajAltitude")
|
|
|
+
|
|
|
+ def majModeForme(self):
|
|
|
+ """met a jour la forme utilisee pour la peinture"""
|
|
|
+ formes = {"cp_formeSimple": "simple", \
|
|
|
+ "cp_formeLigne": "ligne", \
|
|
|
+ "cp_formeLigneOrientee": "frontiere", \
|
|
|
+ "cp_formePot": "pot", \
|
|
|
+ "cp_formeEllipseVide": "ellipseV", \
|
|
|
+ "cp_formeEllipsePlein": "ellipseP", \
|
|
|
+ "cp_formeRectVide": "rectV", \
|
|
|
+ "cp_formeRectPlein": "rectP"}
|
|
|
+ self.pinceau.majForme(formes[str(self.sender().objectName())])
|
|
|
+
|
|
|
+ def majModeCombatDeplacement(self):
|
|
|
+ """active le mode de combat 'deplacement' (mode standard)"""
|
|
|
+ self.modeActif.nouvelleAction(Actions.Deplacement)
|
|
|
+
|
|
|
+ def majModeCombatVol(self):
|
|
|
+ """active le mode de combat 'vol'"""
|
|
|
+ self.modeActif.nouvelleAction(Actions.Vol)
|
|
|
+
|
|
|
+ def majModeCombatAttaqueCaC(self):
|
|
|
+ """active le mode de combat 'corps-a-corps'"""
|
|
|
+ self.modeActif.nouvelleAction(Actions.Cac)
|
|
|
+
|
|
|
+ def majModeCombatAttaqueDist(self):
|
|
|
+ """active le mode de combat 'attaque a distance'"""
|
|
|
+ self.modeActif.nouvelleAction(Actions.Distance)
|
|
|
+
|
|
|
+ def majModeCombatZone(self):
|
|
|
+ if self.fenetre.ui.pi_formeAttaqueZone.currentIndex() == 0:
|
|
|
+ action = Actions.Ligne
|
|
|
+ elif self.fenetre.ui.pi_formeAttaqueZone.currentIndex() == 1:
|
|
|
+ action = Actions.Disque
|
|
|
+ elif self.fenetre.ui.pi_formeAttaqueZone.currentIndex() == 2:
|
|
|
+ action = Actions.Cone
|
|
|
+ if action:
|
|
|
+ self.modeActif.nouvelleAction(action)
|
|
|
+
|
|
|
+ def majRayonZone(self, val):
|
|
|
+ action = self.modeActif.action()
|
|
|
+ if action:
|
|
|
+ action.majRayon(val)
|
|
|
+
|
|
|
+ def majModeDefinirEntree(self):
|
|
|
+ self.activerMode(Modes.CreationEntreeSortie, "E")
|
|
|
+
|
|
|
+ def majModeDefinirSortie(self):
|
|
|
+ self.activerMode(Modes.CreationEntreeSortie, "S")
|
|
|
+
|
|
|
+ def majModeZonePlacement(self):
|
|
|
+ self.activerMode(Modes.ZonePlacement)
|
|
|
+
|
|
|
+ ###############
|
|
|
+
|
|
|
+ ########## Gestion du combat ##############
|
|
|
+ def majAffichageTour(self):
|
|
|
+ """met a jour l'affichage du tour en cours"""
|
|
|
+ self.fenetre.ui.cbt_tour.majTexte("Tour: {}".format(self.tour))
|
|
|
+
|
|
|
+ def initListeOrdreJeu(self):
|
|
|
+ """cree les colonnes et met en forme la table ordre jeu"""
|
|
|
+ self.fenetre.ui.inf_listeOrdreJeu.setColumnWidth(2, 30)
|
|
|
+ self.fenetre.ui.inf_listeOrdreJeu.hideColumn(0)
|
|
|
+ self.fenetre.ui.inf_listeOrdreJeu.hideColumn(2)
|
|
|
+ self.fenetre.ui.inf_listeOrdreJeu.setIconSize(QSize(30,20))
|
|
|
+
|
|
|
+ def majListeOrdreJeu(self):
|
|
|
+ """met a jour la liste des pions infoOrdreJeu"""
|
|
|
+ while self.fenetre.ui.inf_listeOrdreJeu.rowCount() > 0:
|
|
|
+ self.fenetre.ui.inf_listeOrdreJeu.removeRow(0)
|
|
|
+ index = 0
|
|
|
+ for num in self.ordreJeu:
|
|
|
+ self.fenetre.ui.inf_listeOrdreJeu.insertRow(int(index))
|
|
|
+ self.fenetre.ui.inf_listeOrdreJeu.setItem(int(index), 0, QTableWidgetItem(QString.fromUtf8(str(num))))
|
|
|
+ icon = QIcon(self.combattants[num].logo.chemin())
|
|
|
+ item = QTableWidgetItem(icon, QString.fromUtf8(self.combattants[num].txtId()))
|
|
|
+ self.fenetre.ui.inf_listeOrdreJeu.setItem(int(index), 1, item)
|
|
|
+ self.fenetre.ui.inf_listeOrdreJeu.setItem(int(index), 2, QTableWidgetItem(QString.fromUtf8(str(self.ordreJeu[num]))))
|
|
|
+ index += 1
|
|
|
+
|
|
|
+ self.fenetre.ui.inf_listeOrdreJeu.sizeHintForColumn(1)
|
|
|
+## trierTable(self.fenetre.ui.infoOrdreJeu, 2, 0)
|
|
|
+
|
|
|
+ def clicListOrdreJeu(self, ligne, col):
|
|
|
+ """on a clique dans la liste d'ordre de jeu, le pion correspondant est selectionne et centre sur la carte"""
|
|
|
+ numCombattant = int(self.fenetre.ui.inf_listeOrdreJeu.item(ligne, 0).text().toUtf8())
|
|
|
+ self.vue().centerOn(self.cases[self.combattants[numCombattant].position].centreGraphique)
|
|
|
+ self.modeActif.clic_combattant(numCombattant)
|
|
|
+
|
|
|
+ def pionSuivant(self):
|
|
|
+ """selection du pion suivant dans la liste d'ordre de jeu"""
|
|
|
+ if self.numPionEnCours in self.combattants:
|
|
|
+ suivant = self.ordreJeu[self.numPionEnCours] + 1
|
|
|
+ else:
|
|
|
+ suivant = 1
|
|
|
+ if suivant > len(self.ordreJeu):
|
|
|
+ self.tour += 1
|
|
|
+ self.majAffichageTour()
|
|
|
+ suivant = 1
|
|
|
+ for num in self.ordreJeu:
|
|
|
+ if self.ordreJeu[num] == suivant:
|
|
|
+ numCombattant = num
|
|
|
+ break
|
|
|
+
|
|
|
+ for ligne in range(0, self.fenetre.ui.inf_listeOrdreJeu.rowCount()):
|
|
|
+ item = self.fenetre.ui.inf_listeOrdreJeu.item(ligne, 0)
|
|
|
+ item.setSelected(int(self.fenetre.ui.inf_listeOrdreJeu.item(ligne, 0).text().toUtf8()) == numCombattant)
|
|
|
+ if int(item.text().toUtf8()) == numCombattant:
|
|
|
+ self.fenetre.ui.inf_listeOrdreJeu.scrollToItem(item)
|
|
|
+
|
|
|
+ self.vue().centerOn(self.cases[self.combattants[numCombattant].position].centreGraphique)
|
|
|
+ self.pionSaisir(numCombattant)
|
|
|
+
|
|
|
+ def afficheEcranGestionCombat(self):
|
|
|
+ """affiche l'ecran de gestion du combat"""
|
|
|
+ self.gestionCombat = EcranGestionCombat(self)
|
|
|
+ self.gestionCombat.show()
|
|
|
+ self.connect(self.fenetre, SIGNAL("majListesPions"), self.majListesPions)
|
|
|
+ self.connect(self.gestionCombat, SIGNAL("majListesPions"), self.majListesPions)
|
|
|
+ QApplication.processEvents()
|
|
|
+## r = self.gestionCombat.exec_()
|
|
|
+
|
|
|
+ def majOrdreJeu(self):
|
|
|
+ """met a jour l'ordre de jeu des pions en fonction de l'attribut prevu par les regles s'il existe,
|
|
|
+ ou en fonction de l'ordre de jeu parametre sinon"""
|
|
|
+ if len(self.ordreJeu) > 0:
|
|
|
+ attribut = regles.attributOrdreJeu()
|
|
|
+ if attribut != None:
|
|
|
+ dico = {}
|
|
|
+ for numCombattant in self.combattants:
|
|
|
+ dico[numCombattant] = int(self.combattants[numCombattant].listeAttributs[attribut])
|
|
|
+ ordre = sorted(dico, key = dico.get, reverse=(regles.sensTriOrdreJeu() == 1))
|
|
|
+ self.ordreJeu = {}
|
|
|
+ for numCombattant in self.combattants:
|
|
|
+ self.ordreJeu[numCombattant] = ordre.index(numCombattant) + 1
|
|
|
+ self.majListeOrdreJeu()
|
|
|
+
|
|
|
+ def pionDeplacerDansOrdreJeu(self, numCombattant, nouvellePosition):
|
|
|
+ """deplace un pion dans le dictionnaire gerant l'ordre de jeu de maniere a assurer sa coherence
|
|
|
+ nouvellePosition = 0 supprime le pion de la liste"""
|
|
|
+ if numCombattant in self.ordreJeu:
|
|
|
+ if nouvellePosition == 0:
|
|
|
+ del self.ordreJeu[numCombattant]
|
|
|
+ if len(self.ordreJeu) > 0:
|
|
|
+ i = 0
|
|
|
+ tmp = sorted(self.ordreJeu, key=self.ordreJeu.get)
|
|
|
+ if numCombattant in tmp:
|
|
|
+ tmp.remove(numCombattant)
|
|
|
+ for num in tmp:
|
|
|
+ i += 1
|
|
|
+ if i == nouvellePosition:
|
|
|
+ self.ordreJeu[numCombattant] = i
|
|
|
+ i += 1
|
|
|
+ self.ordreJeu[num] = i
|
|
|
+ if i < nouvellePosition:
|
|
|
+ self.ordreJeu[numCombattant] = i + 1
|
|
|
+ elif nouvellePosition > 0:
|
|
|
+ self.ordreJeu[numCombattant] = 1
|
|
|
+ self.majOrdreJeu()
|
|
|
+
|
|
|
+ def listeAttributCelluleModifiee(self, ligne, colonne):
|
|
|
+ """une cellule de la liste des attributs a ete modifiee"""
|
|
|
+ if colonne != 1:
|
|
|
+ print("valeur non modifiable")
|
|
|
+ else:
|
|
|
+ #on verifie la validite de la donnee entree
|
|
|
+ lignesBase = ["Nom","Etat","Alt."] #attention: modifier aussi dans majListeAttribut
|
|
|
+ if ligne < len(lignesBase):
|
|
|
+ pass
|
|
|
+ elif ligne >= 10:
|
|
|
+ attribut = regles.ordreAttributs()[(ligne - 10)]
|
|
|
+ nouvelleVal = str(self.fenetre.ui.pi_listeAttributs.item(ligne, 1).text().toUtf8())
|
|
|
+ valVerifiee = regles.listeControle()[attribut].controler(nouvelleVal)
|
|
|
+ if valVerifiee != None:
|
|
|
+ self.pionSelectionne().listeAttributs[attribut] = valVerifiee
|
|
|
+ if attribut == regles.attributOrdreJeu():
|
|
|
+ print("maj ordre (a implementer)")
|
|
|
+ else:
|
|
|
+ self.fenetre.ui.pi_listeAttributs.setItem(ligne, 1, QTableWidgetItem(QString.fromUtf8(str(self.pionSelectionne().listeAttributs[attribut]))))
|
|
|
+
|
|
|
+ def initListeAttaques(self):
|
|
|
+ """met en forme et connecte la liste des attaques du pion"""
|
|
|
+ self.fenetre.ui.pi_listeAttaques.setColumnWidth(0, 0)
|
|
|
+ self.fenetre.ui.pi_listeAttaques.setColumnWidth(1, (0.3*self.fenetre.ui.pi_listeAttaques.width()))
|
|
|
+ self.fenetre.ui.pi_listeAttaques.setColumnWidth(2, (0.7*self.fenetre.ui.pi_listeAttaques.width()))
|
|
|
+ self.connect(self.fenetre.ui.pi_listeAttaques, SIGNAL("itemSelectionChanged()"), self.majInfosAttaqueEC)
|
|
|
+ self.connect(self.fenetre.ui.pi_listeAttaques, SIGNAL("cellClicked(int, int)"), self.listeAttaquesCelluleCliquee)
|
|
|
+ self.connect(self.fenetre.ui.pi_notesAttaqueEC, SIGNAL("textChanged()"), self.majNotesAttaqueEC)
|
|
|
+ self.fenetre.ui.pi_listeAttributsAttaqueEC.setColumnWidth(0, (0.49*self.fenetre.ui.pi_listeAttributsAttaqueEC.width()))
|
|
|
+ self.fenetre.ui.pi_listeAttributsAttaqueEC.setColumnWidth(1, (0.5*self.fenetre.ui.pi_listeAttributsAttaqueEC.width()))
|
|
|
+
|
|
|
+ def majListeAttaques(self):
|
|
|
+ """met a jour la liste des attaques du pion dans le panneau de combat"""
|
|
|
+ #on vide la liste
|
|
|
+ while self.fenetre.ui.pi_listeAttaques.rowCount() > 0:
|
|
|
+ self.fenetre.ui.pi_listeAttaques.removeRow(0)
|
|
|
+
|
|
|
+ self.fenetre.ui.pi_listeAttaques.setVisible((self.pionSelectionne() != None))
|
|
|
+## self.fenetre.ui.editerAttaques.setVisible((self.pionSelectionne() != None))
|
|
|
+ self.fenetre.ui.pi_panneauAttaqueEC.setVisible((self.pionSelectionne() != None))
|
|
|
+
|
|
|
+ i = 0
|
|
|
+ if self.pionSelectionne() != None:
|
|
|
+ for attaque in self.pionSelectionne().attaques:
|
|
|
+ self.fenetre.ui.pi_listeAttaques.insertRow(i)
|
|
|
+ self.fenetre.ui.pi_listeAttaques.setItem(i, 0, QTableWidgetItem(QString.fromUtf8(str(self.pionSelectionne().attaques.index(attaque)))))
|
|
|
+ icone = None
|
|
|
+ if attaque.typ == "cac":
|
|
|
+ icone = QIcon(":/interface/16/ressource/epee_16.png")
|
|
|
+ if attaque.typ == "dist":
|
|
|
+ icone = QIcon(":/interface/16/ressource/arc_16.png")
|
|
|
+ if attaque.typ == "zone":
|
|
|
+ icone = QIcon(":/interface/16/ressource/baguette_16.png")
|
|
|
+ if icone != None:
|
|
|
+ self.fenetre.ui.pi_listeAttaques.setItem(i, 1, QTableWidgetItem(icone, QString.fromUtf8("")))
|
|
|
+ self.fenetre.ui.pi_listeAttaques.setItem(i, 2, QTableWidgetItem(QString.fromUtf8(attaque.nom)))
|
|
|
+ self.majInfosAttaqueEC()
|
|
|
+
|
|
|
+ def listeAttaquesCelluleCliquee(self, ligne, colonne):
|
|
|
+ """on a clique sur une cellule de la liste des attaques"""
|
|
|
+ numAttaque = int(str(self.fenetre.ui.pi_listeAttaques.item(ligne, 0).text().toUtf8()))
|
|
|
+ if numAttaque >= 0:
|
|
|
+ self.utiliserAttaque(numAttaque)
|
|
|
+
|
|
|
+ def utiliserAttaque(self, numAttaque):
|
|
|
+ """le pion selectionne utilise son attaque n"""
|
|
|
+ if self.pionSelectionne() != None:
|
|
|
+ if numAttaque < len(self.pionSelectionne().attaques):
|
|
|
+ attaque = self.pionSelectionne().attaques[numAttaque]
|
|
|
+ if attaque.typ == "cac":
|
|
|
+ self.majModeCombat("combatAttaqueCaC")
|
|
|
+ if attaque.typ == "dist":
|
|
|
+ self.majModeCombat("combatAttaqueDist")
|
|
|
+ if attaque.typ == "zone":
|
|
|
+ self.modeParam["typeAttaqueZone"] = attaque.formeZone
|
|
|
+ self.fenetre.ui.pi_rayonAttaqueZone.setValue(attaque.rayon)
|
|
|
+ self.majModeCombat("combatAttaqueZone")
|
|
|
+
|
|
|
+ def majInfosAttaqueEC(self):
|
|
|
+ """met a jour les infos de l'attaque en cours (selectionnee)"""
|
|
|
+ selection = self.fenetre.ui.pi_listeAttaques.selectedItems()
|
|
|
+ self.fenetre.ui.pi_panneauAttaqueEC.setVisible(self.pionSelectionne() != None and len(selection) > 0)
|
|
|
+
|
|
|
+ if self.pionSelectionne() != None and len(selection) > 0:
|
|
|
+ ligne = selection[0].row()
|
|
|
+ numAttaque = int(str(self.fenetre.ui.pi_listeAttaques.item(ligne, 0).text().toUtf8()))
|
|
|
+ self.disconnect(self.fenetre.ui.pi_panneauAttaqueEC, SIGNAL("cellChanged(int,int)"), self.attaqueECCelluleModifiee)
|
|
|
+ #on vide la liste
|
|
|
+ while self.fenetre.ui.pi_listeAttributsAttaqueEC.rowCount() > 0:
|
|
|
+ self.fenetre.ui.pi_listeAttributsAttaqueEC.removeRow(0)
|
|
|
+
|
|
|
+ self.fenetre.ui.pi_listeAttributsAttaqueEC.insertRow(0)
|
|
|
+ self.fenetre.ui.pi_listeAttributsAttaqueEC.setItem(0, 0, QTableWidgetItem(QString.fromUtf8("numAtt")))
|
|
|
+ self.fenetre.ui.pi_listeAttributsAttaqueEC.setItem(0, 1, QTableWidgetItem(QString.fromUtf8(str(numAttaque))))
|
|
|
+ self.fenetre.ui.pi_listeAttributsAttaqueEC.setRowHidden(0, True)
|
|
|
+
|
|
|
+ #attributs issus des regles utilisees
|
|
|
+ ordre = regles.ordreAttributsAttaques()
|
|
|
+ for elt in ordre:
|
|
|
+ ligne = 1 + ordre.index(elt)
|
|
|
+ self.fenetre.ui.pi_listeAttributsAttaqueEC.insertRow(ligne)
|
|
|
+ item = QTableWidgetItem(QString.fromUtf8(elt))
|
|
|
+ item.setFlags(Qt.NoItemFlags)
|
|
|
+ self.fenetre.ui.pi_listeAttributsAttaqueEC.setItem(ligne, 0, item)
|
|
|
+ self.fenetre.ui.pi_listeAttributsAttaqueEC.setItem(ligne, 1, QTableWidgetItem(QString.fromUtf8(str(self.pionSelectionne().attaques[numAttaque].attributs[elt]))))
|
|
|
+
|
|
|
+ self.connect(self.fenetre.ui.pi_listeAttributsAttaqueEC, SIGNAL("cellChanged(int,int)"), self.attaqueECCelluleModifiee)
|
|
|
+ #maj des notes
|
|
|
+ self.disconnect(self.fenetre.ui.pi_notesAttaqueEC, SIGNAL("textChanged()"), self.majNotesAttaqueEC)
|
|
|
+ self.fenetre.ui.pi_notesAttaqueEC.majTexte(self.pionSelectionne().attaques[numAttaque].notes)
|
|
|
+ self.connect(self.fenetre.ui.pi_notesAttaqueEC, SIGNAL("textChanged()"), self.majNotesAttaqueEC)
|
|
|
+
|
|
|
+ def attaqueECCelluleModifiee(self, ligne, colonne):
|
|
|
+ """une cellule de la liste d'attributs de l'attaque en cours a ete modifiee"""
|
|
|
+ pass
|
|
|
+
|
|
|
+ def majNotesAttaqueEC(self):
|
|
|
+ """met a jour les notes de l'attaque en cours (selectionnee)"""
|
|
|
+ selection = self.fenetre.ui.pi_listeAttaques.selectedItems()
|
|
|
+ self.fenetre.ui.pi_panneauAttaqueEC.setVisible(self.pionSelectionne() != None and len(selection) > 0)
|
|
|
+ if self.pionSelectionne() != None and len(selection) > 0:
|
|
|
+ ligne = selection[0].row()
|
|
|
+ numAttaque = int(str(self.fenetre.ui.pi_listeAttaques.item(ligne, 0).text().toUtf8()))
|
|
|
+ self.pionSelectionne().attaques[numAttaque].notes = str(self.fenetre.ui.pi_notesAttaqueEC.toPlainText().toUtf8())
|
|
|
+
|
|
|
+ def majNotesCombattant(self):
|
|
|
+ """les notes du pion ont ete mises a jour"""
|
|
|
+ if self.pionSelectionne() != None:
|
|
|
+ self.pionSelectionne().notes = str(self.fenetre.ui.pi_notes.toPlainText().toUtf8())
|
|
|
+ else:
|
|
|
+ pass
|
|
|
+
|
|
|
+ ###############
|
|
|
+
|
|
|
+ ### panneau d'info
|
|
|
+ def majInfosCombattant(self, combattant=None):
|
|
|
+ self.fenetre.ui.inf_boitePion.maj(combattant)
|
|
|
+
|
|
|
+ def majInfosDecor(self, decor=None):
|
|
|
+ self.fenetre.ui.inf_boiteDecor.maj(decor)
|
|
|
+
|
|
|
+ def majInfosCase(self, case=None):
|
|
|
+ self.fenetre.ui.inf_boiteCase.maj(case)
|
|
|
+
|
|
|
+ ############### fonctions de calcul ################
|
|
|
+ def coordonneesValides(self, coord):
|
|
|
+ """les coordonnees entrees en parametre sont elles celles d'une case du plateau"""
|
|
|
+ return (coord[0] >= 0 and coord[1] >= 0 and coord[0] < self.nbCasesX and coord[1] < self.nbCasesY)
|
|
|
+
|
|
|
+ def lstCoordAdjacentes(self, x, y):
|
|
|
+ """renvoie la liste des coordonnees adjacentes, !!!! sans condition d'existence sur le plateau !!!!
|
|
|
+ attention: l'ordre est important"""
|
|
|
+ if self.formeCases == "H":
|
|
|
+ if 1 == (x % 2):
|
|
|
+ voisins = [(x, y-1), (x+1, y), (x+1, y+1), (x, y+1), (x-1, y+1), (x-1, y)]
|
|
|
+ else:
|
|
|
+ voisins = [(x, y-1), (x+1, y-1), (x+1, y), (x, y+1), (x-1, y), (x-1, y-1)]
|
|
|
+ else:
|
|
|
+ voisins = [(x, y-1), (x+1, y), (x, y+1), (x-1, y)]
|
|
|
+ return voisins
|
|
|
+
|
|
|
+ def zone(self, origine, rayon, z=0, conditionFranchissable = False, conditionVisible = False):
|
|
|
+ """renvoie un dictionnaire representant la liste des coordonnees des cases comprises dans la zone
|
|
|
+ la zone en question est la liste des cases situees a une distance d des coordonnees d'origine
|
|
|
+ z = 0 -> hauteur z de l'origine par rapport a l'altitude de la case
|
|
|
+ conditionFranchissable = Vrai -> les cases infranchissables ne sont pas prises en compte
|
|
|
+ conditionVisible = Vrai -> les cases bloquant la visibilite ne sont pas prises en compte"""
|
|
|
+ aVerifier = []
|
|
|
+ aVerifier2 = []
|
|
|
+ resultat = {}
|
|
|
+ k = 0
|
|
|
+ #on part de la premiere case, puis on itere a partir de chaque nouveau depart sur les voisins
|
|
|
+ if origine in self.cases:
|
|
|
+ aVerifier.append(origine)
|
|
|
+ while k <= rayon:
|
|
|
+ for depart in aVerifier:
|
|
|
+ for coord in self.cases[depart].voisins:
|
|
|
+ if not coord in aVerifier and not coord in aVerifier2 and not coord in resultat:
|
|
|
+ if conditionFranchissable and not conditionVisible:
|
|
|
+ if self.cases[coord].estFranchissable(z):
|
|
|
+ aVerifier2.append(coord)
|
|
|
+ elif not conditionFranchissable and conditionVisible:
|
|
|
+ if self.cases[coord].terrain.visibilite:
|
|
|
+ aVerifier2.append(coord)
|
|
|
+ elif conditionFranchissable and conditionVisible:
|
|
|
+ if self.cases[coord].estFranchissable(z) and self.cases[coord].terrain.visibilite:
|
|
|
+ aVerifier2.append(coord)
|
|
|
+ else:
|
|
|
+ aVerifier2.append(coord)
|
|
|
+ for elt in aVerifier:
|
|
|
+ resultat[elt] = k
|
|
|
+ aVerifier = aVerifier2
|
|
|
+ aVerifier2 = []
|
|
|
+ k += 1
|
|
|
+ return resultat
|
|
|
+
|
|
|
+ def zone3d(self, origine, rayon, zCible=0):
|
|
|
+ """renvoie les cases de la zone au format (x, y, z)"""
|
|
|
+ retour = []
|
|
|
+ zone = self.zone(origine, rayon)
|
|
|
+ for coord in zone:
|
|
|
+ x, y = coord
|
|
|
+ dz = rayon - zone[coord]
|
|
|
+ for z in range(-dz, dz + 1):
|
|
|
+ retour.append( (x, y, (zCible+z) ) )
|
|
|
+ return retour
|
|
|
+
|
|
|
+ def cone(self, coord1, coord2):
|
|
|
+ """renvoie les coord des cases composant le cone (en 2d)"""
|
|
|
+ pass
|
|
|
+
|
|
|
+ def polygoneAgglo(self, listeCases):
|
|
|
+ """renvoie un polygone contruit par agglomeration des polygones des cases de la liste
|
|
|
+ les cases doivent etre adjacentes (cases hexagonales ou carrees)"""
|
|
|
+ pointsPolygone = []
|
|
|
+ segments = []
|
|
|
+ case = Case(self)
|
|
|
+
|
|
|
+ #on verifie que toutes les cases sont adjacentes les unes aux autres
|
|
|
+ valide = True
|
|
|
+ if len(listeCases) > 1:
|
|
|
+ for coord in listeCases:
|
|
|
+ if not len(set(listeCases).intersection(self.lstCoordAdjacentes(coord[0], coord[1]))) > 0: valide = False
|
|
|
+ if not len(listeCases) > 0:
|
|
|
+ valide = False
|
|
|
+
|
|
|
+ if valide:
|
|
|
+ #on parcourt les faces des polygones des cases, et on ne garde que ceux qui n'ont pas de case 'en face'
|
|
|
+ for coord in listeCases:
|
|
|
+ polygone = case.polygone(coord[0], coord[1])
|
|
|
+ voisins = self.lstCoordAdjacentes(coord[0], coord[1])
|
|
|
+
|
|
|
+ for i in range(0, len(voisins)):
|
|
|
+ if not voisins[i] in listeCases:
|
|
|
+ j = i+1
|
|
|
+ if j > len(voisins) - 1:
|
|
|
+ j = 0
|
|
|
+ segments.append(QLineF(polygone[i], polygone[j]))
|
|
|
+
|
|
|
+ #on 'accroche' les segments les uns aux autres, dans l'ordre
|
|
|
+ segments2 = [segments[0]]
|
|
|
+ for segment2 in segments2:
|
|
|
+ for segment in segments:
|
|
|
+ if not QLineF(segment.p1(), segment.p2()) in segments2 and not QLineF(segment.p2(), segment.p1()) in segments2:
|
|
|
+ if sqrt((segment.p1().x()-segment2.p2().x())**2+(segment.p1().y()-segment2.p2().y())**2) < 1:
|
|
|
+ segments2.append(QLineF(segment.p1(), segment.p2()))
|
|
|
+ elif sqrt((segment.p2().x()-segment2.p2().x())**2+(segment.p2().y()-segment2.p2().y())**2) < 1:
|
|
|
+ segments2.append(QLineF(segment.p2(), segment.p1()))
|
|
|
+
|
|
|
+ pointsPolygone = []
|
|
|
+ premierPoint = segments2[0].p1()
|
|
|
+ pointsPolygone.append(premierPoint)
|
|
|
+ for segment in segments2:
|
|
|
+ pointSuivant = segment.p2()
|
|
|
+ if pointSuivant != premierPoint:
|
|
|
+ pointsPolygone.append(pointSuivant)
|
|
|
+
|
|
|
+ #creation du polygone
|
|
|
+ polygone = QPolygonF()
|
|
|
+ for point in pointsPolygone:
|
|
|
+ polygone.append(point)
|
|
|
+ else:
|
|
|
+ polygone = None
|
|
|
+
|
|
|
+ return polygone
|
|
|
+
|
|
|
+ def coordCentreListeCases(self, listeCases):
|
|
|
+ """renvoie les coordonnees centrales d'une liste de cases"""
|
|
|
+ retour = None
|
|
|
+ if len(listeCases) > 0:
|
|
|
+ listeTriee = sorted(listeCases)
|
|
|
+ posMilieu = int(len(listeCases)/2)
|
|
|
+ retour = listeTriee[posMilieu]
|
|
|
+ return retour
|
|
|
+
|
|
|
+ def coordonneesAuPoint(self, point):
|
|
|
+ """renvoie les coordonnees de la case situee au QPointF entre en parametre"""
|
|
|
+ coord = None
|
|
|
+ if point != None:
|
|
|
+ lstObjets = self.vue().scene().items(point)
|
|
|
+ for objet in lstObjets:
|
|
|
+ if objet:
|
|
|
+ if objet.__class__.__name__ == "Case":
|
|
|
+ coord = (objet.x, objet.y)
|
|
|
+ break
|
|
|
+ return coord
|
|
|
+
|
|
|
+ def casesSousForme(self, forme, plein = True, epaisseur = 0):
|
|
|
+ """renvoie la liste des cases en collision avec un QGraphicsItem en parametre
|
|
|
+ plein = False: pas le contenu de la forme
|
|
|
+ epaisseur = renvoie aussi les cases voisines jusqu'a la distance demandee"""
|
|
|
+ tmp = []
|
|
|
+ listeCases = []
|
|
|
+ point1 = None
|
|
|
+ point2 = None
|
|
|
+ #point 1 et 2
|
|
|
+ if forme.__class__.__name__ == "QGraphicsLineItem":
|
|
|
+ point1 = forme.line().p1()
|
|
|
+ point2 = forme.line().p2()
|
|
|
+ elif forme.__class__.__name__ == "QGraphicsRectItem" or forme.__class__.__name__ == "QGraphicsEllipseItem":
|
|
|
+ point1 = forme.rect().topLeft()
|
|
|
+ point2 = forme.rect().bottomRight()
|
|
|
+ else:
|
|
|
+ point1 = forme.boundingRect().topLeft()
|
|
|
+ point2 = forme.boundingRect().bottomRight()
|
|
|
+
|
|
|
+ #preselection des cases (meilleures perf)
|
|
|
+ if point1 != None and point2 != None and point1 != point2:
|
|
|
+ preSelection = self.preSelectionCollision(point1, point2)
|
|
|
+ else:
|
|
|
+ preSelection = []
|
|
|
+ for coord in self.cases:
|
|
|
+ preSelection.append(coord)
|
|
|
+
|
|
|
+ #on liste les cases en collision avec la forme
|
|
|
+ for coord in preSelection:
|
|
|
+ if self.cases[coord].collidesWithItem(forme, Qt.IntersectsItemShape):
|
|
|
+ if plein:
|
|
|
+ tmp.append(coord)
|
|
|
+ else:
|
|
|
+ contenu = True
|
|
|
+ for i in range(0,len(self.cases[coord].polygon())):
|
|
|
+ if not forme.contains(self.cases[coord].polygon().at(i)):
|
|
|
+ contenu = False
|
|
|
+ break
|
|
|
+ if contenu == False:
|
|
|
+ tmp.append(coord)
|
|
|
+ #on applique l'epaisseur du pinceau (lignes ou formes vides seulement) si necessaire
|
|
|
+ if not plein and epaisseur > 0:
|
|
|
+ for coord in tmp:
|
|
|
+ zone = self.zone(coord, epaisseur)
|
|
|
+ for coord2 in zone:
|
|
|
+ if not coord2 in listeCases:
|
|
|
+ listeCases.append(coord2)
|
|
|
+ else:
|
|
|
+ listeCases = tmp
|
|
|
+ #si la liste est vide, on ajoute l'origine de la forme
|
|
|
+ if len(listeCases) == 0:
|
|
|
+ listeCases = [self.coordonneesAuPoint(point1)]
|
|
|
+ return listeCases
|
|
|
+
|
|
|
+ def preSelectionCollision(self, point1, point2):
|
|
|
+ """renvoie une liste des cases qui peuvent etre concernees par une collision avec
|
|
|
+ un graphicsItem (pour des raisons de performance)"""
|
|
|
+ preSelection = []
|
|
|
+ coord1 = self.coordonneesAuPoint(point1)
|
|
|
+ coord2 = self.coordonneesAuPoint(point2)
|
|
|
+ if coord1 != None and coord2 != None:
|
|
|
+ minX = min(coord1[0], coord2[0]) - 1
|
|
|
+ maxX = max(coord1[0], coord2[0]) + 1
|
|
|
+ minY = min(coord1[1], coord2[1]) - 1
|
|
|
+ maxY = max(coord1[1], coord2[1]) + 1
|
|
|
+ for coord in self.cases:
|
|
|
+ if coord[0] >= minX and coord[0] <= maxX and coord[1] >= minY and coord[1] <= maxY :
|
|
|
+ preSelection.append(coord)
|
|
|
+ else:
|
|
|
+ preSelection = self.cases
|
|
|
+ return preSelection
|
|
|
+
|
|
|
+ def listeZCible(self, coord):
|
|
|
+ """retourne l'altitude absolue a prendre en compte en fonction de la case ciblee
|
|
|
+ c'est l'altitude la case si aucun pion n'occupe la case
|
|
|
+ c'est la liste des cases occupees en hauteur par le pion sinon
|
|
|
+ 'coord' est de la forme (x, y)"""
|
|
|
+ if self.cases[coord].estOccupee():
|
|
|
+ retour = range(self.cases[coord].occupant().zAbs(), \
|
|
|
+ self.cases[coord].occupant().zAbs() + self.cases[coord].occupant().hauteur)
|
|
|
+ else:
|
|
|
+ retour = [self.cases[coord].altitude]
|
|
|
+ return retour
|
|
|
+
|
|
|
+ def estCibleAttaqueDistValide(self, coordCible):
|
|
|
+ """la case cible est elle valide pour une attaque a distance depuis la position et hauteur
|
|
|
+ du pion selectionne
|
|
|
+ les coord sont de la forme (x, y)"""
|
|
|
+ valide = False
|
|
|
+ x1, y1 = self.pionSelectionne().position
|
|
|
+ coordOrigine = (x1, y1, (self.pionSelectionne().zAbs() + self.pionSelectionne().hauteur))
|
|
|
+
|
|
|
+ x2, y2 = coordCible
|
|
|
+ cible = self.cases[coordCible].occupant()
|
|
|
+ listeZ2 = self.listeZCible(coordCible)
|
|
|
+ if coordOrigine[0] != coordCible[0] or coordOrigine[1] != coordCible[1]:
|
|
|
+ for z2 in listeZ2:
|
|
|
+ zValide = True
|
|
|
+ casesLigneMire = br.ligne(coordOrigine, (x2, y2, z2), self.formeCases)
|
|
|
+ casesLigneMire.remove(coordOrigine)
|
|
|
+ casesLigneMire.remove((x2, y2, z2))
|
|
|
+ for coord in casesLigneMire:
|
|
|
+ if zValide:
|
|
|
+ x, y, z = coord
|
|
|
+ if self.cases[(x,y)].estOccupee(z):
|
|
|
+ if self.cases[(x,y)].occupant(z) not in [self.pionSelectionne(), cible]:
|
|
|
+ zValide = False
|
|
|
+ if zValide:
|
|
|
+ valide = True #si au moins un des z cibles est valide, la ligne de mire est valide
|
|
|
+ break
|
|
|
+
|
|
|
+ return valide
|
|
|
+
|
|
|
+ def pionSurCase(self, coord):
|
|
|
+ """renvoie le pion present sur la case, none sinon"""
|
|
|
+ retour = None
|
|
|
+ for num in self.combattants:
|
|
|
+ if self.combattants[num].position == coord:
|
|
|
+ retour = num
|
|
|
+ return retour
|
|
|
+
|
|
|
+ def pionsSurListeCase(self, listeCases):
|
|
|
+ """renvoie la liste des num des pions presents sur la liste de cases"""
|
|
|
+ retour = []
|
|
|
+ for coord in listeCases:
|
|
|
+ pion = self.cases[coord].occupant()
|
|
|
+ if pion != None and not pion.numero in retour:
|
|
|
+ retour.append(pion.numero)
|
|
|
+ return retour
|
|
|
+
|
|
|
+ def majZonePlacement(self, listeCases):
|
|
|
+ """met a jour la forme et l'affichage de la zone de placement initale des joueurs"""
|
|
|
+ if len(listeCases) > 0:
|
|
|
+ if self.polygoneZonePlacement == None:
|
|
|
+ self.polygoneZonePlacement = QGraphicsPolygonItem(scene=self)
|
|
|
+ self.polygoneZonePlacement.setZValue(0)
|
|
|
+ qCouleurFond = QColor("white")
|
|
|
+ qCouleurFond.setAlpha(50)
|
|
|
+ self.polygoneZonePlacement.setBrush(qCouleurFond)
|
|
|
+ pinceau = QPen(QColor("orange"))
|
|
|
+ pinceau.setWidth(20)
|
|
|
+ self.polygoneZonePlacement.setPen(pinceau)
|
|
|
+ self.polygoneZonePlacement.setAcceptedMouseButtons(Qt.NoButton)
|
|
|
+ self.polygoneZonePlacement.setAcceptHoverEvents(False)
|
|
|
+ self.addItem(self.polygoneZonePlacement)
|
|
|
+ listeCases2 = []
|
|
|
+ for coord in listeCases:
|
|
|
+ if self.cases[coord].estFranchissable():
|
|
|
+ listeCases2.append(coord)
|
|
|
+ self.polygoneZonePlacement.setPolygon(self.polygoneAgglo(listeCases2))
|
|
|
+ self.listeCasesZonePlacement = listeCases
|
|
|
+
|
|
|
+ def materialiserPions(self,actif):
|
|
|
+ """avtive/desactive la reception par les pions (autres que le pion selectionne) des hover events"""
|
|
|
+ for numCombattant in self.combattants:
|
|
|
+ if numCombattant != self.modeParam["numPionSelectionne"]:
|
|
|
+ self.combattants[numCombattant].setAcceptsHoverEvents(actif)
|
|
|
+ self.combattants[numCombattant].polygoneGraphique.setAcceptsHoverEvents(actif)
|
|
|
+ for numCombattant in self.decors:
|
|
|
+ self.decors[numCombattant].setAcceptsHoverEvents(actif)
|
|
|
+ self.decors[numCombattant].polygoneGraphique.setAcceptsHoverEvents(actif)
|
|
|
+
|
|
|
+ #######################
|
|
|
+
|
|
|
+ ######## interaction avec les cases, decors et pions #############
|
|
|
+ def pionSelectionne(self):
|
|
|
+ """renvoie le pion actuellement selectionne"""
|
|
|
+ retour = None
|
|
|
+ if self.modeActif.__class__.__name__ == "PionSelectionne":
|
|
|
+ retour = self.modeActif.pion()
|
|
|
+ return retour
|
|
|
+
|
|
|
+ def caseCliquee(self, x, y):
|
|
|
+ """on a clique sur la case (clic gauche)"""
|
|
|
+ coord = (x, y)
|
|
|
+ accepte = self.modeActif.clic_case(coord)
|
|
|
+ return accepte
|
|
|
+
|
|
|
+ def caseSurvolClicEnfonce(self, coord):
|
|
|
+ """une case est survolee par le curseur (le clic gauche est enfonce)"""
|
|
|
+ accepte = self.modeActif.survolClic_case(coord)
|
|
|
+ return accepte
|
|
|
+
|
|
|
+ def caseSurvol(self, x, y):
|
|
|
+ """une case est survole par le curseur, on affiche ses informations dans la zone prevue"""
|
|
|
+ self.majInfosCase(self.cases[(x,y)])
|
|
|
+ accepte = self.modeActif.survol_case((x,y))
|
|
|
+ return accepte
|
|
|
+
|
|
|
+ def afficherListeCases(self, listeCases, actif):
|
|
|
+ """met ou non en evidence les cases selectionnees"""
|
|
|
+ for coord in listeCases:
|
|
|
+ self.cases[coord].majEstCibleCurseur(actif)
|
|
|
+
|
|
|
+ def pionClique(self, num):
|
|
|
+ """on a clique sur ce pion"""
|
|
|
+ if num < 10000:
|
|
|
+ accepte = self.modeActif.clic_combattant(num)
|
|
|
+ else:
|
|
|
+ accepte = self.modeActif.clic_decor(num)
|
|
|
+ return accepte
|
|
|
+
|
|
|
+ def combattantSurvol(self, num):
|
|
|
+ """le pion est survole par le curseur, on affiche ses informations dans la zone prevue"""
|
|
|
+ accepte = self.modeActif.survol_combattant(num)
|
|
|
+ pion = self.combattants[num]
|
|
|
+ self.majInfosCombattant(pion)
|
|
|
+ if not accepte:
|
|
|
+ accepte = self.caseSurvol(pion.position[0], pion.position[1])
|
|
|
+ return accepte
|
|
|
+
|
|
|
+ def combattantFinSurvol(self, num):
|
|
|
+ """le pion est survole par le curseur, on affiche ses informations dans la zone prevue"""
|
|
|
+ accepte = self.modeActif.finSurvol_combattant(num)
|
|
|
+ self.majInfosCombattant(None)
|
|
|
+ return accepte
|
|
|
+
|
|
|
+ def decorSurvol(self, num):
|
|
|
+ """le pion est survole par le curseur, on affiche ses informations dans la zone prevue"""
|
|
|
+ accepte = self.modeActif.survol_decor(num)
|
|
|
+ pion = self.decors[num]
|
|
|
+ self.majInfosDecor(pion)
|
|
|
+ if not accepte:
|
|
|
+ accepte = self.caseSurvol(pion.position[0], pion.position[1])
|
|
|
+ return accepte
|
|
|
+
|
|
|
+ def decorFinSurvol(self, num):
|
|
|
+ """le pion est survole par le curseur, on affiche ses informations dans la zone prevue"""
|
|
|
+ accepte = self.modeActif.finSurvol_decor(num)
|
|
|
+ self.majInfosDecor(None)
|
|
|
+ return accepte
|
|
|
+
|
|
|
+ def pionDoubleClic(self, numCombattant):
|
|
|
+ """on a double-clique sur le pion"""
|
|
|
+ accepte = self.modeActif.doubleClic_combattant(numCombattant)
|
|
|
+ return accepte
|
|
|
+
|
|
|
+ def creerPion(self, pionModele):
|
|
|
+ """creer un pion (combattant ou decor) aux coordonnees indiquees"""
|
|
|
+ cree = False
|
|
|
+ if self.proj.projectionValide():
|
|
|
+
|
|
|
+ if pionModele.__class__.__name__ == "Combattant":
|
|
|
+ pion = Combattant()
|
|
|
+ elif pionModele.__class__.__name__ == "Decor":
|
|
|
+ pion = Decor()
|
|
|
+
|
|
|
+ for elt in pionModele.__dict__:
|
|
|
+ pion.__dict__[elt] = pionModele.__dict__[elt]
|
|
|
+
|
|
|
+ if pionModele.__class__.__name__ == "Combattant":
|
|
|
+ numero = 1
|
|
|
+ if len(self.combattants) > 0:
|
|
|
+ numero = max(self.combattants) + 1
|
|
|
+ pion.numero = numero
|
|
|
+ pion.numComplementaire = self.numeroterNom(pion.nom)
|
|
|
+ self.combattants[numero] = pion
|
|
|
+ self.pionDeplacerDansOrdreJeu(numero, len(self.ordreJeu) + 2)
|
|
|
+
|
|
|
+ elif pionModele.__class__.__name__ == "Decor":
|
|
|
+ numero = 10001
|
|
|
+ if len(self.decors) > 0:
|
|
|
+ numero = max(self.decors) + 10001
|
|
|
+ pion.numero = numero
|
|
|
+ self.decors[numero] = pion
|
|
|
+
|
|
|
+ pion.position = self.proj.coord()
|
|
|
+ pion.nbRotations = self.proj.nbRotations()
|
|
|
+ pion.ajouterAuPlateau(self)
|
|
|
+
|
|
|
+ cree = True
|
|
|
+ return cree
|
|
|
+
|
|
|
+ def numeroterNom(self, nom):
|
|
|
+ """renvoie le nom du pion avec un numero complementaire si necessaire """
|
|
|
+ i = 1
|
|
|
+ for numCombattant in self.combattants:
|
|
|
+ if self.combattants[numCombattant].nom == nom:
|
|
|
+ i += 1
|
|
|
+ if i == 1:
|
|
|
+ retour = ""
|
|
|
+ else:
|
|
|
+ retour = str(i)
|
|
|
+ return retour
|
|
|
+
|
|
|
+ def pionDeposer(self, coordCase):
|
|
|
+ """on depose le pion sur la case voulue"""
|
|
|
+ if self.pionSelectionne() != None:
|
|
|
+ pion = self.pionSelectionne()
|
|
|
+
|
|
|
+ if pion != None:
|
|
|
+ if self.proj.projectionValide():
|
|
|
+ pion.majPosition(self.proj.coord(), self.proj.nbRotations())
|
|
|
+
|
|
|
+ def majZPion(self, valeur):
|
|
|
+ """met a jour l'altitude du pion selectionne"""
|
|
|
+ if self.pionSelectionne() != None:
|
|
|
+ self.pionSelectionne().majZ(valeur)
|
|
|
+
|
|
|
+ def dialogueVol(self, actuelle):
|
|
|
+ ecran = EcranVol(actuelle)
|
|
|
+ ecran.exec_()
|
|
|
+ nouvelle = ecran.resultat()
|
|
|
+ del ecran
|
|
|
+ return nouvelle
|
|
|
+
|
|
|
+ def pionSupprimer(self, num):
|
|
|
+ """supprime le pion entre en parametre"""
|
|
|
+ #settrace(trace_calls)
|
|
|
+ if num in self.combattants:
|
|
|
+ self.pionDeplacerDansOrdreJeu(num, 0)
|
|
|
+ pionSuppr = self.combattants.pop(num)
|
|
|
+ elif num in self.decors:
|
|
|
+ pionSuppr = self.decors.pop(num)
|
|
|
+
|
|
|
+ pionSuppr.retirerDuPlateau()
|
|
|
+
|
|
|
+ ###############
|
|
|
+
|
|
|
+ ######### caches ###############
|
|
|
+ def activerModeCreationCache(self):
|
|
|
+ self.activerMode(Modes.EditerCaches)
|
|
|
+
|
|
|
+ def activerModeEditionCache(self):
|
|
|
+ idCache = int(self.fenetre.ui.cp_listeCaches.texte(self.fenetre.ui.cp_listeCaches.currentRow(), 0))
|
|
|
+ self.activerMode(Modes.EditerCaches, idCache)
|
|
|
+
|
|
|
+ def initListeCaches(self):
|
|
|
+ """charge la liste des caches avec les donnees en memoire"""
|
|
|
+ self.fenetre.ui.cp_listeCaches.setColumnWidth(0, 10)
|
|
|
+ self.fenetre.ui.cp_listeCaches.setColumnWidth(1, 100)
|
|
|
+ self.fenetre.ui.cp_listeCaches.setColumnWidth(2, 18)
|
|
|
+ for idCache in self.caches:
|
|
|
+ self.ajouterCacheATable(self.caches[idCache])
|
|
|
+
|
|
|
+ def nouveauCache(self, listeCases):
|
|
|
+ nouvelId = 0
|
|
|
+ if len(self.caches) > 0:
|
|
|
+ nouvelId = max(self.caches) + 1
|
|
|
+ cache = Cache(nouvelId)
|
|
|
+ cache.activer(True)
|
|
|
+ cache.nom = "Cache {}".format(nouvelId + 1)
|
|
|
+ self.caches[nouvelId] = cache
|
|
|
+ self.ajouterCacheATable(cache)
|
|
|
+ for coord in listeCases:
|
|
|
+ self.cases[coord].ajouterCache(nouvelId)
|
|
|
+
|
|
|
+ def editerFormeCache(self, idCache, listeCases):
|
|
|
+ """edite le cache avec la liste des cases en param"""
|
|
|
+ actif = self.caches[idCache].actif()
|
|
|
+ for coord in self.cases:
|
|
|
+ if coord in listeCases:
|
|
|
+ self.cases[coord].ajouterCache(idCache, actif)
|
|
|
+ else:
|
|
|
+ self.cases[coord].supprimerCache(idCache)
|
|
|
+
|
|
|
+ def majEtatCache(self, actif):
|
|
|
+ emetteur = self.sender().objectName()
|
|
|
+ idCache = int(emetteur.replace("afficherCache_", ""))
|
|
|
+ self.caches[idCache].activer(actif)
|
|
|
+ if actif:
|
|
|
+ nomImg = "oeilBarre2_32.png"
|
|
|
+ else:
|
|
|
+ nomImg = "oeil_32.png"
|
|
|
+ self.fenetre.ui.cp_listeCaches.item(idCache, 1).setIcon(QIcon(":/interface/32/ressource/{}".format(nomImg)))
|
|
|
+ for coord in self.cases:
|
|
|
+ self.cases[coord].activerCache(idCache, actif)
|
|
|
+
|
|
|
+ def majNomCache(self, ligne, colonne):
|
|
|
+ idCache = int(self.fenetre.ui.cp_listeCaches.texte(ligne, 0))
|
|
|
+ nouveauNom = self.fenetre.ui.cp_listeCaches.texte(ligne, 1)
|
|
|
+ if nouveauNom != self.caches[idCache].nom:
|
|
|
+ self.caches[idCache].nom = nouveauNom
|
|
|
+
|
|
|
+ def supprimerCache(self):
|
|
|
+ ligne = self.fenetre.ui.cp_listeCaches.currentRow()
|
|
|
+ idCache = int(self.fenetre.ui.cp_listeCaches.texte(ligne, 0))
|
|
|
+ for coord in self.cases:
|
|
|
+ self.cases[coord].supprimerCache(idCache)
|
|
|
+ self.fenetre.ui.cp_listeCaches.removeRow(idCache)
|
|
|
+ del self.caches[idCache]
|
|
|
+
|
|
|
+ def mettreCacheEnEvidence(self, ligne, colonne):
|
|
|
+ idCache = int(self.fenetre.ui.cp_listeCaches.texte(ligne, 0))
|
|
|
+ for coord in self.cases:
|
|
|
+ if len(self.cases[coord].cachesActifs) > 0:
|
|
|
+ self.cases[coord].polygoneCache.activerSurbrillance((idCache in self.cases[coord].cachesActifs))
|
|
|
+
|
|
|
+ def ajouterCacheATable(self, cache):
|
|
|
+ """ajoute le cache a la table des caches"""
|
|
|
+ self.fenetre.disconnect(self.fenetre.ui.cp_listeCaches, SIGNAL("cellChanged(int,int)"), self.majNomCache)
|
|
|
+ ligne = self.fenetre.ui.cp_listeCaches.nouvelleLigneFin()
|
|
|
+ if cache.actif():
|
|
|
+ nomImg = "oeilBarre2_32.png"
|
|
|
+ else:
|
|
|
+ nomImg = "oeil_32.png"
|
|
|
+ self.fenetre.ui.cp_listeCaches.majTexte(ligne, 0, str(cache.numero))
|
|
|
+
|
|
|
+ item = QTableWidgetItem(QIcon(":/interface/32/ressource/{}".format(nomImg)), cache.nom)
|
|
|
+ item.setFlags(Qt.ItemIsEnabled | Qt.ItemIsSelectable | Qt.ItemIsEditable)
|
|
|
+ self.fenetre.ui.cp_listeCaches.setItem(ligne, 1, item)
|
|
|
+
|
|
|
+ widget = QCheckBox(QString(""))
|
|
|
+ widget.setChecked(cache.actif())
|
|
|
+ widget.setObjectName(QString("afficherCache_{}".format(ligne)))
|
|
|
+ self.connect(widget, SIGNAL("toggled(bool)"), self.majEtatCache)
|
|
|
+ self.fenetre.ui.cp_listeCaches.setCellWidget(ligne, 2, widget)
|
|
|
+
|
|
|
+ self.fenetre.connect(self.fenetre.ui.cp_listeCaches, SIGNAL("cellChanged(int,int)"), self.majNomCache, Qt.UniqueConnection)
|
|
|
+ ###############"
|
|
|
+
|
|
|
+ ######### gestion des evenements souris et clavier ###############
|
|
|
+ def mouseMoveEvent(self, event):
|
|
|
+ super(Plateau, self).mouseMoveEvent(event)
|
|
|
+ if event.buttons() == Qt.LeftButton and self.vue().dragMode() != QGraphicsView.ScrollHandDrag:
|
|
|
+ coord = self.coordonneesAuPoint(event.scenePos())
|
|
|
+ if coord != None:
|
|
|
+ self.caseSurvolClicEnfonce(coord)
|
|
|
+ else:
|
|
|
+ self.modeActif.mouvementSouris(event)
|
|
|
+ event.ignore()
|
|
|
+
|
|
|
+ def mousePressEvent(self, event):
|
|
|
+ super(Plateau, self).mousePressEvent(event)
|
|
|
+ if event.button() == 1:
|
|
|
+ self.modeActif.clicGauche(event)
|
|
|
+ elif event.button() == 2:
|
|
|
+ self.modeActif.clicDroit(event)
|
|
|
+ event.accept()
|
|
|
+
|
|
|
+ def mouseReleaseEvent(self, event):
|
|
|
+ super(Plateau, self).mouseReleaseEvent(event)
|
|
|
+ self.modeActif.finClicGauche(event)
|
|
|
+
|
|
|
+ def keyPressEvent(self, event):
|
|
|
+ """gestion des evenements clavier"""
|
|
|
+ self.modeActif.toucheClavier(event)
|
|
|
+
|
|
|
+ ################
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|