Plateau.py 55 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207
  1. #from __future__ import unicode_literals
  2. # -*- coding: utf-8 -*-
  3. from __future__ import division
  4. from time import time
  5. from PyQt4.QtCore import Qt, SIGNAL, QPointF, QString
  6. from PyQt4.QtGui import QGraphicsScene, QColor, QPixmap, QPainter, QIcon, \
  7. QTableWidgetItem, QToolButton, QColorDialog, QMessageBox, \
  8. QApplication, QGraphicsPolygonItem, QPen, QGraphicsView, QTableWidget, \
  9. QLineEdit, QTextEdit, QSlider, QDoubleSpinBox
  10. import Actions
  11. from Cache import Cache
  12. from Case import Case
  13. from EcranAffichageTexte import EcranAffichageTexte
  14. from EcranCreerPlateau import EcranCreerPlateau
  15. from EcranGestionCombat import EcranGestionCombat
  16. import Modes
  17. from Pinceau import Pinceau
  18. from ProjectionDep import ProjectionDep
  19. from Terrain import Terrain
  20. from lib.Actions import choisirAttaqueZone
  21. from lib.EcranEditionMateriel import EcranEditionMateriel
  22. from lib.ListePions import ListePions
  23. from lib.commun import lstLibEtats
  24. from lib.dmF import contractTxt
  25. from lib.gC import GestionCombat
  26. from lib.gM import GestionMateriel
  27. from lib.geometrie import Geometrie
  28. from lib.mat import Materiel, chargerMat
  29. import regles as regles
  30. class Plateau(QGraphicsScene, Materiel):
  31. """plateau de jeu contenant les cases, decors et pions"""
  32. def __init__(self, parent=None):
  33. super(Plateau, self).__init__()
  34. #parametres et variables
  35. self._type = "pl"
  36. ##partie et infos plateau
  37. self.chapitre = 0
  38. self.creePar = ""
  39. self.enCours = False
  40. self.public = False
  41. self.dateCreation = ""
  42. self.dateSvg = ""
  43. self.notes = ""
  44. self.presentation = ""
  45. #carac
  46. self.nbCasesX = 0
  47. self.nbCasesY = 0
  48. self.hCase = 0
  49. self.couleurInit = QColor(0, 255, 0, 80)
  50. self.zP = None #plafond
  51. self._compteurPile = 0 #compteur d'empilement, pour gerer l'ordre de recreation des pions
  52. #objets
  53. self.pinceau = Pinceau(self)
  54. self.gM = GestionMateriel()
  55. self.gC = GestionCombat()
  56. self.geo = Geometrie()
  57. self.cases = {} #dict des cases du plateau (coordonnées: case)
  58. self.pions = ListePions()
  59. self.caches = {}
  60. self.listeCasesZonePlacement = []
  61. self.polygoneZonePlacement = None
  62. self.entreesSorties = []
  63. #infos combat
  64. self.numCombattantEnCours = 0
  65. self.ordreJeu = {} #numero du pion: ordre de jeu
  66. def estCreateur(self):
  67. """retourne vrai si l'utilisateur en cours est le createur du plateau"""
  68. return (self.fenetre.util == self.creePar)
  69. def __getstate__(self):
  70. self.dateSvg = time()
  71. state = {key:value for key, value in self.__dict__.items() if not key in ["fenetre", "modeActif", \
  72. "editionTerrain", "editionCreature", "editionDecor", \
  73. "polygoneZonePlacement", "gestionCombat", \
  74. "editionAttaques", "pinceau"]}
  75. return (state)
  76. def __setstate__(self, state):
  77. self.__dict__ = state
  78. def vue(self):
  79. return self.fenetre.ui.cbt_vue
  80. def combattants(self):
  81. return self.pions.combattants()
  82. def combattantsVisibles(self):
  83. return self.pions.combattantsVisibles()
  84. def decors(self):
  85. return self.pions.combattants()
  86. def creer(self, fenetre):
  87. """cree le plateau"""
  88. self.fenetre = fenetre
  89. self.dateCreation = time()
  90. self.creePar = self.fenetre.profil.pseudo()
  91. self.hCase = 120 #hauteur d'une case
  92. self.modeActif = Modes.ModeBase(self)
  93. self.gestionCombat = None
  94. self.initialisationGraphique()
  95. self.connexions()
  96. #cree les cases hexagonales
  97. for x, y in self.geo.listeCases():
  98. c = Case(self)
  99. c.creer(x, y, self.couleurInit)
  100. self.cases[(x, y)] = c
  101. self.plateauModeCreation()
  102. def incrementerPile(self):
  103. self._compteurPile += 1
  104. return self._compteurPile
  105. def recreer(self, fenetre):
  106. self.fenetre = fenetre
  107. self.gestionCombat = None
  108. super(Plateau, self).__init__()
  109. self.modeActif = Modes.ModeBase(self)
  110. self.connexions()
  111. self.initialisationGraphique()
  112. #recreation des cases
  113. for coord in self.cases:
  114. self.cases[coord].recreer(self)
  115. #recreation des caches
  116. for idCache in self.caches:
  117. self.caches[idCache].ajouter(self)
  118. self.majCaches()
  119. #recreation des pions
  120. #on recree les pions par ordre d'empilement (du bas vers le haut)
  121. ordre = [pion for pion in self.pions.pions().values()]
  122. ordre.sort(key=lambda x: x.posPile)
  123. for pion in ordre:
  124. pion.ajouterAuPlateau(self)
  125. self.gC.reinitialiser()
  126. #recreation des marqueurs entree/sortie
  127. for entreeSortie in self.entreesSorties:
  128. entreeSortie.recreer(self)
  129. #recreation de la zone de placement:
  130. if len(self.listeCasesZonePlacement) > 0:
  131. self.polygoneZonePlacement = None
  132. self.majZonePlacement(self.listeCasesZonePlacement)
  133. if self.public:
  134. self.plateauModeCombat()
  135. else:
  136. self.plateauModeCreation()
  137. def fermer(self):
  138. """ferme le plateau 'proprement'"""
  139. self.miniature()
  140. self.pinceau = None
  141. for item in self.items():
  142. item.prepareGeometryChange()
  143. self.removeItem(item)
  144. if self.gestionCombat != None:
  145. del self.gestionCombat
  146. self.reinitialiserPanneaux()
  147. def reinitialiserPanneaux(self):
  148. """remet a neuf les commandes liees au plateau"""
  149. for panneau in [self.fenetre.ui.cbt_panneauHaut, \
  150. self.fenetre.ui.cbt_panneauBas, \
  151. self.fenetre.ui.cbt_panneauGauche, \
  152. self.fenetre.ui.cbt_panneauDroite]:
  153. #listes
  154. for liste in panneau.findChildren(QTableWidget):
  155. while liste.rowCount() > 0:
  156. liste.removeRow(0)
  157. #textes
  158. for texte in panneau.findChildren(QLineEdit):
  159. texte.clear()
  160. for texte in panneau.findChildren(QTextEdit):
  161. texte.clear()
  162. #a cocher
  163. for bouton in panneau.findChildren(QToolButton):
  164. if bouton.isCheckable():
  165. bouton.setChecked(False)
  166. #autre
  167. for item in panneau.findChildren(QSlider):
  168. item.setValue(1)
  169. for item in panneau.findChildren(QDoubleSpinBox):
  170. item.setValue(0)
  171. def miniature(self):
  172. """renvoie une miniature du plateau (QPixMap compresse) qui sera enregistree avec les infos de la sauvegarde"""
  173. ## img = QImage(128, 128, QImage.Format_ARGB32_Premultiplied)
  174. img = QPixmap(1024, 768)
  175. img.fill(QColor("white"))
  176. peintre = QPainter(img)
  177. self.render(peintre)
  178. peintre.end()
  179. img.scaledToHeight(128, Qt.FastTransformation)
  180. def connexions(self):
  181. """connecte le plateau aux differents widgets de la fenetre principale"""
  182. pass
  183. #modes d'interaction
  184. # self.fenetre.connect(self.fenetre.ui.cbt_modeCreation, SIGNAL("clicked()"), self.plateauModeCreation, Qt.UniqueConnection)
  185. # self.fenetre.connect(self.fenetre.ui.cbt_modeCombat, SIGNAL("clicked()"), self.plateauModeCombat, Qt.UniqueConnection)
  186. #
  187. # #etapes du combat
  188. # self.fenetre.connect(self.fenetre.ui.cbt_etapeSuivante, SIGNAL("clicked()"), self.etapeSuivante, Qt.UniqueConnection)
  189. # self.connect(self.fenetre.ui.pc_listePJ, SIGNAL("cellClicked(int, int)"), self.ajouterPj)
  190. #
  191. # #affichage de fenetres
  192. # self.fenetre.connect(self.fenetre.ui.cbt_nom, SIGNAL("clicked()"), self.afficherEcranPlateau, Qt.UniqueConnection)
  193. # self.fenetre.connect(self.fenetre.ui.cbt_afficherGestion, SIGNAL("clicked()"), self.afficheEcranGestionCombat, Qt.UniqueConnection)
  194. # self.fenetre.connect(self.fenetre.ui.pi_listeAttributs, SIGNAL("cellChanged(int,int)"), self.listeAttributCelluleModifiee, Qt.UniqueConnection)
  195. # self.fenetre.connect(self.fenetre.ui.cp_dialogueCouleurs, SIGNAL("clicked()"), self.modePeintureCase, Qt.UniqueConnection)
  196. # self.fenetre.connect(self.fenetre.ui.cp_afficherNotes, SIGNAL("clicked()"), self.agrandirNotesMjPlateau, Qt.UniqueConnection)
  197. # self.fenetre.connect(self.fenetre.ui.pi_fiche, SIGNAL("clicked()"), self.afficherFichePion, Qt.UniqueConnection)
  198. #
  199. # #listes
  200. # self.fenetre.connect(self.fenetre.ui.cp_listeTerrains, SIGNAL("cellClicked(int,int)"), self.modeMajTerrainCase, Qt.UniqueConnection)
  201. # self.fenetre.connect(self.fenetre.ui.cp_listeCreatures, SIGNAL("cellClicked(int,int)"), self.modeCreationCombattant, Qt.UniqueConnection)
  202. # self.fenetre.connect(self.fenetre.ui.cp_listeDecors, SIGNAL("cellClicked(int,int)"), self.modeCreationDecor, Qt.UniqueConnection)
  203. #
  204. # #creation
  205. # self.fenetre.connect(self.fenetre.ui.cp_epaisseurPinceau, SIGNAL("valueChanged(int)"), self.majEpaisseurPinceau, Qt.UniqueConnection)
  206. # self.fenetre.connect(self.fenetre.ui.cp_pipetteCouleur, SIGNAL("clicked()"), self.modeCopieTerrain, Qt.UniqueConnection)
  207. # self.fenetre.connect(self.fenetre.ui.cp_effets, SIGNAL("activated(int)"), self.modeCaseEffet, Qt.UniqueConnection)
  208. #
  209. # #autres:
  210. # self.fenetre.connect(self.fenetre.ui.cp_gomme, SIGNAL("clicked()"), self.majModeSupprimerPions, Qt.UniqueConnection)
  211. # self.fenetre.connect(self.fenetre.ui.cp_placerEntree, SIGNAL("clicked()"), self.majModeDefinirEntree, Qt.UniqueConnection)
  212. # self.fenetre.connect(self.fenetre.ui.cp_placerCache, SIGNAL("clicked()"), self.majModePlacerCache, Qt.UniqueConnection)
  213. # self.fenetre.connect(self.fenetre.ui.cp_placerSortie, SIGNAL("clicked()"), self.majModeDefinirSortie, Qt.UniqueConnection)
  214. # self.fenetre.connect(self.fenetre.ui.cp_defPlacement, SIGNAL("clicked()"), self.majModeZonePlacement, Qt.UniqueConnection)
  215. # self.fenetre.connect(self.fenetre.ui.pi_notes, SIGNAL("textChanged()"), self.majNotesCombattant, Qt.UniqueConnection)
  216. #
  217. # #formes (dessin)
  218. # self.fenetre.connect(self.fenetre.ui.cp_formeSimple, SIGNAL("clicked()"), self.majModeForme, Qt.UniqueConnection)
  219. # self.fenetre.connect(self.fenetre.ui.cp_formeLigne, SIGNAL("clicked()"), self.majModeForme, Qt.UniqueConnection)
  220. # self.fenetre.connect(self.fenetre.ui.cp_formeLigneOrientee, SIGNAL("clicked()"), self.majModeForme, Qt.UniqueConnection)
  221. # self.fenetre.connect(self.fenetre.ui.cp_formePot, SIGNAL("clicked()"), self.majModeForme, Qt.UniqueConnection)
  222. # self.fenetre.connect(self.fenetre.ui.cp_formeRectVide, SIGNAL("clicked()"), self.majModeForme, Qt.UniqueConnection)
  223. # self.fenetre.connect(self.fenetre.ui.cp_formeRectPlein, SIGNAL("clicked()"), self.majModeForme, Qt.UniqueConnection)
  224. #
  225. # self.fenetre.connect(self.fenetre.ui.act_deplacement, SIGNAL("clicked()"), self.majModeCombatDeplacement, Qt.UniqueConnection)
  226. # self.fenetre.connect(self.fenetre.ui.act_attaqueCac, SIGNAL("clicked()"), self.majModeCombatAttaqueCaC, Qt.UniqueConnection)
  227. # self.fenetre.connect(self.fenetre.ui.act_attaqueDist, SIGNAL("clicked()"), self.majModeCombatAttaqueDist, Qt.UniqueConnection)
  228. # self.fenetre.connect(self.fenetre.ui.act_attaqueZone, SIGNAL("clicked()"), self.majModeCombatZone, Qt.UniqueConnection)
  229. # self.fenetre.connect(self.fenetre.ui.pi_formeAttaqueZone, SIGNAL("activated (int)"), self.majModeCombatZone, Qt.UniqueConnection)
  230. # self.fenetre.connect(self.fenetre.ui.pi_rayonAttaqueZone, SIGNAL("valueChanged(int)"), self.majRayonZone, Qt.UniqueConnection)
  231. def initialisationGraphique(self):
  232. """cree la scene graphique et les parametres necessaires a son fonctionnement, et met a jour l'interface"""
  233. #on cree la scene graphique
  234. kx = 1
  235. if self.formeCases == "H":
  236. kx = 0.866
  237. marge = 240
  238. self.setSceneRect(0 - marge, 0 - marge, (kx*self.hCase*(self.nbCasesX+2)) + marge, (self.hCase*(self.nbCasesY+2)) + marge)
  239. self.vue().setScene(self)
  240. self.vue().scale(0.25, 0.25)
  241. self.vue().centerOn(QPointF(0,0))
  242. self.vue().setDragMode(1)
  243. self.setItemIndexMethod(QGraphicsScene.BspTreeIndex)
  244. self.polygoneZonePlacement = None
  245. #gestion du mode d'interaction avec le plateau
  246. self.pions.initialiser(self)
  247. self.pinceau = Pinceau(self)
  248. self.proj = ProjectionDep(self)
  249. #mise a jour de l'interface de creation
  250. self.majNomPlateau()
  251. self.majBoutonsCouleursPerso()
  252. self.gM.initialiser(self.fenetre)
  253. self.gC.initialiser(self)
  254. self.geo.initialiser(self)
  255. self.initListeAttaques()
  256. self.majBoutonEtape()
  257. # self.fenetre.ui.act_deplacement.setCheckable(True)
  258. # self.fenetre.ui.act_attaqueCac.setCheckable(True)
  259. # self.fenetre.ui.act_attaqueDist.setCheckable(True)
  260. # self.fenetre.ui.act_attaqueZone.setCheckable(True)
  261. #mise a jour de l'interface d'informations
  262. self.majInfoCb(None)
  263. self.majInfoDc(None)
  264. def estCree(self):
  265. """renvoie vrai si des cases ont ete creees"""
  266. return (len(self.cases) > 0)
  267. def afficherEcranPlateau(self):
  268. """affiche la fenetre de description du plateau"""
  269. ecran = EcranCreerPlateau()
  270. ecran.afficher(self)
  271. r = ecran.exec_()
  272. if r == 1:
  273. res = ecran.resultat()
  274. self.majNom(res.nom())
  275. self.chapitre = res.chapitre
  276. self.description = res.description
  277. self.presentation = res.presentation
  278. self.majNomPlateau()
  279. def majNomPlateau(self):
  280. """met a jour l'affichage du nom du plateau"""
  281. txt = self.nom()
  282. if not self.public: txt += " [Non Publié]"
  283. self.fenetre.ui.cbt_nom.setText(QString().fromUtf8(" {} ".format(txt)))
  284. def majBoutonEtape(self):
  285. """met a jour le label et l'effet du bouton d'etape (en bas a droite)"""
  286. if not self.public:
  287. self.fenetre.ui.cbt_etapeSuivante.setText(QString().fromUtf8("Publier le plateau"))
  288. return
  289. if not self.gC.tour() > 0:
  290. self.fenetre.ui.cbt_etapeSuivante.setText(QString().fromUtf8("Démarrer le combat"))
  291. return
  292. self.fenetre.ui.cbt_etapeSuivante.setText(QString().fromUtf8("Tour {}\nFinir son tour".format(self.gC.tour())))
  293. def etapeSuivante(self):
  294. """apres clic sur le bouton d'etape, on passe a l'etape suivante (publication, demarrage du combat...)"""
  295. if not self.public:
  296. self.publier()
  297. return
  298. self.gC.pionSuivant()
  299. def publier(self):
  300. self.public = True
  301. self.majListePJ()
  302. self.majBoutonEtape()
  303. def majListePJ(self):
  304. """met a jour la liste des pj qui peuvent etre ajoutes au plateau"""
  305. self.fenetre.ui.pc_listePJ.setColumnWidth(0,0)
  306. self.fenetre.ui.pc_listePJ.vider()
  307. dejaCrees = []
  308. for numPj in self.pions.pjs():
  309. dejaCrees.append(self.pions[numPj].idM())
  310. for idM in self.fenetre.pjs:
  311. if not idM in dejaCrees:
  312. pj = chargerMat(idM, "grp")
  313. ligne = self.fenetre.ui.pc_listePJ.nouvelleLigneFin()
  314. self.fenetre.ui.pc_listePJ.majTexte(ligne, 0, idM)
  315. self.fenetre.ui.pc_listePJ.setItem(ligne, 1, QTableWidgetItem(QIcon(pj.icone().pix()), \
  316. QString(pj.nom())))
  317. self.fenetre.ui.pc_listePJ.setVisible((self.fenetre.ui.pc_listePJ.rowCount() > 0))
  318. def ajouterPj(self, ligne, col):
  319. idM = self.fenetre.ui.pc_listePJ.texte(ligne, 0)
  320. pj = chargerMat(idM, "grp")
  321. if pj: self.activerMode(Modes.CreationPion, pj)
  322. def couleursRapides(self):
  323. return [(255,255,255), (200,200,200), (130,130,130), (90,90,90), (15,15,15), \
  324. (0,85,0), (170,255,0), (170,255,127), (85,85,0), (85,0,0), (170,85,0), (100,50,0), \
  325. (255,255,127), (240,80,0), (85,170,255), (85,85,255), (85,0,255), (0,255,255)]
  326. def majBoutonsCouleursPerso(self):
  327. """met a jour l'affichage des couleurs customisees dans la boite de dialogue de selection de couleur"""
  328. for i in range(0,18):
  329. couleur = QColor()
  330. r, g, b = self.couleursRapides()[i]
  331. couleur.setRgb(r, g, b)
  332. bouton = self.fenetre.ui.cp_boiteCouleurs.findChild(QToolButton, "cp_couleur{}".format(i+1))
  333. if couleur.isValid():
  334. bouton.setStyleSheet("QToolButton {backGround:%s}"%(couleur.name()))
  335. self.fenetre.connect(bouton, SIGNAL("clicked()"), self.modePeintureCase_perso)
  336. def chercherCouleur(self):
  337. """ouvre la boite de dialogue de selection de couleur"""
  338. couleur = QColorDialog(self.vue()).getColor(QColor("white"), self.vue())
  339. return couleur
  340. def majListesPions(self, numCombattant = None):
  341. """met a jour les listes contenant des donnees liees aux pions"""
  342. ## self.majListeOrdreJeu()
  343. ##
  344. ## if numCombattant == None or numCombattant == self.pionSelectionne().numero:
  345. ## self.majListeAttributs()
  346. ## QApplication.processEvents()
  347. pass
  348. # def ajouterPj(self):
  349. # """affiche la fenetre de selection des pj, et recupere l'eventuel pj selectionne"""
  350. # self.ecranSelPj = EcranSelectionPj(self.fenetre)
  351. # self.ecranSelPj.setAttribute(Qt.WA_DeleteOnClose)
  352. # listePj = chargerUnique("parties\\{}\\groupe".format(self.fenetre.partie))
  353. # self.ecranSelPj.charger(listePj)
  354. # r = self.ecranSelPj.exec_()
  355. # if r == 1:
  356. # idPj = int(self.ecranSelPj.selection())
  357. # if idPj != None:
  358. # pj = listePj[idPj]
  359. # self.activerMode(Modes.CreationPion, pj)
  360. # self.ecranSelPj = None
  361. def agrandirNotesMjPlateau(self):
  362. """affiche les notes du plateau dans une QDialog, puis recupere les donnees qui y sont saisies"""
  363. affichageTexte = EcranAffichageTexte(self.notes)
  364. affichageTexte.exec_()
  365. self.notes = affichageTexte.recupererTexte()
  366. del affichageTexte
  367. ############### affichage des caches enregistres
  368. def majCaches(self):
  369. """charge la liste des caches avec les donnees en memoire"""
  370. traite = []
  371. for idCache in self.caches:
  372. for coord in self.caches[idCache].listeCases():
  373. if not coord in traite:
  374. self.cases[coord].majCache()
  375. traite.append(coord)
  376. #### affichage de la fiche du perso ou du decor
  377. def afficherFichePion(self):
  378. if self.pionSelectionne():
  379. fen = EcranEditionMateriel(self.pionSelectionne())
  380. fen.afficher()
  381. fen.exec_()
  382. ############### maj des infos du panneau Pi a la selection/deselection d'un pion
  383. #voir a balancer tout ca dans une classe a part
  384. def majPanneauPi(self):
  385. return
  386. if self.pionSelectionne():
  387. estCombattant = (self.pionSelectionne().numero > 0)
  388. #affichage
  389. # self.fenetre.ui.pi_actions.setEnabled(estCombattant)
  390. self.fenetre.ui.pi_ongletsListes.setTabEnabled(0, estCombattant)
  391. self.fenetre.ui.pi_ongletsListes.setTabEnabled(1, estCombattant)
  392. ### maj la selection dans la liste d'ordre de jeu
  393. if estCombattant:
  394. for i in range(0, self.fenetre.ui.inf_listeOrdreJeu.rowCount()):
  395. if str(self.fenetre.ui.inf_listeOrdreJeu.item(i, 0).text().toUtf8()) == str(self.pionSelectionne().numero):
  396. self.fenetre.ui.inf_listeOrdreJeu.setCurrentCell(i,0)
  397. ### maj de la liste des attributs
  398. if estCombattant:
  399. self.fenetre.ui.pi_listeAttributs.setColumnWidth(0, 50)
  400. self.disconnect(self.fenetre.ui.pi_listeAttributs, SIGNAL("cellChanged(int,int)"), self.listeAttributCelluleModifiee)
  401. #on vide la liste
  402. while self.fenetre.ui.pi_listeAttributs.rowCount() > 0:
  403. self.fenetre.ui.pi_listeAttributs.removeRow(0)
  404. #creation des lignes de base
  405. lignesBase = ["Nom","Etat","Alt."] #attention: modifier aussi dans listeAttributCelluleModifiee
  406. for i in range(0, 10): #10 premieres colonnes reservees pour les infos de base
  407. self.fenetre.ui.pi_listeAttributs.insertRow(i)
  408. item = QTableWidgetItem()
  409. if i < len(lignesBase):
  410. item.setText(QString.fromUtf8(lignesBase[i]))
  411. item.setFlags(Qt.NoItemFlags)
  412. self.fenetre.ui.pi_listeAttributs.setItem(i, 0, item)
  413. self.fenetre.ui.pi_listeAttributs.setRowHidden(i, (i >= len(lignesBase)))
  414. #maj des donnees de base
  415. self.fenetre.ui.pi_listeAttributs.setItem(lignesBase.index("Nom"), 1, QTableWidgetItem(QString.fromUtf8(str(self.pionSelectionne().nom()))))
  416. self.fenetre.ui.pi_listeAttributs.setItem(lignesBase.index("Etat"), 1, QTableWidgetItem(QString.fromUtf8(str(self.pionSelectionne().etat))))
  417. self.fenetre.ui.pi_listeAttributs.setItem(lignesBase.index("Alt."), 1, QTableWidgetItem(QString.fromUtf8(str(self.pionSelectionne().zR))))
  418. #attributs issus des regles utilisees
  419. ordre = regles.ordreAttributs()
  420. for elt in ordre:
  421. ligne = 10 + ordre.index(elt)
  422. self.fenetre.ui.pi_listeAttributs.insertRow(ligne)
  423. item = QTableWidgetItem(QString.fromUtf8(elt))
  424. item.setFlags(Qt.NoItemFlags)
  425. self.fenetre.ui.pi_listeAttributs.setItem(ligne, 0, item)
  426. self.fenetre.ui.pi_listeAttributs.setItem(ligne, 1, QTableWidgetItem(QString.fromUtf8(str(self.pionSelectionne().listeAttributs[elt]))))
  427. self.connect(self.fenetre.ui.pi_listeAttributs, SIGNAL("cellChanged(int,int)"), self.listeAttributCelluleModifiee)
  428. ###affiche les notes du combattant
  429. self.fenetre.ui.pi_notes.majTexte(self.pionSelectionne().notes)
  430. ###maj la liste des attaques du pion
  431. if estCombattant:
  432. #on vide la liste
  433. while self.fenetre.ui.pi_listeAttaques.rowCount() > 0:
  434. self.fenetre.ui.pi_listeAttaques.removeRow(0)
  435. i = 0
  436. for attaque in self.pionSelectionne().attaques:
  437. self.fenetre.ui.pi_listeAttaques.insertRow(i)
  438. self.fenetre.ui.pi_listeAttaques.setItem(i, 0, QTableWidgetItem(QString.fromUtf8(str(self.pionSelectionne().attaques.index(attaque)))))
  439. icone = None
  440. if attaque.typ == "cac":
  441. icone = QIcon(":/interface/16/ressource/epee_16.png")
  442. if attaque.typ == "dist":
  443. icone = QIcon(":/interface/16/ressource/arc_16.png")
  444. if attaque.typ == "zone":
  445. icone = QIcon(":/interface/16/ressource/baguette_16.png")
  446. if icone != None:
  447. self.fenetre.ui.pi_listeAttaques.setItem(i, 1, QTableWidgetItem(icone, QString.fromUtf8("")))
  448. self.fenetre.ui.pi_listeAttaques.setItem(i, 2, QTableWidgetItem(QString.fromUtf8(attaque.nom)))
  449. else:
  450. #maj des infos dans le panneau pi
  451. #vide la liste des attributs
  452. self.disconnect(self.fenetre.ui.pi_listeAttributs, SIGNAL("cellChanged(int,int)"), self.listeAttributCelluleModifiee)
  453. while self.fenetre.ui.pi_listeAttributs.rowCount() > 0:
  454. self.fenetre.ui.pi_listeAttributs.removeRow(0)
  455. #vide la liste des attaques du pion
  456. while self.fenetre.ui.pi_listeAttaques.rowCount() > 0:
  457. self.fenetre.ui.pi_listeAttaques.removeRow(0)
  458. self.majInfosAttaqueEC()
  459. ##### activation des differents modes d'interaction avec le plateau et mises a jour des principaux parametres #######
  460. def majArborescenceModes(self):
  461. self.fenetre.ui.cbt_arbo.majTexte(self.modeActif.arborescence())
  462. def plateauModeCreation(self):
  463. self.activerMode(Modes.StandardCp)
  464. def plateauModeCombat(self):
  465. self.activerMode(Modes.StandardPi)
  466. def activerMode(self, mode, param = None):
  467. """desactive le mode actif et active le nouveau a la place"""
  468. self.modeActif.desactiver()
  469. self.modeActif = mode(self)
  470. self.modeActif.activer(param)
  471. self.majArborescenceModes()
  472. def modePeintureCase(self):
  473. """enclenche le mode peinture de case a partir de la couleur selectionnee"""
  474. couleur = self.chercherCouleur()
  475. if couleur.isValid():
  476. terrain = Terrain()
  477. terrain.couleur = couleur
  478. self.activerMode(Modes.MajCases, terrain)
  479. else:
  480. self.activerMode(Modes.StandardCp)
  481. def modePeintureCase_perso(self):
  482. origine = self.sender().objectName()
  483. index = int(origine.replace("cp_couleur",""))-1
  484. couleur = QColor()
  485. r, g, b = self.couleursRapides()[index]
  486. couleur.setRgb(r, g, b)
  487. if couleur.isValid():
  488. terrain = Terrain()
  489. terrain.couleur = couleur
  490. self.activerMode(Modes.MajCases, terrain)
  491. else:
  492. self.activerMode(Modes.StandardCp)
  493. def modeCopieTerrain(self):
  494. """enclenche le mode copie de case"""
  495. self.activerMode(Modes.Pipette)
  496. def modeCaseEffet(self, index):
  497. """enclenche le mode de mise a jour de l'effet actif des cases"""
  498. effets = ["brule", "eau", "glace", "poison", "aucun"]
  499. self.activerMode(Modes.MajCasesEffet, effets[index])
  500. def majModeSupprimerPions(self):
  501. """enclenche le mode suppression de pions sur clic gauche (creatures ou decors)"""
  502. self.activerMode(Modes.SuppressionPion)
  503. def modeCreationDecor(self, ligne, col):
  504. """enclenche le mode de creation de decors depuis la liste des decors"""
  505. decor = chargerMat(self.fenetre.ui.cp_listeDecors.selection())
  506. self.activerMode(Modes.CreationPion, decor)
  507. def modeCreationCombattant(self, ligne, col):
  508. """enclenche le mode de creation de pions depuis la liste des creatures"""
  509. creature = chargerMat(self.fenetre.ui.cp_listeCreatures.selection())
  510. self.activerMode(Modes.CreationPion, creature)
  511. def modeMajTerrainCase(self, ligne, col):
  512. """enclenche le mode permettant la mise a jour du terrain des cases"""
  513. terrain = chargerMat(self.fenetre.ui.cp_listeTerrains.selection())
  514. if terrain:
  515. self.activerMode(Modes.MajCases, terrain)
  516. else:
  517. print "terrain invalide"
  518. def majEpaisseurPinceau(self, epaisseur):
  519. """met a jour l'epaisseur du pinceau (en cases)"""
  520. self.fenetre.ui.cp_valeurEpaisseurPinceau.majTexte(str(epaisseur))
  521. self.pinceau.majEpaisseur(int(epaisseur))
  522. def majModeForme(self):
  523. """met a jour la forme utilisee pour la peinture"""
  524. formes = {"cp_formeSimple": "simple", \
  525. "cp_formeLigne": "ligne", \
  526. "cp_formeLigneOrientee": "frontiere", \
  527. "cp_formePot": "pot", \
  528. "cp_formeEllipseVide": "ellipseV", \
  529. "cp_formeEllipsePlein": "ellipseP", \
  530. "cp_formeRectVide": "rectV", \
  531. "cp_formeRectPlein": "rectP"}
  532. self.pinceau.majForme(formes[str(self.sender().objectName())])
  533. def majModePlacerCache(self):
  534. """active le mode de creation des caches"""
  535. if self.public:
  536. dial = QMessageBox()
  537. dial.setText(QString().fromUtf8("Vous ne pouvez pas placer de caches une fois le plateau publié"))
  538. dial.exec_()
  539. return
  540. self.activerMode(Modes.PlacerCaches)
  541. def majModeCombatDeplacement(self):
  542. """active le mode de combat 'deplacement' (mode standard)"""
  543. self.modeActif.nouvelleAction(Actions.Deplacement)
  544. def majModeCombatAttaqueCaC(self):
  545. """active le mode de combat 'corps-a-corps'"""
  546. self.modeActif.nouvelleAction(Actions.Cac)
  547. def majModeCombatAttaqueDist(self):
  548. """active le mode de combat 'attaque a distance'"""
  549. self.modeActif.nouvelleAction(Actions.Distance)
  550. def majModeCombatZone(self):
  551. action = choisirAttaqueZone()
  552. self.modeActif.nouvelleAction(action)
  553. def majModeDefinirEntree(self):
  554. self.activerMode(Modes.CreationEntreeSortie, "E")
  555. def majModeDefinirSortie(self):
  556. self.activerMode(Modes.CreationEntreeSortie, "S")
  557. def majModeZonePlacement(self):
  558. self.activerMode(Modes.ZonePlacement)
  559. ###############
  560. ########## Gestion du combat ##############
  561. def afficheEcranGestionCombat(self):
  562. """affiche l'ecran de gestion du combat"""
  563. self.gestionCombat = EcranGestionCombat(self)
  564. self.gestionCombat.show()
  565. self.connect(self.fenetre, SIGNAL("majListesPions"), self.majListesPions)
  566. self.connect(self.gestionCombat, SIGNAL("majListesPions"), self.majListesPions)
  567. QApplication.processEvents()
  568. ## r = self.gestionCombat.exec_()
  569. # def majAffichageTour(self):
  570. # """met a jour l'affichage du tour en cours"""
  571. # self.fenetre.ui.cbt_tour.majTexte("Tour: {}".format(self.tour))
  572. #
  573. # def initListeOrdreJeu(self):
  574. # """cree les colonnes et met en forme la table ordre jeu"""
  575. # self.fenetre.ui.inf_listeOrdreJeu.setColumnWidth(2, 30)
  576. # self.fenetre.ui.inf_listeOrdreJeu.hideColumn(0)
  577. # self.fenetre.ui.inf_listeOrdreJeu.hideColumn(2)
  578. # self.fenetre.ui.inf_listeOrdreJeu.setIconSize(QSize(30,20))
  579. #
  580. # def majListeOrdreJeu(self):
  581. # """met a jour la liste des pions infoOrdreJeu"""
  582. # while self.fenetre.ui.inf_listeOrdreJeu.rowCount() > 0:
  583. # self.fenetre.ui.inf_listeOrdreJeu.removeRow(0)
  584. # index = 0
  585. # for num in self.ordreJeu:
  586. # self.fenetre.ui.inf_listeOrdreJeu.insertRow(int(index))
  587. # self.fenetre.ui.inf_listeOrdreJeu.setItem(int(index), 0, QTableWidgetItem(QString.fromUtf8(str(num))))
  588. # icon = QIcon(self.combattants[num].icone().fichier())
  589. # item = QTableWidgetItem(icon, QString.fromUtf8(self.combattants[num].txtId()))
  590. # self.fenetre.ui.inf_listeOrdreJeu.setItem(int(index), 1, item)
  591. # self.fenetre.ui.inf_listeOrdreJeu.setItem(int(index), 2, QTableWidgetItem(QString.fromUtf8(str(self.ordreJeu[num]))))
  592. # index += 1
  593. #
  594. # self.fenetre.ui.inf_listeOrdreJeu.sizeHintForColumn(1)
  595. # ## trierTable(self.fenetre.ui.infoOrdreJeu, 2, 0)
  596. #
  597. # def clicListOrdreJeu(self, ligne, col):
  598. # """on a clique dans la liste d'ordre de jeu, le pion correspondant est selectionne et centre sur la carte"""
  599. # numCombattant = int(self.fenetre.ui.inf_listeOrdreJeu.item(ligne, 0).text().toUtf8())
  600. # self.vue().centerOn(self.cases[self.combattants[numCombattant].position].centreGraphique)
  601. # self.modeActif.clic_combattant(numCombattant)
  602. #
  603. # def pionSuivant(self):
  604. # """selection du pion suivant dans la liste d'ordre de jeu"""
  605. # if not len(self.combattants) > 0: return
  606. #
  607. # if self.numPionEnCours in self.combattants:
  608. # suivant = self.ordreJeu[self.numPionEnCours] + 1
  609. # else:
  610. # suivant = 1
  611. # if suivant > len(self.ordreJeu):
  612. # self.tour += 1
  613. # self.majAffichageTour()
  614. # suivant = 1
  615. # for num in self.ordreJeu:
  616. # if self.ordreJeu[num] == suivant:
  617. # numCombattant = num
  618. # break
  619. #
  620. # for ligne in range(0, self.fenetre.ui.inf_listeOrdreJeu.rowCount()):
  621. # item = self.fenetre.ui.inf_listeOrdreJeu.item(ligne, 0)
  622. # item.setSelected(int(self.fenetre.ui.inf_listeOrdreJeu.item(ligne, 0).text().toUtf8()) == numCombattant)
  623. # if int(item.text().toUtf8()) == numCombattant:
  624. # self.fenetre.ui.inf_listeOrdreJeu.scrollToItem(item)
  625. #
  626. # self.vue().centerOn(self.cases[self.combattants[numCombattant].position].centreGraphique)
  627. # self.pionSaisir(numCombattant)
  628. #
  629. #
  630. # def majOrdreJeu(self):
  631. # """met a jour l'ordre de jeu des pions en fonction de l'attribut prevu par les regles s'il existe,
  632. # ou en fonction de l'ordre de jeu parametre sinon"""
  633. # if len(self.ordreJeu) > 0:
  634. # attribut = regles.attributOrdreJeu()
  635. # if attribut != None:
  636. # dico = {}
  637. # for numCombattant in self.combattants:
  638. # dico[numCombattant] = int(self.combattants[numCombattant].listeAttributs[attribut])
  639. # ordre = sorted(dico, key = dico.get, reverse=(regles.sensTriOrdreJeu() == 1))
  640. # self.ordreJeu = {}
  641. # for numCombattant in self.combattants:
  642. # self.ordreJeu[numCombattant] = ordre.index(numCombattant) + 1
  643. # self.majListeOrdreJeu()
  644. #
  645. # def pionDeplacerDansOrdreJeu(self, numCombattant, nouvellePosition):
  646. # """deplace un pion dans le dictionnaire gerant l'ordre de jeu de maniere a assurer sa coherence
  647. # nouvellePosition = 0 supprime le pion de la liste"""
  648. # if numCombattant in self.ordreJeu:
  649. # if nouvellePosition == 0:
  650. # del self.ordreJeu[numCombattant]
  651. # if len(self.ordreJeu) > 0:
  652. # i = 0
  653. # tmp = sorted(self.ordreJeu, key=self.ordreJeu.get)
  654. # if numCombattant in tmp:
  655. # tmp.remove(numCombattant)
  656. # for num in tmp:
  657. # i += 1
  658. # if i == nouvellePosition:
  659. # self.ordreJeu[numCombattant] = i
  660. # i += 1
  661. # self.ordreJeu[num] = i
  662. # if i < nouvellePosition:
  663. # self.ordreJeu[numCombattant] = i + 1
  664. # elif nouvellePosition > 0:
  665. # self.ordreJeu[numCombattant] = 1
  666. # self.majOrdreJeu()
  667. def listeAttributCelluleModifiee(self, ligne, colonne):
  668. """une cellule de la liste des attributs a ete modifiee"""
  669. return
  670. if colonne != 1:
  671. print("valeur non modifiable")
  672. else:
  673. #on verifie la validite de la donnee entree
  674. lignesBase = ["Nom","Etat","Alt."] #attention: modifier aussi dans majListeAttribut
  675. if ligne < len(lignesBase):
  676. pass
  677. elif ligne >= 10:
  678. attribut = regles.ordreAttributs()[(ligne - 10)]
  679. nouvelleVal = str(self.fenetre.ui.pi_listeAttributs.item(ligne, 1).text().toUtf8())
  680. valVerifiee = regles.listeControle()[attribut].controler(nouvelleVal)
  681. if valVerifiee != None:
  682. self.pionSelectionne().listeAttributs[attribut] = valVerifiee
  683. if attribut == regles.attributOrdreJeu():
  684. print("maj ordre (a implementer)")
  685. else:
  686. self.fenetre.ui.pi_listeAttributs.setItem(ligne, 1, QTableWidgetItem(QString.fromUtf8(str(self.pionSelectionne().listeAttributs[attribut]))))
  687. def initListeAttaques(self):
  688. """met en forme et connecte la liste des attaques du pion"""
  689. self.fenetre.ui.pi_listeAttaques.setColumnWidth(0, 0)
  690. self.fenetre.ui.pi_listeAttaques.setColumnWidth(1, (0.3*self.fenetre.ui.pi_listeAttaques.width()))
  691. self.fenetre.ui.pi_listeAttaques.setColumnWidth(2, (0.7*self.fenetre.ui.pi_listeAttaques.width()))
  692. self.connect(self.fenetre.ui.pi_listeAttaques, SIGNAL("itemSelectionChanged()"), self.majInfosAttaqueEC)
  693. self.connect(self.fenetre.ui.pi_listeAttaques, SIGNAL("cellClicked(int, int)"), self.listeAttaquesCelluleCliquee)
  694. self.connect(self.fenetre.ui.pi_notesAttaqueEC, SIGNAL("textChanged()"), self.majNotesAttaqueEC)
  695. self.fenetre.ui.pi_listeAttributsAttaqueEC.setColumnWidth(0, (0.49*self.fenetre.ui.pi_listeAttributsAttaqueEC.width()))
  696. self.fenetre.ui.pi_listeAttributsAttaqueEC.setColumnWidth(1, (0.5*self.fenetre.ui.pi_listeAttributsAttaqueEC.width()))
  697. def majListeAttaques(self):
  698. """met a jour la liste des attaques du pion dans le panneau de combat"""
  699. #on vide la liste
  700. while self.fenetre.ui.pi_listeAttaques.rowCount() > 0:
  701. self.fenetre.ui.pi_listeAttaques.removeRow(0)
  702. self.fenetre.ui.pi_listeAttaques.setVisible((self.pionSelectionne() != None))
  703. ## self.fenetre.ui.editerAttaques.setVisible((self.pionSelectionne() != None))
  704. self.fenetre.ui.pi_panneauAttaqueEC.setVisible((self.pionSelectionne() != None))
  705. i = 0
  706. if self.pionSelectionne() != None:
  707. for attaque in self.pionSelectionne().attaques:
  708. self.fenetre.ui.pi_listeAttaques.insertRow(i)
  709. self.fenetre.ui.pi_listeAttaques.setItem(i, 0, QTableWidgetItem(QString.fromUtf8(str(self.pionSelectionne().attaques.index(attaque)))))
  710. icone = None
  711. if attaque.typ == "cac":
  712. icone = QIcon(":/interface/16/ressource/epee_16.png")
  713. if attaque.typ == "dist":
  714. icone = QIcon(":/interface/16/ressource/arc_16.png")
  715. if attaque.typ == "zone":
  716. icone = QIcon(":/interface/16/ressource/baguette_16.png")
  717. if icone != None:
  718. self.fenetre.ui.pi_listeAttaques.setItem(i, 1, QTableWidgetItem(icone, QString.fromUtf8("")))
  719. self.fenetre.ui.pi_listeAttaques.setItem(i, 2, QTableWidgetItem(QString.fromUtf8(attaque.nom)))
  720. self.majInfosAttaqueEC()
  721. def listeAttaquesCelluleCliquee(self, ligne, colonne):
  722. """on a clique sur une cellule de la liste des attaques"""
  723. numAttaque = int(str(self.fenetre.ui.pi_listeAttaques.item(ligne, 0).text().toUtf8()))
  724. if numAttaque >= 0:
  725. self.utiliserAttaque(numAttaque)
  726. def utiliserAttaque(self, numAttaque):
  727. """le pion selectionne utilise son attaque n"""
  728. if self.pionSelectionne() != None:
  729. if numAttaque < len(self.pionSelectionne().attaques):
  730. attaque = self.pionSelectionne().attaques[numAttaque]
  731. if attaque.typ == "cac":
  732. self.majModeCombat("combatAttaqueCaC")
  733. if attaque.typ == "dist":
  734. self.majModeCombat("combatAttaqueDist")
  735. if attaque.typ == "zone":
  736. self.modeParam["typeAttaqueZone"] = attaque.formeZone
  737. self.majModeCombat("combatAttaqueZone")
  738. def majInfosAttaqueEC(self):
  739. """met a jour les infos de l'attaque en cours (selectionnee)"""
  740. selection = self.fenetre.ui.pi_listeAttaques.selectedItems()
  741. self.fenetre.ui.pi_panneauAttaqueEC.setVisible(self.pionSelectionne() != None and len(selection) > 0)
  742. if self.pionSelectionne() != None and len(selection) > 0:
  743. ligne = selection[0].row()
  744. numAttaque = int(str(self.fenetre.ui.pi_listeAttaques.item(ligne, 0).text().toUtf8()))
  745. self.disconnect(self.fenetre.ui.pi_panneauAttaqueEC, SIGNAL("cellChanged(int,int)"), self.attaqueECCelluleModifiee)
  746. #on vide la liste
  747. while self.fenetre.ui.pi_listeAttributsAttaqueEC.rowCount() > 0:
  748. self.fenetre.ui.pi_listeAttributsAttaqueEC.removeRow(0)
  749. self.fenetre.ui.pi_listeAttributsAttaqueEC.insertRow(0)
  750. self.fenetre.ui.pi_listeAttributsAttaqueEC.setItem(0, 0, QTableWidgetItem(QString.fromUtf8("numAtt")))
  751. self.fenetre.ui.pi_listeAttributsAttaqueEC.setItem(0, 1, QTableWidgetItem(QString.fromUtf8(str(numAttaque))))
  752. self.fenetre.ui.pi_listeAttributsAttaqueEC.setRowHidden(0, True)
  753. #attributs issus des regles utilisees
  754. ordre = regles.ordreAttributsAttaques()
  755. for elt in ordre:
  756. ligne = 1 + ordre.index(elt)
  757. self.fenetre.ui.pi_listeAttributsAttaqueEC.insertRow(ligne)
  758. item = QTableWidgetItem(QString.fromUtf8(elt))
  759. item.setFlags(Qt.NoItemFlags)
  760. self.fenetre.ui.pi_listeAttributsAttaqueEC.setItem(ligne, 0, item)
  761. self.fenetre.ui.pi_listeAttributsAttaqueEC.setItem(ligne, 1, QTableWidgetItem(QString.fromUtf8(str(self.pionSelectionne().attaques[numAttaque].attributs[elt]))))
  762. self.connect(self.fenetre.ui.pi_listeAttributsAttaqueEC, SIGNAL("cellChanged(int,int)"), self.attaqueECCelluleModifiee)
  763. #maj des notes
  764. self.disconnect(self.fenetre.ui.pi_notesAttaqueEC, SIGNAL("textChanged()"), self.majNotesAttaqueEC)
  765. self.fenetre.ui.pi_notesAttaqueEC.majTexte(self.pionSelectionne().attaques[numAttaque].notes)
  766. self.connect(self.fenetre.ui.pi_notesAttaqueEC, SIGNAL("textChanged()"), self.majNotesAttaqueEC)
  767. def attaqueECCelluleModifiee(self, ligne, colonne):
  768. """une cellule de la liste d'attributs de l'attaque en cours a ete modifiee"""
  769. pass
  770. def majNotesAttaqueEC(self):
  771. """met a jour les notes de l'attaque en cours (selectionnee)"""
  772. selection = self.fenetre.ui.pi_listeAttaques.selectedItems()
  773. self.fenetre.ui.pi_panneauAttaqueEC.setVisible(self.pionSelectionne() != None and len(selection) > 0)
  774. if self.pionSelectionne() != None and len(selection) > 0:
  775. ligne = selection[0].row()
  776. numAttaque = int(str(self.fenetre.ui.pi_listeAttaques.item(ligne, 0).text().toUtf8()))
  777. self.pionSelectionne().attaques[numAttaque].notes = str(self.fenetre.ui.pi_notesAttaqueEC.toPlainText().toUtf8())
  778. def majNotesCombattant(self):
  779. """les notes du pion ont ete mises a jour"""
  780. if self.pionSelectionne() != None:
  781. self.pionSelectionne().notes = str(self.fenetre.ui.pi_notes.toPlainText().toUtf8())
  782. else:
  783. pass
  784. ###############
  785. ######### gestion des evenements souris et clavier ###############
  786. def clic_pion(self, num):
  787. if num > 0:
  788. return self.clic_combattant(num)
  789. else:
  790. return self.clic_decor(num)
  791. def clic_combattant(self, num):
  792. return self.modeActif.clic_combattant(num)
  793. def clic_decor(self, num):
  794. return self.modeActif.clic_decor(num)
  795. def clic_case(self, coord):
  796. return self.modeActif.clic_case(coord)
  797. def survol_pion(self, num):
  798. if num > 0:
  799. return self.survol_combattant(num)
  800. else:
  801. return self.survol_decor(num)
  802. def survol_combattant(self, num):
  803. """le pion est survole par le curseur, on affiche ses informations dans la zone prevue"""
  804. return self.modeActif.survol_decor(num)
  805. def survol_decor(self, num):
  806. """le pion est survole par le curseur, on affiche ses informations dans la zone prevue"""
  807. return self.modeActif.survol_decor(num)
  808. def survol_case(self, coord):
  809. self.majInfoTr(self.cases[coord])
  810. self.majInfoPion(self.pions[self.cases[coord].occupant()])
  811. return self.modeActif.survol_case(coord)
  812. def finSurvol_pion(self, num):
  813. self.majInfoPion(None)
  814. if num > 0:
  815. return self.finSurvol_combattant(num)
  816. else:
  817. return self.finSurvol_decor(num)
  818. def finSurvol_combattant(self, num):
  819. """le pion est survole par le curseur, on affiche ses informations dans la zone prevue"""
  820. return self.modeActif.finSurvol_combattant(num)
  821. def finSurvol_decor(self, num):
  822. """le pion est survole par le curseur, on affiche ses informations dans la zone prevue"""
  823. return self.modeActif.finSurvol_decor(num)
  824. def finSurvol_case(self, coord):
  825. return self.modeActif.finSurvol_case(coord)
  826. def survolClic_case(self, coord):
  827. return self.modeActif.survolClic_case(coord)
  828. def doubleClic_pion(self, num):
  829. if num > 0:
  830. return self.doubleClic_combattant(num)
  831. def doubleClic_combattant(self, num):
  832. return self.modeActif.doubleClic_combattant(num)
  833. def mouseMoveEvent(self, event):
  834. super(Plateau, self).mouseMoveEvent(event)
  835. if event.buttons() == Qt.LeftButton and self.vue().dragMode() != QGraphicsView.ScrollHandDrag:
  836. coord = self.coordonneesAuPoint(event.scenePos())
  837. if coord != None:
  838. self.survolClic_case(coord)
  839. else:
  840. self.modeActif.mouvementSouris(event)
  841. event.ignore()
  842. def mousePressEvent(self, event):
  843. super(Plateau, self).mousePressEvent(event)
  844. if event.button() == 1:
  845. self.modeActif.clicGauche(event)
  846. elif event.button() == 2:
  847. self.modeActif.clicDroit(event)
  848. event.accept()
  849. def mouseReleaseEvent(self, event):
  850. super(Plateau, self).mouseReleaseEvent(event)
  851. self.modeActif.finClicGauche(event)
  852. def keyPressEvent(self, event):
  853. """gestion des evenements clavier"""
  854. self.modeActif.toucheClavier(event)
  855. ################
  856. ############### Fonctions diverses
  857. def pionSelectionne(self):
  858. """renvoie le pion actuellement selectionne"""
  859. if self.modeActif.__class__.__name__ == "PionSelectionne": return self.modeActif.pion()
  860. return None
  861. def afficherListeCases(self, listeCases, actif):
  862. """met ou non en evidence les cases selectionnees"""
  863. for coord in listeCases:
  864. self.cases[coord].majEstCibleCurseur(actif)
  865. def pionDeposer(self, coordCase):
  866. """on depose le pion sur la case voulue"""
  867. if self.pionSelectionne() != None:
  868. pion = self.pionSelectionne()
  869. if pion != None:
  870. if self.proj.valide():
  871. pion.majPosition(self.proj.coord(), self.proj.nbRotations())
  872. def nouveauCache(self, listeCases):
  873. nouvelId = 0
  874. if len(self.caches) > 0:
  875. nouvelId = max(self.caches) + 1
  876. cache = Cache(nouvelId)
  877. cache.activer(True)
  878. cache.nom = "Cache {}".format(nouvelId + 1)
  879. self.caches[nouvelId] = cache
  880. self.ajouterCacheATable(cache)
  881. for coord in listeCases:
  882. self.cases[coord].ajouterCache(nouvelId)
  883. def supprimerCache(self):
  884. ligne = self.fenetre.ui.cp_listeCaches.currentRow()
  885. idCache = int(self.fenetre.ui.cp_listeCaches.texte(ligne, 0))
  886. for coord in self.cases:
  887. self.cases[coord].supprimerCache(idCache)
  888. self.fenetre.ui.cp_listeCaches.removeRow(idCache)
  889. del self.caches[idCache]
  890. def centrerSur(self, num):
  891. """centre la vue sur le pion"""
  892. self.vue().centerOn(self.cases[self.pions[num].position].centreGraphique)
  893. def coordonneesAuPoint(self, point):
  894. """renvoie les coordonnees de la case situee au QPointF entre en parametre"""
  895. item = self.itemAt(point)
  896. try:
  897. coord = item.coord()
  898. except:
  899. coord = None
  900. return coord
  901. def pionAuPoint(self, point):
  902. """retourne le premier pion de la pile s'il y en a plusieurs"""
  903. coord = self.coordonneesAuPoint(point)
  904. if not coord: return None
  905. pions = self.cases[coord].occupants()
  906. if len(pions) == 0: return None
  907. return pions[0]
  908. def ldmValide(self, origine, cible):
  909. """la ligne de mire entre les deux points est elle valide
  910. origine et cible sont toutes deux de la forme (x,y,z)"""
  911. if not cible != origine: return False
  912. ldm = self.geo.ligne(origine, cible)
  913. if len(ldm) == 0: return False
  914. ldm.remove(origine) ; ldm.remove(cible)
  915. x0, y0, z0 = origine ; x1, y1, z1 = cible
  916. for coord in ldm:
  917. x, y, z = coord
  918. occupant = self.cases[(x, y)].occupant(z)
  919. if occupant:
  920. #si une case de la ligne est occupee par autre chose que le tireur et sa cible
  921. if occupant != self.cases[(x0, y0)].occupant(z0) and \
  922. occupant != self.cases[(x1, y1)].occupant(z1):
  923. return False
  924. return True
  925. def coutDep(self, coord1, coord2, z2 = None):
  926. """renvoie le cout de deplacement de la case 1 a la case 2
  927. pour le pion actuellement selectionne /
  928. un cout egal a -1 implique un deplacement impossible"""
  929. retour = 0
  930. dist = 1
  931. if not self.cases[coord2].terrain.franchissable: return -1
  932. if self.cases[coord2].z1(): return -1
  933. if z2 == None: z2 = self.cases[coord2].z1()
  934. if self.cases[coord2].occupant(z2): return -1
  935. if self.pionSelectionne().zR == 0:
  936. dz = self.cases[coord2].z1() - self.cases[coord1].z1()
  937. if dz < (-1 * self.pionSelectionne().saut): return -1
  938. if dz > self.pionSelectionne().h:
  939. #si la diff de hauteur est superieure a la hauteur du combattant, il escalade
  940. if not self.pionSelectionne().depEscalade > 0: return -1
  941. retour += self.pionSelectionne().coutDep("depEscalade", dz)
  942. elif 0 < dz <= self.pionSelectionne().h:
  943. dist += dz
  944. if self.cases[coord2].terrain.nage:
  945. if not self.pionSelectionne().depNage > 0: return -1
  946. retour += self.pionSelectionne().coutDep("depNage", dist)
  947. else:
  948. if not self.pionSelectionne().depMarche > 0: return -1
  949. retour += self.pionSelectionne().coutDep("depMarche", dist)
  950. else:
  951. if not self.pionSelectionne().depVol > 0: return -1
  952. retour += self.pionSelectionne().coutDep("depVol", dist)
  953. return retour
  954. def majZonePlacement(self, listeCases):
  955. """met a jour la forme et l'affichage de la zone de placement initale des joueurs"""
  956. if len(listeCases) > 0:
  957. if self.polygoneZonePlacement == None:
  958. self.polygoneZonePlacement = QGraphicsPolygonItem(scene=self)
  959. self.polygoneZonePlacement.setZValue(0)
  960. qCouleurFond = QColor("white")
  961. qCouleurFond.setAlpha(50)
  962. self.polygoneZonePlacement.setBrush(qCouleurFond)
  963. pinceau = QPen(QColor("orange"))
  964. pinceau.setWidth(20)
  965. self.polygoneZonePlacement.setPen(pinceau)
  966. self.polygoneZonePlacement.setAcceptedMouseButtons(Qt.NoButton)
  967. self.polygoneZonePlacement.setAcceptHoverEvents(False)
  968. self.addItem(self.polygoneZonePlacement)
  969. listeCases2 = []
  970. for coord in listeCases:
  971. if self.cases[coord].terrain.franchissable:
  972. listeCases2.append(coord)
  973. listeCases3 = self.geo.blocAdjacent(listeCases2)
  974. polygone = self.geo.polygoneAgglo(listeCases3)
  975. if not polygone: return
  976. self.polygoneZonePlacement.setPolygon(polygone)
  977. self.listeCasesZonePlacement = listeCases
  978. ####### maj des panneaux d'info
  979. def majInfoPion(self, pion = None):
  980. self.majInfoCb((pion if pion.numero > 0 else None) if pion else None)
  981. self.majInfoDc((pion if pion.numero < 0 else None) if pion else None)
  982. def majInfoCb(self, cb = None):
  983. self.fenetre.ui.icb_panneau.setVisible((cb != None))
  984. if cb:
  985. self.fenetre.ui.icb_image.chargerImage(cb.icone())
  986. self.fenetre.ui.icb_nom.majTexte(contractTxt(cb.nom(), 25))
  987. self.fenetre.ui.icb_mort.setVisible((cb.etat == 4))
  988. self.fenetre.ui.icb_image.setEnabled((cb.etat != 4))
  989. self.fenetre.ui.icb_etourdi.setVisible(0 in cb.statuts)
  990. self.fenetre.ui.icb_brule.setVisible(4 in cb.statuts)
  991. self.fenetre.ui.icb_paralyse.setVisible(2 in cb.statuts)
  992. self.fenetre.ui.icb_empoisonne.setVisible(3 in cb.statuts)
  993. self.fenetre.ui.icb_gele.setVisible(1 in cb.statuts)
  994. self.fenetre.ui.icb_etat.majTexte(lstLibEtats("cb")[cb.etat])
  995. self.fenetre.ui.icb_hauteur.majTexte("Hauteur: {}".format(cb.h))
  996. self.fenetre.ui.icb_vol.majTexte("En vol: {}".format(cb.zR) if cb.enVol else "")
  997. def majInfoDc(self, dc = None):
  998. self.fenetre.ui.idc_panneau.setVisible((dc != None))
  999. if dc:
  1000. self.fenetre.ui.idc_image.chargerImage(dc.icone())
  1001. self.fenetre.ui.idc_nom.majTexte(contractTxt(dc.nom(), 25))
  1002. self.fenetre.ui.idc_detruit.setVisible((dc.etat == 4))
  1003. self.fenetre.ui.idc_image.setEnabled((dc.etat != 4))
  1004. self.fenetre.ui.idc_brule.setVisible(4 in dc.statuts)
  1005. self.fenetre.ui.idc_verrouille.setVisible(5 in dc.statuts)
  1006. self.fenetre.ui.idc_etat.majTexte(lstLibEtats("dc")[dc.etat])
  1007. self.fenetre.ui.idc_hauteur.majTexte("Hauteur: {}".format(dc.h) if not (self.zP and dc.hMax) else "")
  1008. def majInfoTr(self, case = None):
  1009. if case:
  1010. self.fenetre.ui.ic_coord.majTexte("X{} Y{}".format(case.x, case.y))
  1011. self.fenetre.ui.ic_terrain.majTexte(case.terrain.nom() if (len(case.terrain.nom()) > 0) else "Case")
  1012. self.fenetre.ui.ic_altitude.majTexte("{}".format(case.z0))
  1013. if case.effetActif not in ["", "aucun"]:
  1014. imgEffet = {"brule": "feu_16.png", "eau": "eau_16.png","glace": "glace_16.png","poison": "poison_16.png"}
  1015. pix = QPixmap(":/interface/16/ressource/{}".format(imgEffet[case.effetActif]))
  1016. self.fenetre.ui.ic_effet.setPixmap(pix)
  1017. else:
  1018. self.fenetre.ui.ic_effet.clear()