Difference between revisions of "Packages"

From VCMI Project Wiki
Jump to: navigation, search
(Adding new objects)
(Package structure)
 
(15 intermediate revisions by the same user not shown)
Line 13: Line 13:
 
All files should be placed within the scope of root folder of mod.py file.
 
All files should be placed within the scope of root folder of mod.py file.
 
Mods folder in main VCMI directory is scanned upon entering "new game" menu in search of mod.py files.
 
Mods folder in main VCMI directory is scanned upon entering "new game" menu in search of mod.py files.
 +
 +
In order to ensure compatibility and ease of maintenance, all pacages should follow [[Package folder structure]].
  
 
=Adding new objects=
 
=Adding new objects=
 +
 +
Currently, all handlers load object configuration from game files at application launch. This needs to be separated into basic initialization of engine at application launch and dynamic management of avaliable mods in main menu as well as reconfiguration and dynamic loading of files at game start.
  
 
An example pseudo-code in Python for adding new artifact:
 
An example pseudo-code in Python for adding new artifact:
 
<pre>
 
<pre>
id = CreateArtifact(  
+
art = CreateArtifact(  
'CrystalOrb', #reference name
+
'CrystalOrb', #reference name
'Crystal Orb', #actual name in game
+
'Crystal Orb', #actual name in game
Artifact.ART_RELIC, #rarity from namespace Atifact
+
Artifact.ART_RELIC, #rarity from namespace Atifact
Artifact.ART_HERO, #artifact type (including combined artifacts, commander or creature art)
+
Artifact.ART_HERO, #artifact type (including combined artifacts, commander or creature art)
Artifact.ARTPOS_MISC #slot  
+
Artifact.ARTPOS_MISC #slot  
 
)  
 
)  
id.AddBonus (Bonus.SIGHT_RADIOUS,+12) #using namespace Bonus (in Python they are called packages and modules, but that's confusing)
+
art.AddBonus (Bonus.SIGHT_RADIOUS,+12) #using namespace Bonus (in Python they are called packages and modules, but that's confusing)
id.price = 8000  
+
art.price = 8000  
id.AIValue = 12000  
+
art.AIValue = 12000  
id.description = ParseTextFile ('.\CrystalOrb.txt')  
+
art.description = ParseTextFile ('.\CrystalOrb.txt')  
 
SetArtifactDef ('CrystalOrb','.\lodfile\orb.def')  
 
SetArtifactDef ('CrystalOrb','.\lodfile\orb.def')  
ArtHandler.SetArtAvaliable ('CrystalOrb')  
+
id = ArtHandler.addArtifact ('CrystalOrb') # we get unique ID of that object
 +
ArtHandler.setArtAvaliable(id, true) #Artifact can be found in game at random
 +
 
 +
localID = package.addArtifact('CrystalOrb'); # we get local ID which may be used to refer from other package or script
 
</pre>
 
</pre>
 +
 +
=Object scripting=
 +
Some game objects, such as adventure map buildings may require completely new mechanics. In such case an explicit script function is needed to handle them.
 +
==Artifacts==
 +
Artifact may have a list of functions associated with certain game event(triggers). For example, a function is called when artifact is equipped, at the beginning of battle, at the beginning of each turn etc. This system uses same type of Triggers as ERM scripts, possibly with addition of new ones.
 +
All these functions need to be listed somewhere. For example, a class inherited from CArtifact may have a colection of functions associated with every possible trigger, or void. This of course causes redundancy, but the cost may be not significant.
 +
==Adventure map objects==
 +
Every adventure object acts in a different way. It's not possible to present their behaviour in a form of parameters or property sheet.
 +
It is possible with Python to export some base C++ object classes, such as CPlayersVisited or CArmedInstance to Python classes and ask modders to derive new sub-classes from them, overriding existing functions. This approach requires existence of clear structure of abstract base classes and separating interface from actual behaviour. Currently one class (for example CGVisitableOPH) handles behaviour of many evidently different objects with different ID, such as Tree of Knowledge, Library of Enlightenment AND Arena. This structure is hardcoded and not useful for modders.
 +
 +
==Town buildings==
 +
==Spells==
 +
 +
=Configuration=
 +
There are two types of configuration for a package:
 +
*Setting the value of variable, numerical or boolen (on/off)
 +
*Grouping objects which can be turned on and off at the same time for convenience.

Latest revision as of 09:09, 17 April 2012

Package structure

Packages may consist of following files:

  • mod.py - main file required by Mod Handler. Includes unique name and version of package. Lists all related files included in mod.
  • Script defining new objects and requesting Mod Handler to put them in game.
  • Graphics files
  • Sound files
  • Additional Python script files (.py)
  • Additional text files
  • Possibly .json files

All files should be placed within the scope of root folder of mod.py file. Mods folder in main VCMI directory is scanned upon entering "new game" menu in search of mod.py files.

In order to ensure compatibility and ease of maintenance, all pacages should follow Package folder structure.

Adding new objects

Currently, all handlers load object configuration from game files at application launch. This needs to be separated into basic initialization of engine at application launch and dynamic management of avaliable mods in main menu as well as reconfiguration and dynamic loading of files at game start.

An example pseudo-code in Python for adding new artifact:

art = CreateArtifact( 
		'CrystalOrb', 		#reference name
		'Crystal Orb', 		#actual name in game
		Artifact.ART_RELIC, 	#rarity from namespace Atifact
		Artifact.ART_HERO, 	#artifact type (including combined artifacts, commander or creature art)
		Artifact.ARTPOS_MISC 	#slot 
		) 
art.AddBonus (Bonus.SIGHT_RADIOUS,+12) 	#using namespace Bonus (in Python they are called packages and modules, but that's confusing)
art.price = 8000 
art.AIValue = 12000 
art.description = ParseTextFile ('.\CrystalOrb.txt') 
SetArtifactDef ('CrystalOrb','.\lodfile\orb.def') 
id = ArtHandler.addArtifact ('CrystalOrb')	# we get unique ID of that object
ArtHandler.setArtAvaliable(id, true)		#Artifact can be found in game at random

localID = package.addArtifact('CrystalOrb');	# we get local ID which may be used to refer from other package or script

Object scripting

Some game objects, such as adventure map buildings may require completely new mechanics. In such case an explicit script function is needed to handle them.

Artifacts

Artifact may have a list of functions associated with certain game event(triggers). For example, a function is called when artifact is equipped, at the beginning of battle, at the beginning of each turn etc. This system uses same type of Triggers as ERM scripts, possibly with addition of new ones. All these functions need to be listed somewhere. For example, a class inherited from CArtifact may have a colection of functions associated with every possible trigger, or void. This of course causes redundancy, but the cost may be not significant.

Adventure map objects

Every adventure object acts in a different way. It's not possible to present their behaviour in a form of parameters or property sheet. It is possible with Python to export some base C++ object classes, such as CPlayersVisited or CArmedInstance to Python classes and ask modders to derive new sub-classes from them, overriding existing functions. This approach requires existence of clear structure of abstract base classes and separating interface from actual behaviour. Currently one class (for example CGVisitableOPH) handles behaviour of many evidently different objects with different ID, such as Tree of Knowledge, Library of Enlightenment AND Arena. This structure is hardcoded and not useful for modders.

Town buildings

Spells

Configuration

There are two types of configuration for a package:

  • Setting the value of variable, numerical or boolen (on/off)
  • Grouping objects which can be turned on and off at the same time for convenience.