Mercurial > parpg-core
view src/parpg/charactercreationcontroller.py @ 150:3fc7cfa80771
Modified InventoryGrid to set a name for each slot containing the index.
Added getSlot method to InventoryGrid.
Renamed InventoryGUI class to CharacterGUI.
Added InventoryGUI class which handles the inventory part of the CharacterGUI.
An InventoryGUI instance is now created in CharacterGUI.
author | KarstenBock@gmx.net |
---|---|
date | Wed, 05 Oct 2011 12:59:22 +0200 |
parents | a6b25c2cedab |
children | 756ce052ac85 |
line wrap: on
line source
# This file is part of PARPG. # # PARPG is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # PARPG is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with PARPG. If not, see <http://www.gnu.org/licenses/>. """Provides the controller that defines the behaviour of the character creation screen.""" from parpg import vfs import characterstatistics as char_stats from serializers import XmlSerializer from controllerbase import ControllerBase from gamescenecontroller import GameSceneController from gamesceneview import GameSceneView from parpg.world import World from parpg.entities import General DEFAULT_STAT_VALUE = 50 def getStatCost(offset): """Gets and returns the cost to increase stat based on the offset""" if offset < 0: offset *= -1 if offset < 22: return 1 elif offset < 29: return 2 elif offset < 32: return 3 elif offset < 35: return 4 elif offset < 36: return 5 elif offset < 38: return 6 elif offset < 39: return 7 elif offset < 40: return 8 elif offset < 41: return 9 else: return 10 class CharacterCreationController(ControllerBase, World): """Controller defining the behaviour of the character creation screen.""" #TODO: Change to actual values MAX_TRAITS = 3 MIN_AGE = 16 MAX_AGE = 40 ORIGINS = {"None": None,} GENDERS = ["Male", "Female",] PICTURES = {"Male": ["None",], "Female": ["None",],} TRAITS = {} MAX_BULK = 100 INV_SLOTS = 20 def __init__(self, engine, view, model, application): """Construct a new L{CharacterCreationController} instance. @param engine: Rendering engine used to display the associated view. @type engine: L{fife.Engine} @param view: View used to display the character creation screen. @type view: L{ViewBase} @param model: Model of the game state. @type model: L{GameModel} @param application: Application used to glue the various MVC components together. @type application: L{fife.extensions.basicapplication.ApplicationBase}""" ControllerBase.__init__(self, engine, view, model, application) World.__init__(self) self.settings = self.model.settings self.view.start_new_game_callback = self.startNewGame self.view.cancel_new_game_callback = self.cancelNewGame def reset_character(self): # FIXME M. George Hansen 2011-06-06: character stats scripts aren't # finished, unfortunately. # primary_stats_file = \ # vfs.VFS.open('character_scripts/primary_stats.xml') # primary_stats = XmlSerializer.deserialize(primary_stats_file) # secondary_stats_file = \ # vfs.VFS.open('character_scripts/secondary_stats.xml') # secondary_stats = XmlSerializer.deserialize(secondary_stats_file) primary_stats = [] secondary_stats = [] inventory = [] for x in xrange(self.INV_SLOTS): inventory.append(None) self.char_data = General(self, "PlayerCharacter") self.char_data.description.view_name = "Player" self.char_data.description.real_name = "Enter name here" self.char_data.characterstats.gender = self.GENDERS[0] self.char_data.characterstats.origin = self.ORIGINS.keys()[0] self.char_data.characterstats.age = 20 self.char_data.characterstats.picture = ( self.PICTURES[self.GENDERS[0]][0] ) for primary_stat in primary_stats: short_name = primary_stat.short_name self.char_data.characterstats.primary_stats[short_name] = ( char_stats.PrimaryStatisticValue( primary_stat, self, DEFAULT_STAT_VALUE) ) for secondary_stat in secondary_stats: name = secondary_stat.name self.char_data.characterstats.secondary_stats[name] = ( char_stats.SecondaryStatisticValue(secondary_stat, self) ) self.char_data.container.max_bulk = self.MAX_BULK self.char_data.container.children = inventory self._stat_points = 200 def startNewGame(self): """Create the new character and start a new game. @return: None""" view = GameSceneView(self.engine, self.model) controller = GameSceneController(self.engine, view, self.model, self.application) self.application.view = view self.application.manager.swap_modes(controller) start_map = self.settings.parpg.Map self.model.changeMap(start_map) def cancelNewGame(self): """Exit the character creation view and return the to main menu. @return: None""" # KLUDGE Technomage 2010-12-24: This is to prevent a circular import # but a better fix needs to be thought up. from mainmenucontroller import MainMenuController from mainmenuview import MainMenuView view = MainMenuView(self.engine, self.model) controller = MainMenuController(self.engine, view, self.model, self.application) self.application.view = view self.application.manager.activate_mode(controller) def on_activate(self): self.reset_character() self.view.show() def on_deactivate(self): """Called when the controller is removed from the list. @return: None""" self.view.hide() @property def name(self): """Returns the name of the character. @return: Name of the character""" return self.char_data.description.real_name @property def age(self): """Returns the age of the character. @return: Age of the character""" return self.char_data.characterstats.age @property def gender(self): """Returns the gender of the character. @return: Gender of the character""" return self.char_data.characterstats.gender @property def origin(self): """Returns the origin of the character. @return: Origin of the character""" return self.char_data.characterstats.origin @property def picture(self): """Returns the ID of the current picture of the character.""" return self.char_data.characterstats.picture def getStatPoints(self): """Returns the remaining statistic points that can be distributed""" return self._stat_points def increaseStatistic(self, statistic): """Increases the given statistic by one. @param statistic: Name of the statistic to increase @type statistic: string""" if self.canIncreaseStatistic(statistic): cost = self.getStatisticIncreaseCost(statistic) if cost <= self._stat_points: (self.char_data.characterstats. primary_stats[statistic].value) += 1 self._stat_points -= cost def getStatisticIncreaseCost(self, statistic): """Calculate and return the cost to increase the statistic @param statistic: Name of the statistic to increase @type statistic: string @return cost to increase the statistic""" cur_value = (self.char_data.characterstats. primary_stats[statistic].value) new_value = cur_value + 1 offset = new_value - DEFAULT_STAT_VALUE return getStatCost(offset) def canIncreaseStatistic(self, statistic): """Checks whether the given statistic can be increased or not. @param statistic: Name of the statistic to check @type statistic: string @return: True if the statistic can be increased, False if not.""" stat = self.char_data.characterstats.primary_stats[statistic].value return stat < stat.statistic_type.maximum def decreaseStatistic(self, statistic): """Decreases the given statistic by one. @param statistic: Name of the statistic to decrease @type statistic: string""" if self.canDecreaseStatistic(statistic): gain = self.getStatisticDecreaseGain(statistic) self.char_data.characterstats.primary_stats[statistic].value -= 1 self._stat_points += gain def getStatisticDecreaseGain(self, statistic): """Calculate and return the gain of decreasing the statistic @param statistic: Name of the statistic to decrease @type statistic: string @return cost to decrease the statistic""" cur_value = (self.char_data.characterstats. primary_stats[statistic].value) new_value = cur_value - 1 offset = new_value - DEFAULT_STAT_VALUE return getStatCost(offset) def canDecreaseStatistic(self, statistic): """Checks whether the given statistic can be decreased or not. @param statistic: Name of the statistic to check @type statistic: string @return: True if the statistic can be decreased, False if not.""" stat = self.char_data.characterstats.primary_stats[statistic].value return stat > stat.statistic_type.minimum def getStatisticValue(self, statistic): """Returns the value of the given statistic. @param statistic: Name of the primary or secondary statistic @type statistic: string @return: Value of the given statistic""" if self.char_data.characterstats.primary_stats.has_key: return self.char_data.characterstats.primary_stats[statistic] else: return self.char_data.characterstats.secondary_stats[statistic] def areAllStatisticsValid(self): """Checks if all statistics are inside the minimum/maximum values @return True if all statistics are valid False if not""" all_stats = self.char_data.characterstats.primary_stats.items() all_stats.extend(self.char_data.characterstats.secondary_stats.items()) for stat in all_stats: if not (stat.value > stat.statistic_type.minumum and\ stat.value < stat.statistic_type.maximum): return False return True def setName(self, name): """Sets the name of the character to the given value. @param name: New name @type name: string""" self.char_data.description.real_name = name def isNameValid(self, name): """Checks whether the name is valid. @param name: Name to check @type name: string @return: True if the name is valid, False if not""" if name: return True return False def changeOrigin(self, origin): """Changes the origin of the character to the given value. @param origin: New origin @type origin: string""" if self.isOriginValid(origin): self.char_data.characterstats.origin = origin #TODO: Make changes according to origin def isOriginValid(self, origin): """Checks whether the origin is valid. @param origin: Origin to check @type origin: string @return: True if the origin is valid, False if not""" return origin in self.ORIGINS def changeGender(self, gender): """Changes the gender of the character to the given value. @param gender: New gender @param gender: string""" if self.isGenderValid(gender): self.char_data.characterstats.gender = gender def isGenderValid(self, gender): """Checks whether the gender is valid. @param gender: Gender to check @type gender: string? @return: True if the origin is valid, False if not""" return gender in self.GENDERS def changeAge(self, age): """Sets the age of the character to the given value. @param age: New age @type age: integer """ if self.isAgeValid(age): self.char_data.characterstats.age = age def isAgeValid(self, age): """Checks whether the age is valid. @param age: Age to check @type age: integer @return: True if the origin is valid, False if not""" return age >= self.MIN_AGE and age <= self.MAX_AGE def setPicture(self, picture): """Set picture of the character. @param picture: ID of the new picture @type picture: string""" if self.isPictureValid(picture): self.char_data.characterstats.picture = picture def isPictureValid(self, picture): """Checks whether the picture is valid. @param picture: ID of the picture to check @type picture: string @return: True if the picture is valid, False if not""" return picture in self.PICTURES[self.gender] def addTrait(self, trait): """Adds a trait to the character. @param trait: ID of the trait to add @type trait: string""" if self.canAddAnotherTrait() and self.isTraitValid(trait)\ and not self.hasTrait(trait): self.char_data.characterstats.traits.append(trait) def canAddAnotherTrait(self): """Checks whether another trait can be added. @return: True if another trait can be added, False if not""" return len(self.char_data.characterstats.traits) < self.MAX_TRAITS def removeTrait(self, trait): """Remove trait from character. @param trait: ID of the trait to remove @type trait: string""" if self.hasTrait(trait): self.char_data.characterstats.traits.remove(trait) def hasTrait(self, trait): """Checks whether the character has the trait. @param trait: ID of the trait to check @type trait: string @return: True if the character has the trait, False if not""" return trait in self.char_data.characterstats.traits def isTraitValid(self, trait): """Checks whether the trait is valid. @param trait: ID of the trait to check @type trait: string @return: True if the trait is valid, False if not""" return trait in self.TRAITS def areCurrentTraitsValid(self): """Checks whether the characters traits are valid. @return: True if the traits are valid, False if not""" if len(self.char_data.characterstats.traits) > self.MAX_TRAITS: return False for trait in self.char_data.characterstats.traits: if not self.isTraitValid(trait): return False return True def isCharacterValid(self): """Checks whether the character as a whole is valid. @return: True if the character is valid, False if not""" #Single checks can be disabled by putting a "#" in front of them if True\ and self._stat_points >= 0\ and self.areAllStatisticsValid() \ and self.areCurrentTraitsValid() \ and self.isNameValid(self.name)\ and self.isPictureValid(self.picture)\ and self.isAgeValid(self.age)\ and self.isGenderValid(self.gender)\ and self.isOriginValid(self.origin)\ : return True return False