From 243094b1ea259c19c6cf1b2779abe443fdc2a1f0 Mon Sep 17 00:00:00 2001 From: Ivan Savenko Date: Sun, 13 Aug 2023 00:17:38 +0300 Subject: [PATCH] Imported all data from website wiki --- docs/Frequently asked questions.md | 62 ++ docs/Main Page.md | 79 ++ docs/TODO list.md | 164 +++ docs/developers/Architektura.png | Bin 0 -> 5144 bytes docs/developers/BattleField.png | Bin 0 -> 138134 bytes docs/developers/Bonus system.md | 140 +++ docs/developers/Code_structure.md | 213 ++++ docs/developers/Coding Guidelines.md | 972 ++++++++++++++++++ .../developers/Development_with_Qt_Creator.md | 49 + .../developers/How to build VCMI (Android).md | 117 +++ docs/developers/How to build VCMI (Linux).md | 217 ++++ .../How to build VCMI (Visual Studio 2015).md | 165 +++ .../How to build VCMI (Windows Vcpkg).md | 258 +++++ docs/developers/How to build VCMI (iOS).md | 111 ++ docs/developers/How to build VCMI (macOS).md | 170 +++ docs/developers/Logging API.md | 201 ++++ docs/developers/Logging_Class_Diagram.png | Bin 0 -> 27067 bytes docs/developers/Serialization.md | 352 +++++++ docs/modders/Bonus/List of all bonus types.md | 832 +++++++++++++++ .../Bonus/List of bonus duration types.md | 16 + docs/modders/Bonus/List of bonus limiters.md | 105 ++ .../Bonus/List of bonus propagators.md | 25 + .../Bonus/List of bonus range types.md | 20 + docs/modders/Bonus/List of bonus sources.md | 21 + docs/modders/Bonus/List of bonus updaters.md | 89 ++ .../Bonus/List of bonus value types.md | 31 + docs/modders/Building bonuses.md | 169 +++ docs/modders/Map objects/Creature bank.md | 66 ++ docs/modders/Map objects/Dwelling.md | 22 + docs/modders/Random map template.md | 101 ++ docs/players/Game mechanics.md | 55 + docs/players/Installation on Android.md | 63 ++ docs/players/Installation on Linux.md | 158 +++ docs/players/Installation on Windows.md | 51 + docs/players/Installation on iOS.md | 98 ++ docs/players/Installation on macOS.md | 50 + 36 files changed, 5242 insertions(+) create mode 100644 docs/Frequently asked questions.md create mode 100644 docs/Main Page.md create mode 100644 docs/TODO list.md create mode 100644 docs/developers/Architektura.png create mode 100644 docs/developers/BattleField.png create mode 100644 docs/developers/Bonus system.md create mode 100644 docs/developers/Code_structure.md create mode 100644 docs/developers/Coding Guidelines.md create mode 100644 docs/developers/Development_with_Qt_Creator.md create mode 100644 docs/developers/How to build VCMI (Android).md create mode 100644 docs/developers/How to build VCMI (Linux).md create mode 100644 docs/developers/How to build VCMI (Visual Studio 2015).md create mode 100644 docs/developers/How to build VCMI (Windows Vcpkg).md create mode 100644 docs/developers/How to build VCMI (iOS).md create mode 100644 docs/developers/How to build VCMI (macOS).md create mode 100644 docs/developers/Logging API.md create mode 100644 docs/developers/Logging_Class_Diagram.png create mode 100644 docs/developers/Serialization.md create mode 100644 docs/modders/Bonus/List of all bonus types.md create mode 100644 docs/modders/Bonus/List of bonus duration types.md create mode 100644 docs/modders/Bonus/List of bonus limiters.md create mode 100644 docs/modders/Bonus/List of bonus propagators.md create mode 100644 docs/modders/Bonus/List of bonus range types.md create mode 100644 docs/modders/Bonus/List of bonus sources.md create mode 100644 docs/modders/Bonus/List of bonus updaters.md create mode 100644 docs/modders/Bonus/List of bonus value types.md create mode 100644 docs/modders/Building bonuses.md create mode 100644 docs/modders/Map objects/Creature bank.md create mode 100644 docs/modders/Map objects/Dwelling.md create mode 100644 docs/modders/Random map template.md create mode 100644 docs/players/Game mechanics.md create mode 100644 docs/players/Installation on Android.md create mode 100644 docs/players/Installation on Linux.md create mode 100644 docs/players/Installation on Windows.md create mode 100644 docs/players/Installation on iOS.md create mode 100644 docs/players/Installation on macOS.md diff --git a/docs/Frequently asked questions.md b/docs/Frequently asked questions.md new file mode 100644 index 000000000..3e8a300c9 --- /dev/null +++ b/docs/Frequently asked questions.md @@ -0,0 +1,62 @@ +## General + +#### What to expect working in VCMI? + +Most of original game except multiplayer. Everything else is better to +report on our [bugtracker](http://bugs.vcmi.eu). + +#### Can I play VCMI on my Android device? + +Read this: + +#### Do I need to install WoG to play VCMI? + +No. VCMI has it's own port of WoG mod available from Launcher. We +recommend to install VCMI over fresh SoD / Complete versions. + +#### What does "VCMI" stand for? + +VCMI is an acronym of the [Quenya](https://en.wikipedia.org/wiki/Quenya) +phrase "Vinyar Callor Meletya Ingole", meaning "New Heroes of Might and +Magic". ([Source](https://forum.vcmi.eu/t/what-vcmi-stands-for/297/4)) + +## Game options + +#### How can I change screen resolution? + +Start any scenario, open System Options dialog and click "High" button. + +In case only 800x600 is available, close VCMI, download this +[file](https://www.dropbox.com/sh/fwor43x5xrgzx6q/AABpTFqGK7Q9almbyr3hp9jma/mods/vcmi.zip) +which contains the “bonusIcons” and “extraResolutions” repertories. +Unzip, and place them in XXX (Windows), YYY (Android), ZZZ (Mac) or +~/.local/share/vcmi/Mods (Linux). Then start any scenario, open System +Options dialog and voilà, other resolutions than 800x600 are availables. + +Note that you need to restart VCMI for the change to take effect. + +#### How to turn off creature queue panel in battles? + +Hotkey to switch this panel is "Q" + +#### Can I turn off some WoG features that I don't like? + +Yes. Take a look on config/defaultMods.json file and edit it to your +liking. + +Note to Linux users: this file can be found in vcmi data directory (run +vcmiclient -v to see path). It can be copied into ~/.vcmi/config/ to +avoid editing file usually owned by root. + +## Mods + +#### Is it possible to add town X to vcmi? + +This depends on town authors or anyone else willing to port it to vcmi. +Aim of VCMI is to provide *support* for such features. + +#### Where can I find mods for VCMI? + +Check +[Modding_guidelines#For_players](Modding_guidelines#For_players "wikilink") +page \ No newline at end of file diff --git a/docs/Main Page.md b/docs/Main Page.md new file mode 100644 index 000000000..db7d16310 --- /dev/null +++ b/docs/Main Page.md @@ -0,0 +1,79 @@ +# Welcome to VCMI Project Wiki + +[VCMI](VCMI "wikilink") is an open-source project aiming to reimplement +HMM3:WoG and SoD game engines, giving it new and extended possibilities. + +## Latest release + +As of 28th of April 2023, we released [VCMI +1.2.1](https://github.com/vcmi/vcmi/releases/tag/1.2.1). Now we plan to +have releases 3-4 times per year. Daily builds are still available at +[builds.vcmi.download](https://builds.vcmi.download/branch/develop/) but +they are not guaranteed to be stable. So we encourage everybody to use +them and report found bugs so that we can fix them. +Loading saves made with different version of VCMI is usually **not** +supported, so you may want to finish your ongoing games before +updating. +Please see corresponding "installation on" articles for details for your +platform. + +## Documentation and guidelines for users + +- [ General information about VCMI Project](VCMI "wikilink") +- [Frequently asked questions](Frequently_asked_questions "wikilink") +- [Engine features](Engine_features "wikilink") +- [Game mechanics](Game_mechanics "wikilink") +- [Bug reporting guidelines](Bug_reporting_guidelines "wikilink") +- [Mod list](Mod_list "wikilink") +- [Cheat codes](Cheat_codes "wikilink") +- [Installation](Installation "wikilink") guides: + - [Windows](Installation_on_Windows "wikilink") + - [macOS](Installation_on_macOS "wikilink") + - [Linux](Installation_on_Linux "wikilink") + - [Android](Installation_on_Android "wikilink") + - [iOS](Installation_on_iOS "wikilink") + +## Documentation and guidelines for modders + +- [Modding guidelines](Modding_guidelines "wikilink") +- [Mods repository](Mods_repository "wikilink") +- Formats: + - [Mod file Format](Mod_file_Format "wikilink") + - [Town Format](Town_Format "wikilink") + - [Hero Classes Format](Hero_Classes_Format "wikilink") + - [Hero Format](Hero_Format "wikilink") + - [Creature Format](Creature_Format "wikilink") + - [Artifact Format](Artifact_Format "wikilink") + - [Animation Format](Animation_Format "wikilink") + - [Bonus Format](Bonus_Format "wikilink") + - [Object Format](Object_Format "wikilink") + - [Spell Format](Spell_Format "wikilink") + - [Skill Format](Skill_Format "wikilink") + +## Documentation and guidelines for developers + +- How to build using CMake: + - [Linux](How_to_build_VCMI_(Linux) "wikilink") + - [Linux/MinGW (for + Windows)](How_to_build_VCMI_(Linux/MinGW) "wikilink") + - [macOS](How_to_build_VCMI_(macOS) "wikilink") + - [Windows](How_to_build_VCMI_(Windows/Vcpkg) "wikilink") + - [iOS](How_to_build_VCMI_(iOS) "wikilink") + - [ Android](How_to_build_VCMI_(Android) "wikilink") +- Unsupported build instructions: + - [Windows/MSVS (Visual Studio + 2015)](How_to_build_VCMI_(Windows/Visual_Studio_2015) "wikilink") +- [Coding guidelines](Coding_guidelines "wikilink") +- [Code structure](Code_structure "wikilink") +- [Logging API](Logging_API "wikilink") +- Development environment guides: + - [Development with Qt + Creator](Development_with_Qt_Creator "wikilink") + +## VCMI Places + +- [Website](https://vcmi.eu/) +- [Forum](https://forum.vcmi.eu/) +- [Bugtracker](https://bugs.vcmi.eu/) +- [Slack invite page](https://slack.vcmi.eu/) +- [GitHub repository](https://github.com/vcmi/vcmi) \ No newline at end of file diff --git a/docs/TODO list.md b/docs/TODO list.md new file mode 100644 index 000000000..f21b806e9 --- /dev/null +++ b/docs/TODO list.md @@ -0,0 +1,164 @@ +The list of all essential, optional and requested features alongside +with the team members interested in them. + +# Heroes III + +[Missing features at +Trello](https://trello.com/b/68e5rAAl/vcmi-missing-features-only) + +### Most important bugfixes + +- daily build contains broken vcmi essential package (ticket is for + linux but same problem on Windows also) + - questionable +- desync in multiplayer cross-platform + + +### Establish release process + +In January 2021 there was a proposition on Slack to make 3 branches: +develop, beta and stable. develop is where people make their changes +when they are ready, people can test it but its not for normal players +beta could be for players who agree to be testers. stable could be for +players who want stable version. Hovewer there were no decision made + +### HD mod/quality of life + +contact MikeLodz if you have questions about this section + +These are necessary, as although they werent present back in 1999, they +are standard today. + +- quick transfer of artifacts and armies between heroes, started here + +- adventure map: movements points preview and cost +- move artifacts between visiting town and garrison heroes +- hero list preview on the "start map" screen. + +etc see here for full list of enhancements: + + +- some walking creatures need to move faster during battles, as its a + complete waste of time (we need a so called "turbo" mode) + + + +- this one not sure if its a bug or missing hd mod feature: it should + be possible to preview hero screen when choosing a skill on levelup. + +### Hota rebalances? + +contact MikeLodz about this section + +- what is our stance on Hota rebalances ? we should discuss them at + least and decide which to adopt, and which to ignore \* + +### Random map generator + +Dydzio said about it on Slack: + +`finish `[`https://github.com/dydzio0614/vcmi/tree/rmgtemplates`](https://github.com/dydzio0614/vcmi/tree/rmgtemplates)` (random map generator template pick,` + +better selection lists for random map generator template - two versions +(two bitmaps provided) also one more thing - for random map template +pick my vision was to create more generic select list component and make +town portal select component derive from it + +### [Adventure AI](Adventure_AI "wikilink") + +- More functionality + - Adventure map spells support + - Survival instinct - AI defending towns, escaping etc. + - Handling of all adventure map objects +- Evaluating game objects + - priority for visited objects over others sharing similiar + function + - Support for new objects possible to add via mods - use abstract + interface to determine rewards etc. +- Advanced strategy + - Battle preparation (constructing suitable army & strategy) + - Expert system for Bonuses + ([Warmonger](http://forum.vcmi.eu/profile.php?mode=viewprofile&u=130)) + +### Main menu + +- Hall of Fame + +# Modding + +- Possibility for creatures to cast arbitrary spells, as in H4/H5 + +### Scripting system + +- Language support +- Synchronising scripts in multiplayer + +### Mod system + +- Adding new content + - Adventure map objects + - Battlefields + +[Forum +thread](http://forum.vcmi.eu/viewtopic.php?t=471&postdays=0&postorder=asc&start=0) + +### Wog features + +- Mithril +- ERM handling (Tow, Tow Dragon) + +# New features + +- Support for other languages files + ([Ivan](http://forum.vcmi.eu/profile.php?mode=viewprofile&u=336)) +- Support for multiple map levels +- [New map editor](http://forum.vcmi.eu/viewtopic.php?t=1139) +- Installer + +### Online game + +- Simultaneous turns +- Spectator mode +- Dedicated server mode +- [Replays](http://forum.vcmi.eu/viewtopic.php?t=264) + +### Other platforms + +- Linux (**Supported**, [forum + thread](http://forum.vcmi.eu/viewtopic.php?t=112)) +- Mac OS (**Supported**, [forum + thread](http://forum.vcmi.eu/viewtopic.php?t=439)) +- Android (**Supported**, [forum + thread](http://forum.vcmi.eu/viewtopic.php?t=850)) +- iOS (**Supported**, [forum + thread](https://forum.vcmi.eu/t/ios-port/820)) +- Haiku (**Status unknown**, [forum + thread](http://forum.vcmi.eu/viewtopic.php?t=310)) +- Maemo (**Status unknown**, [forum + thread](http://forum.vcmi.eu/viewtopic.php?t=328)) +- FreeBSD (**Status unknown**) + +# New graphics + +### New menus project and graphics + +- New stack experience menu ([forum + thread](http://forum.vcmi.eu/viewtopic.php?t=376&start=0)) +- New stack artifact dialog + +### Improved support for high resolutions + +- Auto-adjust resolution +- Moddable menus + +### New players + +- More player color graphics +- New menus + +### 32-bit graphics + +### 800 x 480 resolution + +Experimental version posted on our forum is available +[here](http://forum.vcmi.eu/viewtopic.php?t=273). \ No newline at end of file diff --git a/docs/developers/Architektura.png b/docs/developers/Architektura.png new file mode 100644 index 0000000000000000000000000000000000000000..d7af85b06a3000167e4bbf3b92853db124d5d5c0 GIT binary patch literal 5144 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 literal 0 HcmV?d00001 diff --git a/docs/developers/BattleField.png b/docs/developers/BattleField.png new file mode 100644 index 0000000000000000000000000000000000000000..90022a324e982d18cb015c6f6621c2bac7dd0bec GIT binary patch literal 138134 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�(&Tf%Xs-)_7?W1{T);=HV|16(Z;RGgQd@FLbEcD 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஑ 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 literal 0 HcmV?d00001 diff --git a/docs/developers/Bonus system.md b/docs/developers/Bonus system.md new file mode 100644 index 000000000..5acbad04c --- /dev/null +++ b/docs/developers/Bonus system.md @@ -0,0 +1,140 @@ +The bonus system of VCMI is a set of mechanisms that make handling of +different bonuses for heroes, towns, players and units easier. The +system consists of a set of nodes representing objects that can be a +source or a subject of a bonus and two directed acyclic graphs (DAGs) +representing inheritance and propagation of bonuses. Core of bonus +system is defined in HeroBonus.h file. + +Here is a brief sketch of the system (black arrows indicate the +direction of inheritance and red arrows the direction of propagation): + +
+ +
Bonus_system.png
+
+ +## Propagation and inheritance + +Each bonus originates from some node in the bonus system, and may have +propagator and limiter objects attached to it. Bonuses are shared around +as follows: + +1. Bonuses with propagator are propagated to "matching" descendants in + the red DAG - which descendants match is determined by the + propagator. Bonuses without a propagator will not be propagated. +2. Bonuses without limiters are inherited by all descendants in the + black DAG. If limiters are present, they can restrict inheritance to + certain nodes. + +Inheritance is the default means of sharing bonuses. A typical example +is an artefact granting a bonus to attack/defense stat, which is +inherited by the hero wearing it, and then by creatures in the hero's +army. + +A common limiter is by creature - e.g. the hero Eric has a specialty +that grants bonuses to attack, defense and speed, but only to griffins. + +Propagation is used when bonuses need to be shared in a different +direction than the black DAG for inheritance. E.g. Magi and Archmagi on +the battlefield reduce the cost of spells for the controlling hero. + +### Technical Details + +- Propagation is done by copying bonuses to the target nodes. This + happens when bonuses are added. +- Inheritance is done on-the-fly when needed, by traversing the black + DAG. Results are cached to improve performance. +- Whenever a node changes (e.g. bonus added), a global counter gets + increased which is used to check whether cached results are still + current. + +## Operations on the graph + +There are two basic types of operations that can be performed on the +graph: + +### Adding a new node + +When node is attached to a new black parent [1], the propagation system +is triggered and works as follows: + + +For the attached node and its all red ancestors + + +For every bonus + + +Call propagator giving the new descendant -\> then attach appropriately +bonuses to the red descendant of attached node (or the node itself). + +E.g. when a hero equips an artifact, the hero gets attached to the +artifact to inherit its bonuses. + +### Deleting an existing node + +Analogically to the adding a new node, just remove propagated bonuses +instead of adding them. Then update the hierarchy. + +E.g. when a hero removes an artifact, the hero (which became a child of +the artifact when equipping it) is removed from it. + +Note that only *propagated* bonuses need to be handled when nodes are +added or removed. *Inheritance* is done on-the-fly and thus automatic. + +## Limiters + +If multiple limiters are specified for a bonus, a child inherits the +bonus only if all limiters say that it should. + +So e.g. a list of multiple creature type limiters (with different +creatures) would ensure that no creature inherits the bonus. In such a +case, the solution is to use one bonus per creature. + +## Propagators + +## Updaters + +Updaters are objects attached to bonuses. They can modify a bonus +(typically by changing *val*) during inheritance, including bonuses that +a node "inherits" from itself, based on properties (typically level) of +the node it passes through. Which nodes update a bonus depends on the +type of updater. E.g. updaters that perform updates based on hero level +will update bonuses as the are inherited by heroes. + +The following example shows an artifact providing a bonus based on the +level of the hero that wears it: + +` "core:greaterGnollsFlail":` +` {` +` "text" : { "description" : "This mighty flail increases the attack of all gnolls under the hero's command by twice the hero's level." },` +` "bonuses" : [` +` {` +` "limiters" : [` +` {` +` "parameters" : [ "gnoll", true ],` +` "type" : "CREATURE_TYPE_LIMITER"` +` }` +` ],` +` "subtype" : "primSkill.attack",` +` "type" : "PRIMARY_SKILL",` +` "val" : 2,` +` "updater" : "TIMES_HERO_LEVEL"` +` }` +` ]` +` }` + +## Calculating the total value of a bonus + +- [List of bonus value types](List_of_bonus_value_types "wikilink") + +## Automatic generation of bonus description + +TBD + +# Notes + + + +[1] the only possibility -\> adding parent is the same as adding a child +to it \ No newline at end of file diff --git a/docs/developers/Code_structure.md b/docs/developers/Code_structure.md new file mode 100644 index 000000000..183cefdd0 --- /dev/null +++ b/docs/developers/Code_structure.md @@ -0,0 +1,213 @@ +The code of VCMI is divided into several main parts: client, server, lib +and AIs, each one in a separate binary file. + +# The big picture + +
+ +
Architektura.png
+
+ +VCMI contains three core projects: VCMI_lib (dll / so), VCMI_client +(executable) and VCMI_server (executable). [Server](Server "wikilink") +handles all [game mechanics](game_mechanics "wikilink") and events. +[Client](Client "wikilink") presents [game state](game_state "wikilink") +and events to player and collects input from him. + +During the game, we have one (and only one) server and one or more (one +for each player computer) clients. + +Important: State of the game and its mechanics are synchronized between +clients and server. All changes to the game state or mechanics must be +done by server which will send appropriate notices to clients. + +## Game state + +It's basically CGameState class object and everything that's accessible +from it: map (with objects), player statuses, game options, etc. + +## Bonus system + +One of the more important pieces of VCMI is the [bonus +system](bonus_system "wikilink"). It's described in a separate article. + +## Configuration + +Most of VCMI configuration files uses Json format and located in +"config" directory + +### [Json parser and writer](Json_parser_and_writer "wikilink") + +# Client + +## Main purposes of client + +[Client](Client "wikilink") is responsible for: + +- displaying state of game to human player +- capturing player's actions and sending requests to server +- displaying changes in state of game indicated by server + +## Rendering of graphics + +Rendering of graphics relies heavily on SDL. Currently we do not have +any wrapper for SDL internal structures and most of rendering is about +blitting surfaces using SDL_BlitSurface. We have a few function that +make rendering easier or make specific parts of rendering (like printing +text). They are places in client/SDL_Extensions and client/SDL_Framerate +(the second one contains code responsible for keeping appropriate +framerate, it should work more smart than just SDL_Delay(miliseconds)). +In rendering, Interface object system is quite helpful. Its base is +CIntObject class that is basically a base class for our library of GUI +components and other objects. + +### Video player + +Located in client/VideoHandler.cpp/.h, have several platform-specific +versions: + +- For 32-bit Windows - using original 32-bit libraries (binkw32.dll, + smackw32.dll) +- For \*nix systems - using ffmpeg libraries. +- Empty player for 64-bit Windows + +### [Primitive controls](Primitive_controls "wikilink") + +## [Adventure map interface](Adventure_map_interface "wikilink") + +TBD + +## [Town interface](Town_interface "wikilink") + +TBD + +## [Battle interface](Battle_interface "wikilink") + +# Server + +## Main purposes of server + +[Server](Server "wikilink") is responsible for: + +- maintaining state of the game +- handling requests from all clients participating in game +- informing all clients about changes in state of the game that are + visible to them + +# Lib + +## Main purposes of lib + +VCMI_Lib is a library that contains code common to server and client, so +we avoid it's duplication. Important: the library code is common for +client and server and used by them, but the library instance (in +opposition to the library as file) is not shared by them! Both client +and server create their own "copies" of lib with all its class +instances. + +iOS platform pioneered single process build, where server is a static +library and not a dedicated executable. For that to work, the lib had to +be wrapped into special namespace that is defined by client and server +targets on iOS, so that single process is able to contain 2 versions of +the library. To make it more convenient, a few macros were introduced +that can be found in +[Global.h](https://github.com/vcmi/vcmi/blob/develop/Global.h). The most +important ones are `VCMI_LIB_NAMESPACE_BEGIN` and +`VCMI_LIB_NAMESPACE_END` which must be used anywhere a symbol from the +lib is needed, otherwise building iOS (or any other platform that would +use single process approach) fails. See [#Wrapped namespace +examples](#Wrapped_namespace_examples "wikilink"). + +[Lib](Lib "wikilink") contains code responsible for: + +- handling most of Heroes III files (.lod, .txt setting files) +- storing information common to server and client like state of the + game +- managing armies, buildings, artifacts, spells, bonuses and other + game objects +- handling general game mechanics and related actions (only adventure + map objects; it's an unwanted remnant of past development - all game + mechanics should be handled by the server) +- networking and serialization + +### [Serialization](Serialization "wikilink") + +The serialization framework can serialize basic types, several standard +containers among smart pointers and custom objects. Its design is based +on the [boost serialization +libraries](http://www.boost.org/doc/libs/1_52_0/libs/serialization/doc/index.html). +In addition to the basic functionality it provides light-weight transfer +of CGObjectInstance objects by sending only the index/id. + +See the [Serialization](Serialization "wikilink") page for all the +details. + +### Wrapped namespace examples + +#### Inside the lib + +Both header and implementation of a new class inside the lib should have +the following structure: + +`` +`VCMI_LIB_NAMESPACE_BEGIN` +`` +`VCMI_LIB_NAMESPACE_END` + +Example: +[header](https://github.com/vcmi/vcmi/blob/develop/lib/CBuildingHandler.h) +and +[implementation](https://github.com/vcmi/vcmi/blob/develop/lib/CBuildingHandler.cpp) + +#### Headers outside the lib + +Forward declarations of the lib in headers of other parts of the project +need to be wrapped in the macros: + +`` +`VCMI_LIB_NAMESPACE_BEGIN` +`` +`VCMI_LIB_NAMESPACE_END` +`` +`` + +Example: + + +#### New project part + +If you're creating new project part, place `VCMI_LIB_USING_NAMESPACE` in +its `StdInc.h` to be able to use lib classes without explicit namespace +in implementation files. Example: + + +# [Artificial Intelligence](Artificial_Intelligence "wikilink") (AI) + +## [StupidAI](StupidAI "wikilink") + +Stupid AI is recent and used battle AI. + +## [Adventure AI](Adventure_AI "wikilink") + +VCAI module is currently developed agent-based system driven by goals +and heroes. + +## [Programming challenge](Programming_challenge "wikilink") + +## [Fuzzy logic](Fuzzy_logic "wikilink") + +VCMI includes [FuzzyLite](http://code.google.com/p/fuzzy-lite/) library +to make use of fuzzy rule-based algorithms. They are useful to handle +uncertanity and resemble human behaviour who takes decisions based on +rough observations. FuzzyLite is linked as separate static library in +AI/FuzzyLite.lib file. + +# [Utilities](Utilities "wikilink") + +## [Launcher](Launcher "wikilink") + +## [Duels](Duels "wikilink") + +[Mod system proposal](Mod_system_proposal "wikilink") + +## [ERM parser](ERM_parser "wikilink") \ No newline at end of file diff --git a/docs/developers/Coding Guidelines.md b/docs/developers/Coding Guidelines.md new file mode 100644 index 000000000..389ce70d1 --- /dev/null +++ b/docs/developers/Coding Guidelines.md @@ -0,0 +1,972 @@ +## C++ Standard + +VCMI implementation bases on C++14 standard. Any feature is acceptable +as long as it's will pass build on our CI, but there is list below on +what is already being used. + +Any compiler supporting C++14 should work, but this has not been +thoroughly tested. You can find information about extensions and +compiler support at +[1](http://en.cppreference.com/w/cpp/compiler_support). + +## Style Guidelines + +In order to keep the code consistent, please use the following +conventions. From here on \`good' and \`bad' are used to attribute +things that would make the coding style match, or not match. It is not a +judgment call on your coding abilities, but more of a style and look +call. Please try to follow these guidelines to ensure prettiness. + +### Indentation + +Use tabs for indentation. If you are modifying someone else's code, try +to keep the coding style similar. + +### Where to put braces + +Inside a code block put the opening brace on the next line after the +current statement: + +Good: + +``` cpp +if(a) +{ + code(); + code(); +} +``` + +Bad: + +``` cpp +if(a) { + code(); + code(); +} +``` + +Avoid using unnecessary open/close braces, vertical space is usually +limited: + +Good: + +``` cpp +if(a) + code(); +``` + +Bad: + +``` cpp +if(a) { + code(); +} +``` + +Unless there are either multiple hierarchical conditions being used or +that the condition cannot fit into a single line. + +Good: + +``` cpp +if(a) +{ + if(b) + code(); +} +``` + +Bad: + +``` cpp +if(a) + if(b) + code(); +``` + +If there are brackets inside the body, outside brackets are required. + +Good: + +``` cpp +if(a) +{ + for(auto elem : list) + { + code(); + } +} +``` + +Bad: + +``` cpp +if(a) + for(auto elem : list) + { + code(); + } +``` + +If "else" branch has brackets then "if" should also have brackets even +if it is one line. + +Good: + +``` cpp +if(a) +{ + code(); +} +else +{ + for(auto elem : list) + { + code(); + } +} +``` + +Bad: + +``` cpp +if(a) + code(); +else +{ + for(auto elem : list) + { + code(); + } +} +``` + +If you intentionally want to avoid usage of "else if" and keep if body +indent make sure to use braces. + +Good: + +``` cpp +if(a) +{ + code(); +} +else +{ + if(b) + code(); +} +``` + +Bad: + +``` cpp +if(a) + code(); +else + if(b) + code(); +``` + +When defining a method, use a new line for the brace, like this: + +Good: + +``` cpp +void method() +{ +} +``` + +Bad: + +``` cpp +void Method() { +} +``` + +### Use whitespace for clarity + +Use white space in expressions liberally, except in the presence of +parenthesis. + +**Good:** + +``` cpp +if(a + 5 > method(blah('a') + 4)) + foo += 24; +``` + +**Bad:** + +``` cpp +if(a+5>method(blah('a')+4)) +foo+=24; +``` + +Between if, for, while,.. and the opening brace there shouldn't be a +whitespace. The keywords are highlighted, so they don't need further +separation. + +### Where to put spaces + +Use a space before and after the address or pointer character in a +pointer declaration. + +Good: + +``` cpp +CIntObject * images[100]; +``` + +Bad: + +``` cpp +CIntObject* images[100]; or +CIntObject *images[100]; +``` + +Do not use spaces before parentheses. + +Good: + +``` cpp +if(a) + code(); +``` + +Bad: + +``` cpp +if (a) + code(); +``` + +Do not use extra spaces around conditions inside parentheses. + +Good: + +``` cpp +if(a && b) + code(); + +if(a && (b || c)) + code(); +``` + +Bad: + +``` cpp +if( a && b ) + code(); + +if(a && ( b || c )) + code(); +``` + +Do not use more than one space between operators. + +Good: + +``` cpp +if((a && b) || (c + 1 == d)) + code(); +``` + +Bad: + +``` cpp +if((a && b) || (c + 1 == d)) + code(); + +if((a && b) || (c + 1 == d)) + code(); +``` + +### Where to use parentheses + +When allocating objects, don't use parentheses for creating stack-based +objects by zero param c-tors to avoid c++ most vexing parse and use +parentheses for creating heap-based objects. + +Good: + +``` cpp +std::vector v; +CGBoat btn = new CGBoat(); +``` + +Bad: + +``` cpp +std::vector v(); // shouldn't compile anyway +CGBoat btn = new CGBoat; +``` + +Avoid overuse of parentheses: + +Good: + +``` cpp +if(a && (b + 1)) + return c == d; +``` + +Bad: + +``` cpp +if((a && (b + 1))) + return (c == d); +``` + +### Class declaration + +Base class list must be on same line with class name. + +``` cpp +class CClass : public CClassBaseOne, public CClassBaseOne +{ + int id; + bool parameter; + +public: + CClass(); + ~CClass(); +}; +``` + +When 'private:', 'public:' and other labels are not on the line after +opening brackets there must be a new line before them. + +Good: + +``` cpp +class CClass +{ + int id; + +public: + CClass(); +}; +``` + +Bad: + +``` cpp +class CClass +{ + int id; +public: + CClass(); +}; +``` + +Good: + +``` cpp +class CClass +{ +protected: + int id; + +public: + CClass(); +}; +``` + +Bad: + +``` cpp +class CClass +{ + +protected: + int id; + +public: + CClass(); +}; +``` + +### Constructor base class and member initialization + +Constructor member and base class initialization must be on new line, +indented with tab with leading colon. + +``` cpp +CClass::CClass() + : CClassBaseOne(true, nullptr), id(0), bool parameters(false) +{ + code(); +} +``` + +### Switch statement + +Switch statements have the case at the same indentation as the switch. + +Good: + +``` cpp +switch(alignment) +{ +case EAlignment::EVIL: + do_that(); + break; +case EAlignment::GOOD: + do_that(); + break; +case EAlignment::NEUTRAL: + do_that(); + break; +default: + do_that(); + break; +} +``` + +Bad: + +``` cpp +switch(alignment) +{ + case EAlignment::EVIL: + do_that(); + break; + default: + do_that(); + break; +} + +switch(alignment) +{ + case EAlignment::EVIL: + do_that(); + break; + default: + do_that(); + break; +} + +switch(alignment) +{ +case EAlignment::EVIL: +{ + do_that(); +} +break; +default: +{ + do_that(); +} +break; +} +``` + +### Lambda expressions + +Good: + +``` cpp +auto lambda = [this, a, &b](int3 & tile, int index) -> bool +{ + do_that(); +}; +``` + +Bad: + +``` cpp +auto lambda = [this,a,&b](int3 & tile, int index)->bool{do_that();}; +``` + +Empty parameter list is required even if function takes no arguments. + +Good: + +``` cpp +auto lambda = []() +{ + do_that(); +}; +``` + +Bad: + +``` cpp +auto lambda = [] +{ + do_that(); +}; +``` + +Do not use inline lambda expressions inside if-else, for and other +conditions. + +Good: + +``` cpp +auto lambda = []() +{ + do_that(); +}; +if(lambda) +{ + code(); +} +``` + +Bad: + +``` cpp +if([]() +{ + do_that(); +}) +{ + code(); +} +``` + +Do not pass inline lambda expressions as parameter unless it's the last +parameter. + +Good: + +``` cpp +auto lambda = []() +{ + do_that(); +}; +obj->someMethod(lambda, true); +``` + +Bad: + +``` cpp +obj->someMethod([]() +{ + do_that(); +}, true); +``` + +Good: + +``` cpp +obj->someMethod(true, []() +{ + do_that(); +}); +``` + +### Serialization + +Serialization of each element must be on it's own line since this make +debugging easier. + +Good: + +``` cpp +template void serialize(Handler & h, const int version) +{ + h & identifier; + h & description; + h & name; + h & dependencies; +} +``` + +Bad: + +``` cpp +template void serialize(Handler & h, const int version) +{ + h & identifier & description & name & dependencies; +} +``` + +Save backward compatibility code is exception when extra brackets are +always useful. + +Good: + +``` cpp +template void serialize(Handler & h, const int version) +{ + h & identifier; + h & description; + if(version >= 123) + { + h & totalValue; + } + else if(!h.saving) + { + totalValue = 200; + } + h & name; + h & dependencies; +} +``` + +Bad: + +``` cpp +template void serialize(Handler & h, const int version) +{ + h & identifier; + h & description; + if(version >= 123) + h & totalValue; + else if(!h.saving) + totalValue = 200; + h & name; + h & dependencies; +} +``` + +### File headers + +For any new files, please paste the following info block at the very top +of the source file: + +``` cpp +/* + * Name_of_File.h, part of VCMI engine + * + * Authors: listed in file AUTHORS in main folder + * + * License: GNU General Public License v2.0 or later + * Full text of license available in license.txt file, in main folder + * + */ +``` + +The above notice have to be included both in header and source files +(.h/.cpp). + +### Code order in files + +For any header or source file code must be in following order: + +1. Licensing information +2. pragma once preprocessor directive +3. include directives +4. Forward declarations +5. All other code + +``` cpp +/* + * Name_of_File.h, part of VCMI engine + * + * Authors: listed in file AUTHORS in main folder + * + * License: GNU General Public License v2.0 or later + * Full text of license available in license.txt file, in main folder + * + */ +#pragma once + +#include "Header.h" + +class CGObjectInstance; +struct CPackForClient; +``` + +### Where and how to comment + +If you comment on the same line with code there must be one single space +between code and slashes. + +Good: + +``` cpp +if(a) +{ + code(); //Do something +} +else // Do something. +{ + code(); // Do something. +} +``` + +Bad: + +``` cpp +if(a) +{ + code();//Do something +} +else // Do something. +{ + code(); // TODO: +} +``` + +If you add single-line comment on own line slashes must have same indent +as code around: + +Good: + +``` cpp +// Do something +if(a) +{ + //Do something + for(auto item : list) + code(); +} +``` + +Bad: + +``` cpp + // Do something +if(a) +{ +//Do something + for(auto item : list) + code(); +} +``` + +Avoid comments inside multi-line if-else conditions. If your conditions +are too hard to understand without additional comments this usually +means that code need refactoring. Example given below is need +improvement though. **FIXME** + +Good: + +``` cpp +bool isMyHeroAlive = a && b || (c + 1 > 15); +bool canMyHeroMove = myTurn && hero.movePoints > 0; +if(isMyHeroAlive && canMyHeroMove) +{ + code(); +} +``` + +Bad: + +``` cpp +if((a && b || (c + 1 > 15)) //Check if hero still alive + && myTurn && hero.movePoints > 0) //Check if hero can move +{ + code(); +} +``` + +You should write a comment before the class definition which describes +shortly the class. 1-2 sentences are enough. Methods and class data +members should be commented if they aren't self-describing only. +Getters/Setters, simple methods where the purpose is clear or similar +methods shouldn't be commented, because vertical space is usually +limited. The style of documentation comments should be the three +slashes-style: ///. + +``` cpp +/// Returns true if a debug/trace log message will be logged, false if not. +/// Useful if performance is important and concatenating the log message is a expensive task. +bool isDebugEnabled() const; +bool isTraceEnabled() const; +``` + +The above example doesn't follow a strict scheme on how to comment a +method. It describes two methods in one go. Comments should be kept +short. + +If you need a more detailed description for a method you can use such +style: + +``` cpp +///
+/// +/// +/// +/// +/// @param Description of method's or function's input parameter +/// @param ... +/// @return Description of the return value +``` + +A good essay about writing comments: +[2](http://ardalis.com/when-to-comment-your-code) + +### Casing + +Local variables and methods start with a lowercase letter and use the +camel casing. Classes/Structs start with an uppercase letter and use the +camel casing as well. Macros and constants are written uppercase. + +### Line length + +The line length for c++ source code is 120 columns. If your function +declaration arguments go beyond this point, please align your arguments +to match the opening brace. For best results use the same number of tabs +used on the first line followed by enough spaces to align the arguments. + +### Warnings + +Avoid use of #pragma to disable warnings. Compile at warning level 3. +Avoid commiting code with new warnings. + +### File/directory naming + +Compilation units(.cpp,.h files) start with a uppercase letter and are +named like the name of a class which resides in that file if possible. +Header only files start with a uppercase letter. JSON files start with a +lowercase letter and use the camel casing. + +Directories start with a lowercase letter and use the camel casing where +necessary. + +### Logging + +Outdated. There is separate entry for [Logging +API](Logging_API "wikilink") + +If you want to trace the control flow of VCMI, then you should use the +macro LOG_TRACE or LOG_TRACE_PARAMS. The first one prints a message when +the function is entered or leaved. The name of the function will also be +logged. In addition to this the second macro, let's you specify +parameters which you want to print. You should print traces with +parameters like this: + +``` cpp +LOG_TRACE_PARAMS(logGlobal, "hero '%s', spellId '%d', pos '%s'.", hero, spellId, pos); +``` + +When using the macro every "simple" parameter should be logged. The +parameter can be a number, a string or a type with a ostream +operator\<\<. You should not log contents of a whole text file, a byte +array or sth. like this. If there is a simple type with a few members +you want to log, you should write an ostream operator\<\<. The produced +message can look like this: + +`{BattleAction: side '0', stackNumber '1', actionType 'Walk and attack', destinationTile '{BattleHex: x '7', y '1', hex '24'}', additionalInfo '7', selectedStack '-1'}` + +The name of the type should be logged first, e.g. {TYPE_NAME: +members...}. The members of the object will be logged like logging trace +parameters. Collection types (vector, list, ...) should be logged this +way: \[{BattleHex: ...}, {...}\] There is no format which has to be +followed strictly, so if there is a reason to format members/objects in +a different way, then this is ok. + +## Best practices + +### Avoid code duplication + +Avoid code duplication or don't repeat yourself(DRY) is the most +important aspect in programming. Code duplication of any kind can lead +to inconsistency and is much harder to maintain. If one part of the +system gets changed you have to change the code in several places. This +process is error-prone and leads often to problems. Here you can read +more about the DRY principle: +[](http://en.wikipedia.org/wiki/Don%27t_repeat_yourself) + +### Do not use uncommon abbrevations + +Do not use uncommon abbrevations for class, method, parameter and global +object names. + +Bad: + +``` cpp +CArt * getRandomArt(...) +class CIntObject +``` + +Good: + +``` cpp +CArtifact * getRandomArtifact(...) +class CInterfaceObject +``` + +### Loop handling + +Use range-based for loops. It should be used in any case except you +absolutely need iterator, then you may use a simple for loop. + +The loop counter should be of type int, unless you are sure you won't +need negative indices -- then use size_t. + +### Include guards + +Use #pragma once instead of the traditional #ifndef/#define/#endif +include guards. + +### Pre compiled header file + +The header StdInc.h should be included in every compilation unit. It has +to be included before any C macro and before any c++ statements. Pre +compiled header should not be changed, except any important thing is +missing. The StdInc includes most Boost libraries and nearly all +standard STL and C libraries, so you don’t have to include them by +yourself. + +### Enumeration handling + +Do not declare enumerations in global namespace. It is better to use +strongly typed enum or to wrap them in class or namespace to avoid +polluting global namespace: + +``` cpp +enum class EAlignment +{ + GOOD, + EVIL, + NEUTRAL +}; + +namespace EAlignment +{ + enum EAlignment + { + GOOD, EVIL, NEUTRAL + }; +} +``` + +### Avoid senseless comments + +If the comment duplicates the name of commented member, it's better if +it wouldn't exist at all. It just increases maintenance cost. Bad: + +``` cpp +size_t getHeroesCount(); //gets count of heroes (surprise?) +``` + +### Class handling + +There is no definitive rule which has to be followed strictly. You can +freely decide if you want to pack your own classes, where you are +programming on, all in one file or each in one file. It's more important +that you feel comfortable with the code, than consistency overall the +project. VCMI has several container class files, so if you got one +additional class to them than just add it to them instead of adding new +files. + +### Functions and interfaces + +Don't return const objects or primitive types from functions -- it's +pointless. Also, don't return pointers to non-const game data objects +from callbacks to player interfaces. + +Bad: + +``` cpp +const std::vector guardingCreatures(int3 pos) const; +``` + +Good: + +``` cpp +std::vector guardingCreatures(int3 pos) const; +``` + +## Sources + +[Mono project coding +guidelines](http://www.mono-project.com/Coding_Guidelines) \ No newline at end of file diff --git a/docs/developers/Development_with_Qt_Creator.md b/docs/developers/Development_with_Qt_Creator.md new file mode 100644 index 000000000..756ecab5e --- /dev/null +++ b/docs/developers/Development_with_Qt_Creator.md @@ -0,0 +1,49 @@ +# Introduction to Qt Creator + +Qt Creator is the recommended IDE for VCMI development on Linux +distributions, but it may be used on other operating systems as well. It +has the following advantages compared to other IDEs: + +- Fast parser/indexer, stable. +- Almost no manual configuration when used with CMake. Project + configuration is read from CMake text files, +- Easy to setup and use with multiple different compiler toolchains: + GCC, Visual Studio, Clang + +You can install Qt Creator from repository, but better to stick to +latest version from Qt website: + + +## Configuration + +To open the project you have to click File -\> Open file or project... +-\> Select /path/to/vcmi/src/CMakeLists.txt. + +For the first time and for every CMake project configuration change you +have to execute CMake. This step can be done when opening the project +for the first time or alternatively via the left bar -\> Projects -\> +Build Settings -\> Execute CMake. You have to specify CMake arguments +and the build dir. CMake arguments can be the following: + + -DCMAKE_BUILD_TYPE=Debug + +The build dir should be set to something like /trunk/build for the debug +build and /trunk/buildrel for the release build. For cleaning the build +dir a command like "make clean" may be not enough. Better way is to +delete the build dir, re-create it and re-execute CMake. Steps for +cleaning can be configured in the Projects tab as well. + +## Debugging + +There is a problem with QtCreator when debugging both vcmiclient and +vcmiserver. If you debug the vcmiclient, start a game, attach the +vcmiserver process to the gdb debugger(Debug \> Start Debugging \> +Attach to Running External Application...) then breakpoints which are +set for vcmiserver will be ignored. This looks like a bug, in any case +it's not intuitively. Two workarounds are available luckily: + +1\) Run vcmiclient (no debug mode), then attach server process to the +debugger + +2\) Open two instances of QtCreator and debug vcmiserver and vcmiclient +separately(it works!) \ No newline at end of file diff --git a/docs/developers/How to build VCMI (Android).md b/docs/developers/How to build VCMI (Android).md new file mode 100644 index 000000000..6b25355cd --- /dev/null +++ b/docs/developers/How to build VCMI (Android).md @@ -0,0 +1,117 @@ +The following instructions apply to **v1.2 and later**. For earlier +versions the best documentation is + (and +reading scripts in that repo), however very limited to no support will +be provided from our side if you wish to go down that rabbit hole. + +*Note*: building has been tested only on Linux and macOS. It may or may +not work on Windows out of the box. + +## Requirements + +1. CMake 3.20+: download from your package manager or from + +2. JDK 11, not necessarily from Oracle +3. Android command line tools or Android Studio for your OS: + +4. Android NDK version **r25c (25.2.9519653)**, there're multiple ways + to obtain it: + - install with Android Studio + - install with `sdkmanager` command line tool + - download from + - download with Conan, see [#NDK and + Conan](#NDK_and_Conan "wikilink") +5. (optional) Ninja: download from your package manager or from + + +## Obtaining source code + +Clone with submodules. Example for +command line: + +`git clone --recurse-submodules https://github.com/vcmi/vcmi.git` + +## Obtaining dependencies + +We use Conan package manager to build/consume dependencies, find +detailed usage instructions +[here](https://github.com/vcmi/vcmi/tree/develop/docs/conan.md). Note +that the link points to the cutting-edge state in `develop` branch, for +the latest release check the same document in the [master +branch](https://github.com/vcmi/vcmi/tree/master/docs/conan.md). + +On the step where you need to replace **PROFILE**, choose: + +- `android-32` to build for 32-bit architecture (armeabi-v7a) +- `android-64` to build for 64-bit architecture (aarch64-v8a) + +### NDK and Conan + +Conan must be aware of the NDK location when you execute +`conan install`. There're multiple ways to achieve that as written in +the [Conan +docs](https://docs.conan.io/1/integrations/cross_platform/android.html): + +- the easiest is to download NDK from Conan (option 1 in the docs), + then all the magic happens automatically. You need to create your + own Conan profile that imports our Android profile and adds 2 new + lines (you can of course just copy everything from our profile into + yours without including) and then pass this new profile to + `conan install`: + +`include(/path/to/vcmi/CI/conan/android-64)` +`[tool_requires]` +`android-ndk/r25c` + +- to use an already installed NDK, you can simply pass it on the + command line to `conan install`: + +`conan install -c tools.android:ndk_path=/path/to/ndk ...` + +## Build process + +Building for Android is a 2-step process. First, native C++ code is +compiled to a shared library (unlike executable on other platforms), +then Java code is compiled to an actual executable which will be loading +the native shared library at runtime. + +### C++ code + +This is a traditional CMake project, you can build it from command line +or some IDE. You're not required to pass any custom options (except +Conan toolchain file), defaults are already good. If you wish to use +your own CMake presets, inherit them from our `build-with-conan` preset. +Example: + +`cmake -S . -B ../build -G Ninja -D CMAKE_BUILD_TYPE=Debug --toolchain ...` +`cmake --build ../build` + +You can also see a more detailed walkthrough on CMake configuration at +[How to build VCMI (macOS)#Configuring project for +building](How_to_build_VCMI_(macOS)#Configuring_project_for_building "wikilink"). + +### Java code + +After the C++ part is built, native shared libraries are copied to the +appropriate location of the Java project (they will be packaged in the +APK). You can either open the Java project located in `android` +directory of the repo in Android studio and work with it as with any +Android project or build from command line. + +Example how to build from command line in Bash shell, assumes that +current working directory is VCMI repository: + +`# the following environment variables must be set` +`export JAVA_HOME=/path/to/jdk11` +`export ANDROID_HOME=/path/to/android/sdk` +`` +`cd android` +`./gradlew assembleDebug` + +APK will appear in `android/vcmi-app/build/outputs/apk/debug` directory +which you can then install to your device with +`adb install -r /path/to/apk` (adb command is from Android command line +tools). + +If you wish to build and install to your device in single action, use +`installDebug` instead of `assembleDebug`. \ No newline at end of file diff --git a/docs/developers/How to build VCMI (Linux).md b/docs/developers/How to build VCMI (Linux).md new file mode 100644 index 000000000..f9e51b3d3 --- /dev/null +++ b/docs/developers/How to build VCMI (Linux).md @@ -0,0 +1,217 @@ +# Compiling VCMI + +- Current baseline requirement for building is Ubuntu 20.04 +- Supported C++ compilers for UNIX-like systems are GCC 5.5+ and Clang + 13+ + +Older distributions and compilers might work, but they aren't tested by +[Travis CI](https://travis-ci.org/vcmi/vcmi/) + +# Installing dependencies + +## Prerequisites + +To compile, the following packages (and their development counterparts) +are needed to build: + +- CMake 3.10 or newer +- SDL2 with devel packages: mixer, image, ttf +- zlib and zlib-devel +- Recommended, if you want to build launcher or map editor: Qt 5, + widget and network modules +- Recommended, FFmpeg libraries, if you want to watch in-game videos: + libavformat and libswscale. Their name could be libavformat-devel + and libswscale-devel, or ffmpeg-libs-devel or similar names. +- Boost C++ libraries v1.48+: program-options, filesystem, system, + thread, locale +- Optional, if you want to build scripting modules: LuaJIT + +## On Debian-based systems (e.g. Ubuntu) + +For Ubuntu 22.04 (jammy) or newer you need to install this list of +packages, including **libtbb2-dev**: + + sudo apt-get install cmake g++ libsdl2-dev libsdl2-image-dev libsdl2-ttf-dev libsdl2-mixer-dev zlib1g-dev libavformat-dev libswscale-dev libboost-dev libboost-filesystem-dev libboost-system-dev libboost-thread-dev libboost-program-options-dev libboost-locale-dev qtbase5-dev libtbb2-dev libluajit-5.1-dev qttools5-dev + +For Ubuntu 21.10 (impish) or older and all versions of Debian (9 +stretch - 11 bullseye) you need to install this list of packages, +including **libtbb-dev**: + + sudo apt-get install cmake g++ libsdl2-dev libsdl2-image-dev libsdl2-ttf-dev libsdl2-mixer-dev zlib1g-dev libavformat-dev libswscale-dev libboost-dev libboost-filesystem-dev libboost-system-dev libboost-thread-dev libboost-program-options-dev libboost-locale-dev qtbase5-dev libtbb-dev libluajit-5.1-dev qttools5-dev + +Alternatively if you have VCMI installed from repository or PPA you can +use: + + sudo apt-get build-dep vcmi + +## On RPM-based distributions (e.g. Fedora) + + sudo yum install cmake gcc-c++ SDL2-devel SDL2_image-devel SDL2_ttf-devel SDL2_mixer-devel boost boost-devel boost-filesystem boost-system boost-thread boost-program-options boost-locale zlib-devel ffmpeg-devel ffmpeg-libs qt5-qtbase-devel tbb-devel luajit-devel fuzzylite-devel + +## On Arch-based distributions + +On Arch-based distributions, there is a development package available +for VCMI on the AUR. + +It can be found at: + +Information about building packages from the Arch User Repository (AUR) +can be found at the Arch wiki. + +## Manual Installation + +For older OS versions the latest prerequisite packages may not be +readily available via the system installer. Some brief instructions for +manual install are given below (tested on Ubuntu 14.04, update version +numbers as desired). + +- CMake (see also + ) + + + + wget https://cmake.org/files/v3.11/cmake-3.11.0.tar.gz + tar xfz cmake-3.11.0.tar.gz + cd cmake-3.11.0 + ./bootstrap + make -j2 + sudo checkinstall --pkgname cmake --pkgversion 3.11.0 -y + +Note: Will only be visible in new terminals. Test with cmake --version. + +- Boost (see also ) + + + + wget https://dl.bintray.com/boostorg/release/1.66.0/source/boost_1_66_0.tar.gz + tar xfz boost_1_66_0.tar.gz + cd boost_1_66_0 + ./bootstrap.sh --with-libraries=program-options,filesystem,system,thread,locale + ./b2 + sudo ./b2 install + +Note: Boost 1.66.0 produces a bug in asio.hpp when used with old gcc +versions (see ). + +- GCC (for Ubuntu - compile from source is lengthy) + + + + sudo add-apt-repository ppa:ubuntu-toolchain-r/test + sudo apt-get update + sudo apt-get install gcc-7 g++-7 + sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-7 70 --slave /usr/bin/g++ g++ /usr/bin/g++-7 + +Note: Test with gcc --version (and g++ --version). + +- Clang (for Ubuntu 14.04 - for later versions first line is not + needed, and 'trusty' should be replaced with version name) + + + + sudo add-apt-repository ppa:ubuntu-toolchain-r/test + sudo add-apt-repository "deb http://apt.llvm.org/trusty/ llvm-toolchain-trusty-6.0 main" + sudo apt-get update + sudo apt-get install clang-6.0 + sudo update-alternatives --install /usr/bin/clang clang /usr/bin/clang-6.0 60 --slave /usr/bin/clang++ clang++ /usr/bin/clang++-6.0 + +Note: Test with clang --version (and clang++ --version). + +# Getting the sources + +VCMI is still in development. We recommend the following initial +directory structure: + + . + ├── vcmi -> contains sources and is under git control + └── build -> contains build output, makefiles, object files,... + +You can get latest sources with: + + git clone -b develop --recursive https://github.com/vcmi/vcmi.git + +# Compilation + +## Configuring Makefiles + + mkdir build && cd build + cmake ../vcmi + + # Additional options that you may want to use: + ## To enable debugging: + cmake ../vcmi -DCMAKE_BUILD_TYPE=Debug + +**Notice**: The ../vcmi/ is not a typo, it will place makefile scripts +into the build dir as the build dir is your working dir when calling +CMake. + +## Trigger build + + cmake --build . -- -j2 + # -j2 = compile with 2 threads, you can specify any value + +That will generate vcmiclient, vcmiserver, vcmilauncher as well as 4 .so +libraries in **build/bin/** directory. + +# Package building + +## RPM package + +The first step is to prepare a RPM build environment. On Fedora systems +you can follow this guide: + + +1\. Download the file rpm/vcmi.spec from any tagged VCMI release for +which you wish to build a RPM package via the SVN Browser trac at this +URL for example(which is for VCMI 0.9): + + +2\. Copy the file to ~/rpmbuild/SPECS + +3\. Follow instructions in the vcmi.spec. You have to export the +corresponding SVN tag, compress it to a g-zipped archive and copy it to +~/rpmbuild/SOURCES. Instructions are written as comments and you can +copy/paste commands into terminal. + +4\. Go to ~/rpmbuild/SPECS and open terminal in this folder and type: + + rpmbuild -ba vcmi.spec (this will build rpm and source rpm) + +5\. Generated RPM is in folder ~/rpmbuild/RPMS + +If you want to package the generated RPM above for different processor +architectures and operating systems you can use the tool mock. Moreover, +it is necessary to install mock-rpmfusion_free due to the packages +ffmpeg-devel and ffmpeg-libs which aren't available in the standard RPM +repositories(at least for Fedora). Go to ~/rpmbuild/SRPMS in terminal +and type: + + mock -r fedora-17-i386-rpmfusion_free path_to_source_RPM + mock -r fedora-17-x86_64-rpmfusion_free path_to_source_RPM + +Available root environments and their names are listed in /etc/mock. + +## Debian/Ubuntu + +1\. Install debhelper and devscripts packages + +2\. Run dpkg-buildpackage command from vcmi source directory + + sudo apt-get install debhelper devscripts + cd /path/to/source + dpkg-buildpackage + +To generate packages for different architectures see "-a" flag of +dpkg-buildpackage command + +## Documentation + +To compile using Doxygen, the UseDoxygen CMake module must be installed. +It can be fetched from: + +Once UseDoxygen is installed, run: + + cmake . + make doc + +The built documentation will be available from ./doc \ No newline at end of file diff --git a/docs/developers/How to build VCMI (Visual Studio 2015).md b/docs/developers/How to build VCMI (Visual Studio 2015).md new file mode 100644 index 000000000..990409849 --- /dev/null +++ b/docs/developers/How to build VCMI (Visual Studio 2015).md @@ -0,0 +1,165 @@ +**Warning!** VCMI project only officially support building with CMake: +[How to build VCMI +(Windows/Vcpkg)](How_to_build_VCMI_(Windows/Vcpkg) "wikilink"). + +Guide below and VS solution found in source tree might be broken and not +automatically tested. Use at your own risk only if you know what you're +doing. + +# Prerequisites + +- Installed Heroes3 (can be bought for $10 at + [gog.com](http://www.gog.com/en/gamecard/heroes_of_might_and_magic_3_complete_edition/)) +- Optionally, you can have also WoG or ERA installed. +- IDE: + - Microsoft Visual Studio 2015 (Community Edition recommended - it + is free for non-commercial use). Earlier version support is + deprecated and project may not compile anymore with them. +- Git client: + - Visual Studio 2015 has built-in Git support. It isn't complete, + but having most important Git commands integrated in IDE is very + convienent. Additional GitHub extension for Visual Studio + [1](https://visualstudio.github.com/) gives few more features + that may be useful. + - Alternatively, you can use another Git client with better Git + support, for example Sourcetree + [2](https://www.sourcetreeapp.com/) +- Libraries used by VCMI - where to get them will be explained later + in this tutorial + - Boost + - SDL2 + - SDL2_image + - SDL2_mixer + - SDL2_TTF + - FFmpeg + - zlib + - QT 5 (only used to compile VCMI launcher, which does not have to + be rebuilt to test another VCMI parts) + +# Preparing place + +## Initial directory structure + +Create a directory for VCMI development, eg. C:\VCMI. It will be base +directory for VCMI source code. + +It is recommended to avoid non-ascii characters in the path to your VCMI +development folder. The folder should not be write-protected by system. +Good location: + +- C:\VCMI + +Bad locations: + +- C:\Users\Michał\VCMI (non-ascii character) +- C:\Program Files (x86)\VCMI (write protection) + +## Obtaining VCMI sources + +### Using Sourcetree (version 1.9.6.1) + +- Click "Clone / New" button in upper left part of the program +- Make sure you are in first tab (Clone Repository). In "Source Path / + URL:" type following link: +- Set "Destination Path" field to directory desired for VCMI + development and press "Clone" button. + +Now you have the local copy of the repository on the disk. It should +appear in the Team Explorer under the "Local Git Repositories" section. +Double click it and then select a solution to open. + +# Getting Libraries + +This section will show ways to get up-to-date versions of libraries +required to build VCMI. When you have a choice if you want 32 or 64 bit +version of library - choosing 32 bit will make things easier as you will +not have to do additional configuration in Visual Studio to switch to 64 +bit etc. + +## Boost + +- Header files with extra things can be obtained from boost website + download: [3](http://www.boost.org/users/download/) +- To avoid rebuilding boost from sources, you can download prebuilt + windows binaries (lib files) from there as well. MSVC 14 binaries + are for Visual Studio 2015. + +UPDATE: Somebody reported problem with boost newer than 1.62 when trying +to build VCMI. To get all boost 1.62 required files use these links: +[4](https://sourceforge.net/projects/boost/files/boost/1.62.0/boost_1_62_0.7z/download) +[5](https://sourceforge.net/projects/boost/files/boost-binaries/1.62.0/boost_1_62_0-msvc-14.0-32.exe/download) + +## SDL2 and sublibraries + +- You can get SDL2 from [6](http://libsdl.org/download-2.0.php) - + download development libraries to get lib and header files +- Similar to SDL2 package you can get SDL2_image from + [7](https://www.libsdl.org/projects/SDL_image/), SDL2_mixer from + [8](https://www.libsdl.org/projects/SDL_mixer/), SDL2_ttf from + [9](https://www.libsdl.org/projects/SDL_ttf/). + +## FFmpeg + +- You can get this library from + [10](https://ffmpeg.zeranoe.com/builds/). Both header and lib files + are available if you choose "dev" download version. + +## zlib + +- most tricky to get - use NuGet package manager that is part of + Visual Studio 2015 to get it. Link in NuGet gallery: + [11](https://www.nuget.org/packages/zlib/) + +## QT 5 + +- (TO BE ADDED) + +# Compiling VCMI + +To compile VCMI you need to be able to compile some of projects that +VCMI solution provides, more information about them is in next part of +this tutorial. Default build configuration for VCMI solution is RD, what +means "release with debug information". + +You need to resolve header and library directories to point to all +required libraries in project settings to properly build VCMI. This is +out of scope of this tutorial. + +# VCMI solution details + +VCMI solution consists of few separate projects that get compiled to +separate output. Many of them rely on VCMI_lib, so making changes to +VCMI_lib requires recompiling another projects. Some of the projects are +dead or not updated for very long time, for example Editor or ERM. +FuzzyLite and minizip are utility projects and are not meant to be +currently changed. Projects in development and their purpose are: + +- BattleAI - as name says this project is for artificial intelligence + during battles. Gets compiled to DLL module. +- VCAI - adventure map artificial intelligence. Gets compiled to DLL + module. +- VCMI_client - game client, "game display" and user interface related + code is here. One of two main game game executables +- VCMI_launcher - game launcher with ability to change some available + game options, disable / enable VCMI mods etc. +- VCMI_lib - contains shared code for client and server. Large part of + game mechanics can be found here. Compilable to DLL module. +- VCMI_server - game server. Server starts everytime a scenario is + launched, and performs network-based communication with game client. + Some parts of game mechanics can be found here. One of two main game + executables. + +Projects mentioned above need to be compiled "together" to work because +of VCMI_lib dependency - for example compiling VCMI_lib and VCMI_client +requires recompiling server, AI projects etc. because their equivalents +from other sources such as VCMI windows package will not work with new +VCMI_lib and raise "cannot find entry point..." error *(TODO: Maybe this +can be worked around using another project code generation settings)*. +Working launcher is not needed to run the game though, as mentioned in +first part of this tutorial (prerequisites). Additional workaround to +skip compiling launcher and have access to launcher settings is to use +VCMI windows package as separate vcmi copy - changes made in launcher +there affect all vcmi copies. + +**There is also Test project for development purposes that can be used +for unit tests and similar things that developers may want to do.** \ No newline at end of file diff --git a/docs/developers/How to build VCMI (Windows Vcpkg).md b/docs/developers/How to build VCMI (Windows Vcpkg).md new file mode 100644 index 000000000..8ae1127df --- /dev/null +++ b/docs/developers/How to build VCMI (Windows Vcpkg).md @@ -0,0 +1,258 @@ +# Prerequisites + +- Windows Vista or newer. +- Microsoft Visual Studio + [2017](https://www.visualstudio.com/vs/older-downloads/) or + [2019](http://www.visualstudio.com/downloads/download-visual-studio-vs) +- CI use VS2019, so you are going to have less problems with it. +- Git or git GUI, for example, SourceTree + [download](http://www.sourcetreeapp.com/download) +- CMake [download](https://cmake.org/download/). During install after + accepting license agreement make sure to check "Add CMake to the + system PATH for all users". +- To unpack pre-build Vcpkg: + [7-zip](http://www.7-zip.org/download.html) +- To create installer: [NSIS](http://nsis.sourceforge.net/Main_Page) + +# Choose directory + +Create a directory for VCMI development, eg. **C:\VCMI** We will call +this directory **%VCMI_DIR%** + +**Warning!** Replace **%VCMI_DIR%** with path you chosen in following +commands of this instruction. + +## How to choose good directory + +It is recommended to avoid non-ascii characters in the path to your +working folders. The folder should not be write-protected by system. +Good location: + +- **C:\VCMI** + +Bad locations: + +- **C:\Users\Michał\VCMI** (non-ascii character) +- **C:\Program Files (x86)\VCMI** (write protection) + +# Install dependencies + +You have two options: to use pre-built libraries or build your own. We +strongly recommend start with using pre-built ones. + +## Option A. Use pre-built Vcpkg + +So you decide to start using Vcpkg packages pre-built by VCMI team. + +Package guaranteed to work since they tested with every commit by +[GitHub Actions](https://github.com/vcmi/vcmi/actions). + +### Download and unpack archive + +Archives are available from GitHub: + + +Only download latest version available. + +- vcpkg-export-**x86**-windows-v140.7z to build for 32-bit no debug, 3 + times smaller file size +- vcpkg-export-**x64**-windows-v140.7z to build for 64-bit no debug, 3 + times smaller file size +- vcpkg-export-**x86**-windows-v140-debug.7z to build for 32-bit with + debug configuration available +- vcpkg-export-**x64**-windows-v140-debug.7z to build for 64-bit with + debug configuration available + +Extract archive by right clicking on it and choosing "7-zip -\> Extract +Here". + +### Move dependencies to target directory + +Once extracted "vcpkg" directory will appear with "installed" and +"scripts" inside it. + +Move extracted "vcpkg" directory into your **%VCMI_DIR%**. + +## Option B. Build Vcpkg on your own + +Please be aware that if you're running 32-bit Windows version, then this +is impossible due to + +Be aware that building Vcpkg might take a lot of time depend on your CPU +model and 10-20GB of disk space. + +### Create initial directory + +### Clone vcpkg + +1. open SourceTree +2. File -\> Clone +3. select **** as source +4. select **%VCMI_DIR%/vcpkg** as destination +5. click **Clone** + +From command line use: + + git clone https://github.com/microsoft/vcpkg.git %VCMI_DIR%/vcpkg + +### Build vcpkg + +- Run + + + + %VCMI_DIR%/vcpkg/bootstrap-vcpkg.bat + +### Build dependencies + +- For 32-bit build run: + + + + %VCMI_DIR%/vcpkg/vcpkg.exe install tbb:x64-windows fuzzylite:x64-windows sdl2:x64-windows sdl2-image:x64-windows sdl2-ttf:x64-windows sdl2-mixer[mpg123]:x64-windows boost:x64-windows qt5-base:x64-windows ffmpeg:x64-windows luajit:x64-windows + +- For 64-bit build run + + + + %VCMI_DIR%/vcpkg/vcpkg.exe install install tbb:x86-windows fuzzylite:x86-windows sdl2:x86-windows sdl2-image:x86-windows sdl2-ttf:x86-windows sdl2-mixer[mpg123]:x86-windows boost:x86-windows qt5-base:x86-windows ffmpeg:x86-windows luajit:x86-windows + +For the list of the packages used you can also consult +[vcmi-deps-windows readme](https://github.com/vcmi/vcmi-deps-windows) in +case this article gets outdated a bit. + +# Build VCMI + +## Clone VCMI + +1. open SourceTree +2. File -\> Clone +3. select **** as source +4. select **%VCMI_DIR%/source** as destination +5. expand Advanced Options and change Checkout Branch to "develop" +6. tick Recursive submodules +7. click **Clone** + +or From command line use: + + git clone --recursive https://github.com/vcmi/vcmi.git %VCMI_DIR%/source + +## Generate solution for VCMI + +1. create **%VCMI_DIR%/build** folder +2. open **%VCMI_DIR%/build** in command line: + 1. Run Command Prompt or Power Shell. + 2. Execute: cd %VCMI_DIR%/build +3. execute one of following commands to generate project + +**Visual Studio 2017 - 32-bit build** + + cmake %VCMI_DIR%/source -DCMAKE_TOOLCHAIN_FILE=%VCMI_DIR%/vcpkg/scripts/buildsystems/vcpkg.cmake -G "Visual Studio 15 2017" + +**Visual Studio 2017 - 64-bit build** + + cmake %VCMI_DIR%/source -DCMAKE_TOOLCHAIN_FILE=%VCMI_DIR%/vcpkg/scripts/buildsystems/vcpkg.cmake -G "Visual Studio 15 2017 Win64" + +**Visual Studio 2019 - 32-bit build** + + cmake %VCMI_DIR%/source -DCMAKE_TOOLCHAIN_FILE=%VCMI_DIR%/vcpkg/scripts/buildsystems/vcpkg.cmake -G "Visual Studio 16 2019" -A Win32 + +**Visual Studio 2019 - 64-bit build** + + cmake %VCMI_DIR%/source -DCMAKE_TOOLCHAIN_FILE=%VCMI_DIR%/vcpkg/scripts/buildsystems/vcpkg.cmake -G "Visual Studio 16 2019" -A x64 + +## Compile VCMI with Visual Studio + +1. open **%VCMI_DIR%/build/VCMI.sln** in Visual Studio +2. select "Release" build type in combobox +3. right click on **BUILD_ALL** project - build project. This BUILD_ALL + project should be in "CMakePredefinedTargets" tree in Solution + Explorer. +4. grab VCMI in **%VCMI_DIR%/build/bin** folder! + +## Compile VCMI from command line + +**For release build** + + cmake --build %VCMI_DIR%/build --config Release + +**For debug build** + + cmake --build %VCMI_DIR%/build --config Debug + +Debug will be used by default even "--config" if not specified. + +# Create VCMI installer (This step is not required for just building & development) + +Make sure NSIS is installed to default directory or have registry entry +so CMake can find it. + +After you build VCMI execute following commands from +**%VCMI_DIR%/build**. + +### Execute following if you built for Release: + + cpack + +### If you built for Debug: + + cpack -C Debug + +# Troubleshooting and workarounds + +Vcpkg might be very unstable due to limited popularity and fact of using +bleeding edge packages (such as most recent Boost). Using latest version +of dependencies could also expose both problems in VCMI code or library +interface changes that developers not checked yet. So if you're built +Vcpkg yourself and can't get it working please try to use binary +package. + +Pre-built version we provide is always manually tested with all +supported versions of MSVC for both Release and Debug builds and all +known quirks are listed below. + +### VCMI won't run since some library is missing + +**If you open solution using vcmi.sln** Try to build INSTALL target and +see if its output works as expected. Copy missing libraries or even all +libraries from there to your build directory. Or run cpack and use +produced installer and see if you can get libs from there. cpack -V will +give more info. If cpack complains that it can not find dumpbin try +Visual Studio Command Prompt (special version of cmd provided with +Visual Studio with additional PATH) or modify PATH to have this tool +available. Another alternative if you use prebuilt vcpkg package is to +download latest msvc build, install it and copy missing/all libraries +from there. + +### Debug build is very slow + +Debug builds with MSVC are generally extremely slow since it's not just +VCMI binaries are built as debug, but every single dependency too and +this usually means no optimizations at all. Debug information that +available for release builds is often sufficient so just avoid full +debug builds unless absolutely necessary. Instead use RelWithDebInfo +configuration. Also Debug configuration might have some compilation +issues because it is not checked via CI for now. + +### I got crash within library XYZ.dll + +VCPKG generated projects quite often have both debug and regular libs +available to linker so it can select wrong lib. For stable +RelWithDebInfo build you may try to remove debug folder from +VCPKG/installed/x64-windows. Same is done on CI. Also it reduces package +size at least twice. + +### Some outdated problems + +All problems of such kind should be solved with proper cmake INSTALL +code. + +**Build is successful but can not start new game** + +Check that all non-VCMI dlls in AI and Scripting (vcmilua.dll and +vcmierm.dll) folders are also copied to the parent folder so that they +are available for vcmi_clent.exe. These are tbb.dll fuzzylite.dll +lua51.dll. Also there should be as well folder scripts (lua scripts for +ERM). If scripting folder is absent please build vcmiLua and vcmiErm +projects. There is no direct dependency between them and vcmi_client for +now (2021-08-28) \ No newline at end of file diff --git a/docs/developers/How to build VCMI (iOS).md b/docs/developers/How to build VCMI (iOS).md new file mode 100644 index 000000000..0c7437146 --- /dev/null +++ b/docs/developers/How to build VCMI (iOS).md @@ -0,0 +1,111 @@ +## Requirements + +1. **macOS** +2. Xcode: +3. CMake 3.21+: `brew install --cask cmake` or get from + + +## Obtaining source code + +Clone with submodules. Example for +command line: + +`git clone --recurse-submodules https://github.com/vcmi/vcmi.git` + +## Obtaining dependencies + +There're 2 ways to get prebuilt dependencies: + +- [Conan package + manager](https://github.com/vcmi/vcmi/tree/develop/docs/conan.md) - + recommended. Note that the link points to the cutting-edge state in + `develop` branch, for the latest release check the same document in + the [master + branch](https://github.com/vcmi/vcmi/tree/master/docs/conan.md). +- [legacy manually built + libraries](https://github.com/vcmi/vcmi-ios-deps) - can be used if + you have Xcode 11/12 or to build for simulator / armv7 device + +## Configuring project + +Only Xcode generator (`-G Xcode`) is supported! + +As a minimum, you must pass the following variables to CMake: + +- `BUNDLE_IDENTIFIER_PREFIX`: unique bundle identifier prefix, + something like `com.MY-NAME` +- (if using legacy dependencies) `CMAKE_PREFIX_PATH`: path to the + downloaded dependencies, e.g. + `~/Downloads/vcmi-ios-depends/build/iphoneos` + +There're a few [CMake +presets](https://cmake.org/cmake/help/latest/manual/cmake-presets.7.html): +for device (Conan and legacy dependencies) and for simulator, named +`ios-device-conan`, `ios-device` and `ios-simulator` respectively. You +can also create your local "user preset" to avoid typing variables each +time, see example +[here](https://gist.github.com/kambala-decapitator/59438030c34b53aed7d3895aaa48b718). + +Open terminal and `cd` to the directory with source code. Configuration +example for device with Conan: + +`cmake --preset ios-device-conan \` +` -D BUNDLE_IDENTIFIER_PREFIX=com.MY-NAME` + +By default build directory containing Xcode project will appear at +`../build-ios-device-conan`, but you can change it with `-B` option. + +### Building for device + +To be able to build for iOS device, you must also specify codesigning +settings. If you don't know your development team ID, open the generated +Xcode project, open project settings (click **VCMI** with blue icon on +the very top in the left panel with files), select **vcmiclient** +target, open **Signing & Capabilities** tab and select yout team. Now +you can copy the value from **Build Settings** tab - `DEVELOPMENT_TEAM` +variable (paste it in the Filter field on the right) - click the +greenish value - Other... - copy. Now you can pass it in +`CMAKE_XCODE_ATTRIBUTE_DEVELOPMENT_TEAM` variable when configuring the +project to avoid selecting the team manually every time CMake +re-generates the project. + +Advanced users who know exact private key and provisioning profile to +sign with, can use `CMAKE_XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY` and +`CMAKE_XCODE_ATTRIBUTE_PROVISIONING_PROFILE_SPECIFIER` variables +instead. In this case you must also pass + +`-D CMAKE_XCODE_ATTRIBUTE_CODE_SIGN_STYLE=Manual`. + +## Building project + +### From Xcode IDE + +Open `VCMI.xcodeproj` from the build directory, select `vcmiclient` +scheme (the only one with nice icon) with your destination +device/simulator and hit Run (Cmd+R). + +You must also install game files, see [Installation on +iOS](Installation_on_iOS "wikilink"). But this is not necessary if you +are going to run on simulator, as it is able to use game data from your +Mac located at `~/Library/Application Support/vcmi`. + +### From command line + +`cmake --build `` --target vcmiclient -- -quiet` + +You can pass additional xcodebuild options after the `--`. Here `-quiet` +is passed to reduce amount of output. + +Alternatively, you can invoke `xcodebuild` directly. + +There's also `ios-release-conan` configure and build preset that is used +to create release build on CI. + +## Creating ipa file for distribution + +Invoke `cpack` after building: + +`cpack -C Release` + +This will generate file with extension **ipa** if you use CMake 3.25+ +and **zip** otherwise (simply change extension to ipa). \ No newline at end of file diff --git a/docs/developers/How to build VCMI (macOS).md b/docs/developers/How to build VCMI (macOS).md new file mode 100644 index 000000000..a08809cfd --- /dev/null +++ b/docs/developers/How to build VCMI (macOS).md @@ -0,0 +1,170 @@ +# Requirements + +1. C++ toolchain, either of: + - Xcode Command Line Tools (aka CLT): + `sudo xcode-select --install` + - Xcode IDE: + - (not tested) other C++ compilers, e.g. gcc/clang from + [Homebrew](https://brew.sh/) +2. CMake: `brew install --cask cmake` or get from + +3. (optional) Ninja: `brew install ninja` or get from + + +# Obtaining source code + +Clone with submodules. Example for +command line: + +`git clone --recurse-submodules https://github.com/vcmi/vcmi.git` + +# Obtaining dependencies + +There're 2 ways to get dependencies automatically. + +## Conan package manager + +Please find detailed instructions in [VCMI +repository](https://github.com/vcmi/vcmi/tree/develop/docs/conan.md). +Note that the link points to the cutting-edge state in `develop` branch, +for the latest release check the same document in the [master +branch](https://github.com/vcmi/vcmi/tree/master/docs/conan.md). + +On the step where you need to replace **PROFILE**, choose: + +- if you're on an Intel Mac: `macos-intel` +- if you're on an Apple Silicon Mac: `macos-arm` + +Note: if you wish to build 1.0 release in non-`Release` configuration, +you should define `USE_CONAN_WITH_ALL_CONFIGS=1` environment variable +when executing `conan install`. + +## Homebrew + +1. [Install Homebrew](https://brew.sh/) +2. Install dependencies: + `brew install boost minizip sdl2 sdl2_image sdl2_mixer sdl2_ttf tbb` +3. If you want to watch in-game videos, also install FFmpeg: + `brew install ffmpeg@4` +4. Install Qt dependency in either of the ways (note that you can skip + this if you're not going to build Launcher): + - `brew install qt@5` for Qt 5 or `brew install qt` for Qt 6 + - using [Qt Online Installer](https://www.qt.io/download) - choose + **Go open source** + +# Preparing build environment + +This applies only to Xcode-based toolchain. If `xcrun -f clang` prints +errors, then use either of the following ways: + +- select an Xcode instance from Xcode application - Preferences - + Locations - Command Line Tools +- use `xcode-select` utility to set Xcode or Xcode Command Line Tools + path: for example, + `sudo xcode-select -s /Library/Developer/CommandLineTools` +- set `DEVELOPER_DIR` environment variable pointing to Xcode or Xcode + Command Line Tools path: for example, + `export DEVELOPER_DIR=/Applications/Xcode.app` + +# Configuring project for building + +Note that if you wish to use Qt Creator IDE, you should skip this step +and configure respective variables inside the IDE. + +1. In Terminal `cd` to the source code directory +2. Start assembling CMake invocation: type `cmake -S . -B BUILD_DIR` + where *BUILD_DIR* can be any path, **don't press Return** +3. Decide which CMake generator you want to use: + - Makefiles: no extra option needed or pass `-G 'Unix Makefiles'` + - Ninja (if you have installed it): pass `-G Ninja` + - Xcode IDE (if you have installed it): pass `-G Xcode` +4. If you picked Makefiles or Ninja, pick desired *build type* - either + of Debug / RelWithDebInfo / Release / MinSizeRel - and pass it in + `CMAKE_BUILD_TYPE` option, for example: + `-D CMAKE_BUILD_TYPE=Release`. If you don't pass this option, + `RelWithDebInfo` will be used. +5. If you don't want to build Launcher, pass `-D ENABLE_LAUNCHER=OFF` +6. You can also pass `-Wno-dev` if you're not interested in CMake + developer warnings +7. Next step depends on the dependency manager you have picked: + - Conan: pass + `-D CMAKE_TOOLCHAIN_FILE=conan-generated/conan_toolchain.cmake` + where **conan-generated** must be replaced with your directory + choice + - Homebrew: if you installed FFmpeg or Qt 5, you need to pass + `-D "CMAKE_PREFIX_PATH="` variable. See below what you can + insert after `=` (but **before the closing quote**), multiple + values must be separated with `;` (semicolon): + - if you installed FFmpeg, insert `$(brew --prefix ffmpeg@4)` + - if you installed Qt 5 from Homebrew, insert: + `$(brew --prefix qt@5)` + - if you installed Qt from Online Installer, insert your path + to Qt directory, for example: + `/Users/kambala/dev/Qt-libs/5.15.2/Clang64` + - example for FFmpeg + Qt 5: + `-D "CMAKE_PREFIX_PATH=$(brew --prefix ffmpeg@4);$(brew --prefix qt@5)"` +8. now press Return + +# Building project + +You must also install game files to be able to run the built version, +see [Installation on macOS](Installation_on_macOS "wikilink"). + +## From Xcode IDE + +Open `VCMI.xcodeproj` from the build directory, select `vcmiclient` +scheme and hit Run (Cmd+R). To build Launcher, select `vcmilauncher` +scheme instead. + +## From command line + +`cmake --build ` + +- If using Makefiles generator, you'd want to utilize all your CPU + cores by appending `-- -j$(sysctl -n hw.ncpu)` to the above +- If using Xcode generator, you can also choose which configuration to + build by appending `--config ` to the above, for + example: `--config Debug` + +# Packaging project into DMG file + +After building, run `cpack` from the build directory. If using Xcode +generator, also pass `-C ` with the same +configuration that you used to build the project. + +If you use Conan, it's expected that you use **conan-generated** +directory at step 4 of [#Conan package +manager](#Conan_package_manager "wikilink"). + +# Running VCMI + +You can run VCMI from DMG, but it's will also work from your IDE be it +Xcode or Qt Creator. + +Alternatively you can run binaries directly from "bin" directory: + + BUILD_DIR/bin/vcmilauncher + BUILD_DIR/bin/vcmiclient + BUILD_DIR/bin/vcmiserver + +CMake include commands to copy all needed assets from source directory +into "bin" on each build. They'll work when you build from Xcode too. + +# Some useful debugging tips + +Anyone who might want to debug builds, but new to macOS could find +following commands useful: + + # To attach DMG file from command line use + hdiutil attach vcmi-1.0.dmg + # Detach volume: + hdiutil detach /Volumes/vcmi-1.0 + # To view dependency paths + otool -L /Volumes/vcmi-1.0/VCMI.app/Contents/MacOS/vcmiclient + # To display load commands such as LC_RPATH + otool -l /Volumes/vcmi-1.0/VCMI.app/Contents/MacOS/vcmiclient + +# Troubleshooting + +In case of troubles you can always consult our CI build scripts or +contact the dev team via slack \ No newline at end of file diff --git a/docs/developers/Logging API.md b/docs/developers/Logging API.md new file mode 100644 index 000000000..2e89b4def --- /dev/null +++ b/docs/developers/Logging API.md @@ -0,0 +1,201 @@ +# Features + +- A logger belongs to a "domain", this enables us to change log level + settings more selectively +- The log format can be customized +- The color of a log entry can be customized based on logger domain + and logger level +- Logger settings can be changed in the settings.json file +- No std::endl at the end of a log entry required +- Thread-safe +- Macros for tracing the application flow +- Provides stream-like and function-like logging + +# Class diagram + +
+ +
Logging_Class_Diagram.jpg
+
+ +Some notes: + +- There are two methods `configure` and `configureDefault` of the + class `CBasicLogConfigurator` to initialize and setup the logging + system. The latter one setups default logging and isn't dependent on + VCMI's filesystem, whereas the first one setups logging based on the + user's settings which can be configured in the settings.json. +- The methods `isDebugEnabled` and `isTraceEnabled` return true if a + log record of level debug respectively trace will be logged. This + can be useful if composing the log message is a expensive task and + performance is important. + +# Usage + +## Setup settings.json + +``` javascript +{ + "logging" : { + "console" : { + "threshold" : "debug", + "colorMapping" : [ + { + "domain" : "network", + "level" : "trace", + "color" : "magenta" + } + ] + }, + "loggers" : [ + { + "domain" : "global", + "level" : "debug" + }, + { + "domain" : "ai", + "level" : "trace" + } + ] + } +} +``` + +The above code is an example on how to configure logging. It sets the +log level to debug globally and the log level of the domain ai to trace. +In addition, it tells the console to log debug messages as well with the +threshold attribute. Finally, it configures the console so that it logs +network trace messages in magenta. + +## Configuration + +The following code shows how the logging system can be configured: + + console = new CConsoleHandler; + CBasicLogConfigurator logConfig(VCMIDirs::get().localPath() + "/VCMI_Server_log.txt", console); + logConfig.configureDefault(); // Initialize default logging due to that the filesystem and settings are not available + preinitDLL(console); // Init filesystem + settings.init(); // Init settings + logConfig.configure(); // Now setup "real" logging system, overwrites default settings + +If `configureDefault` or `configure` won't be called, then logs aren't +written either to the console or to the file. The default logging setups +a system like this: + +**Console** + +Format: %m + +Threshold: info + +coloredOutputEnabled: true + +colorMapping: trace -\> gray, debug -\> white, info -\> green, warn -\> +yellow, error -\> red + +**File** + +Format: %d %l %n \[%t\] - %m + +**Loggers** + +global -\> info + +## How to get a logger + +There exist only one logger object per domain. A logger object cannot be +copied. You can get access to a logger object by using the globally +defined ones like `logGlobal` or `logAi`, etc... or by getting one +manually: + + CLogger * logger = CLogger::getLogger(CLoggerDomain("rmg")); + +## Logging + +Logging can be done via two ways, stream-like or function-like. + + logGlobal->warnStream() << "Call to loadBitmap with void fname!"; + logGlobal->warn("Call to loadBitmap with void fname!"); + +Don't include a '\n' or std::endl at the end of your log message, a new +line will be appended automatically. + +The following list shows several log levels from the highest one to the +lowest one: + +- error -\> for errors, e.g. if resource is not available, if a + initialization fault has occured, if a exception has been thrown + (can result in program termination) +- warn -\> for warnings, e.g. if sth. is wrong, but the program can + continue execution "normally" +- info -\> informational messages, e.g. Filesystem initialized, Map + loaded, Server started, etc... +- debug -\> for debugging, e.g. hero moved to (12,3,0), direction 3', + 'following artifacts influence X: .. or pattern detected at pos + (10,15,0), p-nr. 30, flip 1, repl. 'D' +- trace -\> for logging the control flow, the execution progress or + fine-grained events, e.g. hero movement completed, entering + CMapEditManager::updateTerrainViews: posx '10', posy '5', width + '10', height '10', mapLevel '0',... + +The following colors are available for console output: + +- default +- green +- red +- magenta +- yellow +- white +- gray +- teal + +## How to trace execution + +The program execution can be traced by using the macros TRACE_BEGIN, +TRACE_END and their \_PARAMS counterparts. This can be important if you +want to analyze the operations/internal workings of the AI or the +communication of the client-server. In addition, it can help you to find +bugs on a foreign VCMI installation with a custom mod configuration. + + int calculateMovementPointsForPath(int3 start, int3 end, CHero * hero) // This is just an example, the function is fictive + { + TRACE_BEGIN_PARAMS(logGlobal, "start '%s', end '%s', hero '%s'", start.toString() % end.toString() % hero.getName()); // toString is fictive as well and returns a string representation of the int3 pos, .... + int movPoints; + // Do some stuff + // ... + TRACE_END_PARAMS(logGlobal, "movPoints '%i'", movPoints); + return movPoints; + } + +# Concepts + +## Domain + +A domain is a specific part of the software. In VCMI there exist several +domains: + +- network +- ai +- bonus +- network + +In addition to these domains, there exist always a super domain called +"global". Sub-domains can be created with "ai.battle" or "ai.adventure" +for example. The dot between the "ai" and "battle" is important and +notes the parent-child relationship of those two domains. A few examples +how the log level will be inherited: + +global, level=info +network, level=not set, effective level=info + +global, level=warn +network, level=trace, effective level=trace + +global, level=debug +ai, level=not set, effective level=debug +ai.battle, level=trace, effective level=trace + +The same technique is applied to the console colors. If you want to have +another debug color for the domain ai, you can explicitely set a color +for that domain and level. \ No newline at end of file diff --git a/docs/developers/Logging_Class_Diagram.png b/docs/developers/Logging_Class_Diagram.png new file mode 100644 index 0000000000000000000000000000000000000000..0d5301548e9fa49d831975e9829f458da7a2b454 GIT binary patch literal 27067 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

a<7zljur`{Z>A_)|i{Q}o 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\> when deserializing. + +Serializer provides a public bool field `saving`that set to true during +serialziation and to false for deserialziation. + +Typically, serializing class involves serializing all its members (given +that they are serializable). Sample: + +``` cpp +/// The rumor struct consists of a rumor name and text. +struct DLL_LINKAGE Rumor +{ + std::string name; + std::string text; + + template + void serialize(Handler & h, const int version) + { + h & name & text; + } +}; +``` + +## Backwards compatibility + +Serializer, before sending any data, stores its version number. It is +passed as the parameter to the serialize method, so conditional code +ensuring backwards compatibility can be added. + +Yet, because of numerous changes to our game data structure, providing +means of backwards compatibility is not feasible. The versioning feature +is rarely used. + +Sample: + +``` cpp +/// The rumor struct consists of a rumor name and text. +struct DLL_LINKAGE Rumor +{ + std::string name; //introduced in version 1065 + std::string text; + + template + void serialize(Handler & h, const int version) + { + if(version >= 1065) + h & name; + else if(!h.saving) //when loading old savegame + name = "no name"; //set name to some default value [could be done in class constructor as well] + + h & text; + } +}; +``` + +## Serializer classes + +### Common information + +Serializer classes provide iostream-like interface with operator\<\< for +serialization and operator\>\> for deserialization. Serializer upon +creation will retrieve/store some metadata (version number, endianess), +so even if no object is actually serialized, some data will be passed. + +### Serialization to file + +CLoadFile/CSaveFile classes allow to read data to file and store data to +file. They take filename as the first parameter in constructor and, +optionally, the minimum supported version number (default to the current +version). If the construction fails (no file or wrong file) the +exception is thrown. + +### Networking + +CConnection class provides support for sending data structures over +TCP/IP protocol. It provides 3 constructors: 1) connect to given +hostname at given port (host must be accepting connection) 2) accept +connection (takes boost.asio acceptor and io_service) 3) adapt +boost.asio socket with already established connection + +All three constructors take as the last parameter the name that will be +used to identify the peer. + +## Additional features + +Here is the list of additional custom features serialzier provides. Most +of them can be turned on and off. + +- [#Polymorphic serialization](#Polymorphic_serialization "wikilink") + — no flag to control it, turned on by calls to registerType. +- [#Vectorized list member + serialization](#Vectorized_list_member_serialization "wikilink") — + enabled by smartVectorMembersSerialization flag. +- [#Stack instance + serialization](#Stack_instance_serialization "wikilink") — enabled + by sendStackInstanceByIds flag. +- [#Smart pointer + serialization](#Smart_pointer_serialization "wikilink") — enabled by + smartPointerSerialization flag. + +### Polymorphic serialization + +Serializer is to recognize the true type of object under the pointer if +classes of that hierarchy were previously registered. + +This means that following will work + +``` cpp +Derived *d = new Derived(); +Base *basePtr = d; +CSaveFile output("test.dat"); +output << b; +// +Base *basePtr = nullptr; +CLoadFile input("test.dat"); +input >> basePtr; //a new Derived object will be put under the pointer +``` + +Class hierarchies that are now registered to benefit from this feature +are mostly adventure map object (CGObjectInstance) and network packs +(CPack). See the RegisterTypes.h file for the full list. + +It is crucial that classes are registered in the same order in the both +serializers (storing and loading). + +### Vectorized list member serialization + +Both client and server store their own copies of game state and VLC +(handlers with data from config). Many game logic objects are stored in +the vectors and possess a unique id number that represent also their +position in such vector. + +The vectorised game objects are: + +`CGObjectInstance` +`CGHeroInstance` +`CCreature` +`CArtifact` +`CArtifactInstance` +`CQuest` + +For this to work, serializer needs an access to gamestate library +classes. This is done by calling a method +`CSerializer::addStdVecItems(CGameState *gs, LibClasses *lib)`. + +When the game ends (or gamestate pointer is invaldiated for another +reason) this feature needs to be turned off by toggling its flag. + +When vectorized member serialization is turned on, serializing pointer +to such object denotes not sending an object itself but rather its +identity. For example: + +``` cpp +//Server code +CCreature *someCreature = ...; +connection << someCreature; +``` + +the last line is equivalent to + +``` cpp +connection << someCreature->idNumber; +``` + +//Client code + +``` cpp +CCreature *someCreature = nullptr; +connection >> someCreature; +``` + +the last line is equivalent to + +``` cpp +CreatureID id; +connection >> id; +someCreature = VLC->creh->creatures[id.getNum()]; +``` + +Important: this means that the object state is not serialized. + +This feature makes sense only for server-client network communication. + +### Stack instance serialization + +This feature works very much like the vectorised object serialization. +It is like its special case for stack instances that are not vectorised +(each hero owns its map). When this option is turned on, sending +CStackInstance\* will actually send an owning object (town, hero, +garrison, etc) id and the stack slot position. + +For this to work, obviously, both sides of the connection need to have +exactly the same copies of an armed object and its stacks. + +This feature depends on vectorised member serialization being turned on. +(Sending owning object by id.) + +### Smart pointer serialization + +Note: name is unfortunate, this feature is not about smart pointers +(like shared-ptr and unique_ptr). It is for raw C-style pointers, that +happen to point to the same object. + +This feature makes it that multiple pointers pointing to the same object +are not stored twice. + +Each time a pointer is stored, a unique id is given to it. If the same +pointer is stored a second time, its contents is not serialized — +serializer just stores a reference to the id. + +For example: + +``` cpp +Foo * a = new Foo(); +Foo * b = b; + +{ + CSaveFile test("test.txt"); + test << a << b; +} + +Foo *loadedA, *loadedB; +{ + CLoadFile test("test.txt"); + test >> loadedA >> loadedB; + //now both pointers point to the same object + assert(loadedA == loadedB); +} +``` + +The feature recognizes pointers by addresses. Therefore it allows mixing +pointers to base and derived classes. However, it does not allow +serializing classes with multiple inheritance using a "non-first" base +(other bases have a certain address offset from the actual object). + +Pointer cycles are properly handled/ + +This feature makes sense for savegames and is turned on for them. \ No newline at end of file diff --git a/docs/modders/Bonus/List of all bonus types.md b/docs/modders/Bonus/List of all bonus types.md new file mode 100644 index 000000000..4def5a198 --- /dev/null +++ b/docs/modders/Bonus/List of all bonus types.md @@ -0,0 +1,832 @@ +The bonuses were grouped according to their original purpose. The bonus +system allows them to propagate freely betwen the nodes, however they +may not be recognized properly beyond the scope of original use. + +# General-purpose bonuses + +### NONE + +### MORALE, LUCK + +- val = value + +### MAGIC_SCHOOL_SKILL + +eg. for magic plains terrain and for magic school secondary skills + +- subtype: school of magic (0 - all, 1 - air, 2 - fire, 4 - water, 8 - + earth) +- val - level + +### NO_TYPE + +### DARKNESS + +- val = radius + +# Hero bonuses + +### MOVEMENT + +Before 1.2: both water / land After 1.2: subtype 0 - sea, subtype 1 - +land + +- val = number of movement points (100 points for a tile) + +### LAND_MOVEMENT, SEA_MOVEMENT (before 1.2) + +- val = number of movement points (100 points for a tile) + +### WATER_WALKING + +- subtype: 1 - without penalty, 2 - with penalty + +### FLYING_MOVEMENT + +- subtype: 1 - without penalty, 2 - with penalty + +### NO_TERRAIN_PENALTY (since 0.98f) + +Hero does not get movement penalty on certain terrain type (Nomads +ability). + +- subtype - type of terrain + +### PRIMARY_SKILL + +- uses subtype to pick skill +- additional info if set: 1 - only melee, 2 - only distance + +### SIGHT_RADIOUS (before 1.2) + +Additional bonus to range of sight (Used for Scouting secondary skill) + +- val = distance in tiles + +### SIGHT_RADIUS (after 1.2) + +Sight radius of a hero. Used for base radius + Scouting secondary skill + +- val = distance in tiles + +### MANA_REGENERATION + +Before 1.2: points per turn apart from normal (1 + mysticism) After 1.2: +points per turn (used for artifacts, global 1 point/turn regeneration +and mysticism secondary skill) + +### FULL_MANA_REGENERATION + +all mana points are replenished every day + +### NONEVIL_ALIGNMENT_MIX + +good and neutral creatures can be mixed without morale penalty + +### SECONDARY_SKILL_PREMY (before 1.2) + +% + +### SURRENDER_DISCOUNT + +% + +### IMPROVED_NECROMANCY + +Before 1.2: allows Necropolis units other than skeletons to be raised by +necromancy After 1.2: determine units which is raised by necromancy +skill. + +- subtype: creature raised +- val: Necromancer power +- addInfo: limiter by Necromancer power +- Example (from Necromancy skill): + +` "power" : {` +` "type" : "IMPROVED_NECROMANCY",` +` "subtype" : "creature.skeleton",` +` "addInfo" : 0` +` }` + +### LEARN_BATTLE_SPELL_CHANCE (since 1.2) + +- subtype: 0 - from enemy hero, 1 - from entire battlefield (not + implemented now). +- val: chance to learn spell after battle victory + +Note: used for Eagle Eye skill + +### LEARN_BATTLE_SPELL_LEVEL_LIMIT (since 1.2) + +- subtype: school (-1 for all), others TODO +- val: maximum learning level + +Note: used for Eagle Eye skill + +### LEARN_MEETING_SPELL_LIMIT (since 1.2) + +- subtype: school (-1 for all), others TODO +- val: maximum learning level for learning a spell during hero + exchange + +Note: used for Scholar skill + +### ROUGH_TERRAIN_DISCOUNT (since 1.2) + +- val: Non-road terrain discount in movement points + +Note: used for Pathfinding skill + +### WANDERING_CREATURES_JOIN_BONUS (since 1.2) + +- val: value than used as level of diplomacy inside joining + probability calculating + +### BEFORE_BATTLE_REPOSITION (since 1.2) + +- val: number of hexes - 1 than should be used as repositionable hexes + before battle (like H3 tactics skill) + +### BEFORE_BATTLE_REPOSITION_BLOCK (since 1.2) + +- val: value than block opposite tactics, if value of opposite tactics + is less than this value of your hero (for 1.2, double-side tactics + is not working). + +### HERO_EXPERIENCE_GAIN_PERCENT (since 1.2) + +- val: how many experience hero gains from any source. There is a + global effect which set it by 100 (global value) and it is used as + learning skill + +### UNDEAD_RAISE_PERCENTAGE (since 1.2) + +- val: Percentage of killed enemy creatures to be raised after battle + as undead. + +Note: used for Necromancy secondary skill, Necromancy artifacts and town +buildings. + +### MANA_PER_KNOWLEDGE (since 1.2) + +- val: Percentage rate of translating 10 hero knowledge to mana, used + for intelligence and global bonus + +### HERO_GRANTS_ATTACKS (since 1.2) + +- subtype: creature to have additional attacks +- val: Number of attacks + +Note: used for Artillery secondary skill + +### BONUS_DAMAGE_PERCENTAGE (since 1.2) + +- subtype: creature to have additional damage percentage +- val: percentage to be granted + +Note: used for Artillery secondary skill + +### BONUS_DAMAGE_CHANCE (since 1.2) + +- subtype: creature to have additional damage chance (will have + BONUS_DAMAGE_PERCENTAGE applied before attack concluded) +- val: chance in percent + +### MAX_LEARNABLE_SPELL_LEVEL (since 1.2) + +- val: maximum level of spells than hero can learn from any source. + This bonus have priority above any other LEARN\_\*SPELL_LEVEL + bonuses. + +Note: used as global effect and as wisdom secondary skill. + +## Hero specialties + +### SPECIAL_SPELL_LEV + +- subtype = id +- additionalInfo = value per level in percent + +### SPELL_DAMAGE + +Since 1.2: used for Sorcery secondary skill + +- val = value in percent + +### SPECIFIC_SPELL_DAMAGE + +- subtype = id of spell +- val = value in percent (Luna, Ciele) + +### SPECIAL_BLESS_DAMAGE (before 1.2) + +- subtype = spell (bless by default) +- val = value per level in percent + +### MAXED_SPELL (before 1.2) + +Spell always has expert effects but not expert range + +- subtype = id + +### SPECIAL_PECULIAR_ENCHANT + +blesses and curses with id = val dependent on unit's level + +- subtype = 0 or 1 for Coronius + +### SPECIAL_UPGRADE + +- subtype = base creature ID +- addInfo = target creature ID + +# Artifact bonuses + +### SPELL_DURATION + +### AIR_SPELL_DMG_PREMY, EARTH_SPELL_DMG_PREMY, FIRE_SPELL_DMG_PREMY, WATER_SPELL_DMG_PREMY + +Effect of original Orb artifacts. + +- val - **percent** bonus to air / earth / fire / water spell damage. + +### BLOCK_MORALE, BLOCK_LUCK (removed in 1.2) + +### SPELL + +Hero knows spell, even if this spell is banned in map options or set to +"special". + +- subtype - spell id +- val - skill level (0 - 3) + +### SPELLS_OF_LEVEL + +hero knows all spells of given level + +- subtype - level +- val - skill level + +Does not grant spells banned in map options. + +### FIRE_SPELLS, AIR_SPELLS, WATER_SPELLS, EARTH_SPELLS + +All spells of this school are granted to hero, eg. by Tomes of Magic. +Does not grant spells banned in map options. + +### GENERATE_RESOURCE + +- subtype - [resource](resource "wikilink") type +- val - daily income + +### CREATURE_GROWTH + +for legion artifacts + +- value - weekly growth bonus, +- subtype - monster level if aplicable + +### CREATURE_GROWTH_PERCENT + +increases growth of all units in all towns, + +- val - percentage + +### BATTLE_NO_FLEEING + +for Shackles of War + +### NEGATE_ALL_NATURAL_IMMUNITIES + +Orb of Vulnerability + +### OPENING_BATTLE_SPELL + +casts a spell at expert level at beginning of battle + +- subtype - [spell](spell "wikilink") id +- val - spell power + +### FREE_SHIP_BOARDING + +movement points preserved with ship boarding and landing + +### WHIRLPOOL_PROTECTION + +hero won't lose army when teleporting through whirlpool + +# Creature bonuses + +### STACK_HEALTH + +### STACKS_SPEED + +- additional info - percent of speed bonus applied after direct + bonuses; \>0 - added, \<0 - subtracted to this part + +### CREATURE_DAMAGE + +- subtype: 0 = both, 1 = min, 2 = max + +### SHOTS + +### EXP_MULTIPLIER + +- val - percent of additional exp gained by stack / commander (base + value 100) + +# Creature abilities + +## Static abilities and immunities + +### NON_LIVING + +eg. golems, elementals + +### GARGOYLE + +Gargoyle is special than NON_LIVING, cannot be rised or healed + +### UNDEAD + +### SIEGE_WEAPON + +War machines have it. They cannot be raised or healed, have no morale +and don't move. + +### DRAGON_NATURE + +### KING1, KING2, KING3 (before 1.2) + +Creatures take more damage from basic, advanced or expert Slayer effect. + +### KING (after 1.2) + +Creatures take more damage from Slayer effect than have greater or equal +value than KING bonus. + +### FEARLESS + +### NO_LUCK + +eg. when fighting on cursed ground + +### NO_MORALE + +eg. when fighting on cursed ground + +### SELF_MORALE (before 1.2) + +eg. minotaur + +### SELF_LUCK (before 1.2) + +halfling + +## Combat abilities + +### FLYING + +- subtype - 0 - regular, 1 - teleport + +### SHOOTER + +### CHARGE_IMMUNITY + +### ADDITIONAL_ATTACK + +### UNLIMITED_RETALIATIONS + +### ADDITIONAL_RETALIATION + +- value - number of additional retaliations + +### JOUSTING + +for champions + +- val: percentage of charge + +### HATE + +eg. angels hate devils, + +- subtype - ID of hated creature, +- val - damage bonus percent + +### SPELL_LIKE_ATTACK + +range is taken from spell, but damage from creature; eg. magog, lich + +- subtype - spell, +- value - spell level + +### THREE_HEADED_ATTACK + +eg. cerberus + +### ATTACKS_ALL_ADJACENT + +eg. hydra + +### TWO_HEX_ATTACK_BREATH + +eg. dragons + +### RETURN_AFTER_STRIKE + +### ENEMY_DEFENCE_REDUCTION + +in % (value) eg. behemots + +### GENERAL_DAMAGE_REDUCTION + +- subtype - 0 - shield (melee) , 1 - air shield effect (ranged), -1 - + armorer secondary skill (all, since 1.2) + +### PERCENTAGE_DAMAGE_BOOST (since 1.2) + +- subtype: -1 - any damage (not used), 0 - melee damage (offence), 1 - + ranged damage (archery) + +### GENERAL_ATTACK_REDUCTION + +eg. while stoned or blinded - in % + +- subtype: -1 - any damage, 0 - melee damage, 1 - ranged damage + +### DEFENSIVE_STANCE + +WoG ability. + +- val - bonus to defense while defending + +### NO_DISTANCE_PENALTY + +### NO_MELEE_PENALTY + +Ranged stack does full damage in melee. + +### NO_WALL_PENALTY + +### FREE_SHOOTING + +stacks can shoot even if otherwise blocked (sharpshooter's bow effect) + +### BLOCKS_RETALIATION + +eg. naga + +### SOUL_STEAL + +WoG ability. Gains new creatures for each enemy killed + +- val: number of units gained per enemy killed +- subtype: 0 - gained units survive after battle, 1 - they do not + +### TRANSMUTATION + +WoG ability. % chance to transform attacked unit to other type + +- val: chance to trigger in % +- subtype: 0 - resurrection based on HP, 1 - based on unit count +- addInfo: additional info - target creature ID (attacker default) + +### SUMMON_GUARDIANS + +WoG ability. Summon guardians surrounding desired stack + +- val - amount in % of stack count +- subtype = creature ID + +### RANGED_RETALIATION + +Allows shooters to perform ranged retaliation + +- no additional parameters + +### BLOCKS_RANGED_RETALIATION + +Disallows ranged retaliation for shooter unit, BLOCKS_RETALIATION bonus +is for melee retaliation only + +- no additional parameters + +### WIDE_BREATH + +Dragon breath affecting multiple nearby hexes + +- no additional parameters + +### FIRST_STRIKE + +First counterattack, then attack if possible + +- no additional parameters + +### SHOOTS_ALL_ADJACENT + +H4 Cyclops-like shoot (attacks all hexes neighboring with target) +without spell-like mechanics + +- no additional parameters + +### DESTRUCTION + +Kills extra units after hit + +- subtype: 0 - kill percentage of units, 1 - kill amount +- val: chance in percent to trigger +- addInfo: amount/percentage to kill + +### LIMITED_SHOOTING_RANGE (since VCMI 1.2) + +Limits shooting range and/or changes long range penalty + +- val: max shooting range in hexes +- addInfo: optional - sets range for "broken arrow" half damage + mechanic - default is 10 + +## Special abilities + +### CATAPULT + +- subtype: (since 1.2) ability to use when catapulting (usually it + contains ballistics parameters, ability for standard catapult and + affected by ballistics is core:spell.catapultShot) + +### CATAPULT_EXTRA_SHOTS + +- subtype: (since 1.2) ability to be affected. Ability of CATAPULT + bonus should match. Used for ballistics secondary skill with subtype + of core:spell.catapultShot. +- val: (since 1.2) ability level to be used with catapult. Additional + shots configured in ability level, not here. +- val: (before 1.2) number of additional shots, requires CATAPULT + bonus to work + +### MANUAL_CONTROL + +- manually control warmachine with +- id = subtype +- val = chance + +### CHANGES_SPELL_COST_FOR_ALLY + +eg. mage + +- value - reduction in mana points + +### CHANGES_SPELL_COST_FOR_ENEMY + +eg. Silver Pegasus + +- value - mana points penalty + +### SPELL_RESISTANCE_AURA + +eg. unicorns + +- value - resistance bonus in % for adjacent creatures + +### HP_REGENERATION + +creature regenerates val HP every new round + +- val: amount of HP regeneration per round + +### MANA_DRAIN + +value - spell points per turn + +### MANA_CHANNELING + +eg. familiar + +- value in % + +### LIFE_DRAIN + +- val - precentage of life drained + +### DOUBLE_DAMAGE_CHANCE + +eg. dread knight + +- value in % + +### FEAR + +### HEALER + +First aid tent + +- subtype: (since 1.2) ability used for healing. + +### FIRE_SHIELD + +### MAGIC_MIRROR + +- value - chance of redirecting in % + +### ACID_BREATH + +- val - damage per creature after attack, +- additional info - chance in percent + +### DEATH_STARE + +- subtype: 0 - gorgon, 1 - commander +- val: if subtype is 0, its the (average) percentage of killed + creatures related to size of attacking stack + +### SPECIAL_CRYSTAL_GENERATION + +Crystal dragon crystal generation + +### NO_SPELLCAST_BY_DEFAULT + +Spellcast will not be default attack option for this creature + +## Creature spellcasting and activated abilities + +### SPELLCASTER + +Creature gain activated ability to cast a spell. Example: Archangel, +Faerie Dragon + +- subtype - spell id +- value - level of school +- additional info - weighted chance + +use SPECIFIC_SPELL_POWER, CREATURE_SPELL_POWER or CREATURE_ENCHANT_POWER +for calculating the power (since 1.2 those bonuses can be used for +calculating CATAPULT and HEALER bonuses) + +### ENCHANTER + +for Enchanter spells + +- val - skill level +- subtype - spell id +- additionalInfo - cooldown (number of turns) + +### RANDOM_SPELLCASTER + +eg. master genie + +- val - spell mastery level + +### SPELL_AFTER_ATTACK + +- subtype - spell id +- value - chance % +- additional info - \[X, Y\] +- X - spell level +- Y = 0 - all attacks, 1 - shot only, 2 - melee only + +### SPELL_BEFORE_ATTACK + +- subtype - spell id +- value - chance % +- additional info - \[X, Y\] +- X - spell level +- Y = 0 - all attacks, 1 - shot only, 2 - melee only + +### CASTS + +how many times creature can cast activated spell + +### SPECIFIC_SPELL_POWER + +- value used for Thunderbolt and Resurrection casted by units, also + for Healing secondary skill (for core:spell.firstAid used by First + Aid tent) +- subtype - spell id + +### CREATURE_SPELL_POWER + +- value per unit, divided by 100 (so faerie Dragons have 500) + +### CREATURE_ENCHANT_POWER + +total duration of spells casted by creature + +### REBIRTH + +- val - percent of total stack HP restored +- subtype = 0 - regular, 1 - at least one unit (sacred Phoenix) + +### ENCHANTED + +Stack is permanently enchanted with spell subID of skill level = val, if +val \> 3 then spell is mass and has level of val-3. Enchantment is +refreshed every turn. + +## Spell immunities + +### LEVEL_SPELL_IMMUNITY + +creature is immune to all spell with level below or equal to value of +this bonus + +### MAGIC_RESISTANCE + +- value - percent + +### SPELL_DAMAGE_REDUCTION + +eg. golems + +- value - reduction in % +- subtype - spell school; -1 - all, 0 - air, 1 - fire, 2 - water, 3 - + earth + +### MORE_DAMAGE_FROM_SPELL + +- value - damage increase in % +- subtype - spell id + +### FIRE_IMMUNITY,WATER_IMMUNITY, EARTH_IMMUNITY, AIR_IMMUNITY + +- subtype 0 - all, 1 - all except positive, 2 - only damage spells + +### MIND_IMMUNITY + +Creature is immune to all mind spells. + +### SPELL_IMMUNITY + +- subtype - spell id +- ainfo - 0 - normal, 1 - absolute + +### DIRECT_DAMAGE_IMMUNITY + +WoG ability. Creature is completely immune to damage spells. + +### RECEPTIVE + +WoG ability. Creature accepts all friendly spells even though it would +be normally immune to it. + +## Deprecated creature abilities + +### DAEMON_SUMMONING + +pit lord - removed in VCMI 1.2 as part of major battles refactoring + +- subtype - type of creatures +- val - hp per unit + +# Spell effects + +### POISON + +- val - max health penalty from poison possible + +### SLAYER + +- value - spell level + +### BIND_EFFECT + +doesn't do anything particular, works as a marker + +### FORGETFULL + +forgetfulness spell effect + +- value - level + +### NOT_ACTIVE + +### ALWAYS_MINIMUM_DAMAGE + +unit does its minimum damage from range + +- subtype: -1 - any attack, 0 - melee, 1 - ranged +- value: additional damage penalty (it'll subtracted from dmg) +- additional info - multiplicative anti-bonus for dmg in % \[eg 20 + means that creature will inflict 80% of normal minimal dmg\] + +### ALWAYS_MAXIMUM_DAMAGE + +eg. bless effect + +- subtype: -1 - any attack, 0 - melee, 1 - ranged +- value: additional damage +- additional info - multiplicative bonus for dmg in % + +### ATTACKS_NEAREST_CREATURE + +while in berserk + +### IN_FRENZY + +- value - level + +### HYPNOTIZED + +### NO_RETALIATION + +Eg. when blinded or paralyzed. \ No newline at end of file diff --git a/docs/modders/Bonus/List of bonus duration types.md b/docs/modders/Bonus/List of bonus duration types.md new file mode 100644 index 000000000..616af670d --- /dev/null +++ b/docs/modders/Bonus/List of bonus duration types.md @@ -0,0 +1,16 @@ +Bonus may have any of these durations. They acts in disjunction. + +## List of all bonus duration types + +- PERMANENT +- ONE_BATTLE //at the end of battle +- ONE_DAY //at the end of day +- ONE_WEEK //at the end of week (bonus lasts till the end of week, + thats NOT 7 days +- N_TURNS //used during battles, after battle bonus is always removed +- N_DAYS +- UNTIL_BEING_ATTACKED //removed after any damage-inflicting attack +- UNTIL_ATTACK //removed after attack and counterattacks are performed +- STACK_GETS_TURN //removed when stack gets its turn - used for + defensive stance +- COMMANDER_KILLED \ No newline at end of file diff --git a/docs/modders/Bonus/List of bonus limiters.md b/docs/modders/Bonus/List of bonus limiters.md new file mode 100644 index 000000000..dda2f807c --- /dev/null +++ b/docs/modders/Bonus/List of bonus limiters.md @@ -0,0 +1,105 @@ +## Predefined Limiters + +The limiters take no parameters: + +- SHOOTER_ONLY +- DRAGON_NATURE +- IS_UNDEAD +- CREATURE_NATIVE_TERRAIN +- OPPOSITE_SIDE + +Example: + +``` javascript +"limiters" : [ "SHOOTER_ONLY" ] +``` + +## Customizable Limiters + +### HAS_ANOTHER_BONUS_LIMITER + +Parameters: + +- Bonus type +- (optional) bonus subtype +- (optional) bonus sourceType and sourceId in struct +- example: (from Adele's bless): + +``` javascript + "limiters" : [ + { + "type" : "HAS_ANOTHER_BONUS_LIMITER", + "parameters" : [ + "GENERAL_DAMAGE_PREMY", + 1, + { + "type" : "SPELL_EFFECT", + "id" : "spell.bless" + } + ] + } + ], +``` + +### CREATURE_TYPE_LIMITER + +Parameters: + +- Creature id (string) +- (optional) include upgrades - default is false + +### CREATURE_ALIGNMENT_LIMITER + +Parameters: + +- Alignment identifier + +### CREATURE_FACTION_LIMITER + +Parameters: + +- Faction identifier + +### CREATURE_TERRAIN_LIMITER + +Parameters: + +- Terrain identifier + +Example: + +``` javascript +"limiters": [ { + "type":"CREATURE_TYPE_LIMITER", + "parameters": [ "angel", true ] +} ], +``` + +``` javascript +"limiters" : [ { + "type" : "CREATURE_TERRAIN_LIMITER", + "parameters" : ["sand"] +} ] +``` + +## Aggregate Limiters + +The following limiters must be specified as the first element of a list, +and operate on the remaining limiters in that list: + +- allOf (default when no aggregate limiter is specified) +- anyOf +- noneOf + +Example: + +``` javascript +"limiters" : [ + "noneOf", + "IS_UNDEAD", + { + "type" : "HAS_ANOTHER_BONUS_LIMITER", + "parameters" : [ "SIEGE_WEAPON" ] + } +] +``` \ No newline at end of file diff --git a/docs/modders/Bonus/List of bonus propagators.md b/docs/modders/Bonus/List of bonus propagators.md new file mode 100644 index 000000000..408229b4e --- /dev/null +++ b/docs/modders/Bonus/List of bonus propagators.md @@ -0,0 +1,25 @@ +## Available propagators + +- BATTLE_WIDE + +Affects both sides during battle + +- VISITED_TOWN_AND_VISITOR + +Used with Legion artifacts (town visited by hero) + +- PLAYER_PROPAGATOR + +Bonus will affect all objects owned by player. Used by Statue of Legion. + +- TEAM_PROPAGATOR + +Bonus will affect all objects owned by player and his allies. + +- HERO + +Bonus will be transferred to hero (for example from stacks in his army). + +- GLOBAL_EFFECT + +This effect will influence all creatures, heroes and towns on the map. \ No newline at end of file diff --git a/docs/modders/Bonus/List of bonus range types.md b/docs/modders/Bonus/List of bonus range types.md new file mode 100644 index 000000000..b5c131507 --- /dev/null +++ b/docs/modders/Bonus/List of bonus range types.md @@ -0,0 +1,20 @@ +# List of all Bonus range types + +- NO_LIMIT +- ONLY_DISTANCE_FIGHT +- ONLY_MELEE_FIGHT +- ONLY_ENEMY_ARMY (before 1.2) + +TODO: in 0.91 ONLY_MELEE_FIGHT / ONLY_DISTANCE_FIGHT range types work +ONLY with creature attack, should be extended to all battle abilities. + +(1.2+) For replacing ONLY_ENEMY_ARMY alias, you should use the following +parameters of bonus: + + "propagator": "BATTLE_WIDE", + "propagationUpdater" : "BONUS_OWNER_UPDATER", + "limiters" : [ "OPPOSITE_SIDE" ] + +If some propagators was set before, it was actually ignored and should +be replaced to code above. And OPPOSITE_SIDE limiter should be first, if +any other limiters exists. \ No newline at end of file diff --git a/docs/modders/Bonus/List of bonus sources.md b/docs/modders/Bonus/List of bonus sources.md new file mode 100644 index 000000000..320333957 --- /dev/null +++ b/docs/modders/Bonus/List of bonus sources.md @@ -0,0 +1,21 @@ +# List of all possible bonus sources + +- ARTIFACT +- ARTIFACT_INSTANCE +- OBJECT +- CREATURE_ABILITY +- TERRAIN_NATIVE +- TERRAIN_OVERLAY +- SPELL_EFFECT +- TOWN_STRUCTURE +- HERO_BASE_SKILL +- SECONDARY_SKILL +- HERO_SPECIAL +- ARMY +- CAMPAIGN_BONUS +- SPECIAL_WEEK +- STACK_EXPERIENCE +- COMMANDER +- GLOBAL_EFFECT (before 1.2) +- GLOBAL (after 1.2) +- OTHER \ No newline at end of file diff --git a/docs/modders/Bonus/List of bonus updaters.md b/docs/modders/Bonus/List of bonus updaters.md new file mode 100644 index 000000000..2bb74d794 --- /dev/null +++ b/docs/modders/Bonus/List of bonus updaters.md @@ -0,0 +1,89 @@ +# List of Bonus Updaters + +Updaters come in two forms: simple and complex. Simple updaters take no +parameters and are specified as strings. Complex updaters do take +parameters (sometimes optional), and are specified as structs. + +Check the files in *config/heroes/* for additional usage examples. + +## GROWS_WITH_LEVEL + +- Type: Complex +- Parameters: valPer20, stepSize=1 +- Effect: Updates val to + +` ceil(valPer20 * floor(heroLevel / stepSize) / 20)` + +Example: The following updater will cause a bonus to grow by 6 for every +40 levels. At first level, rounding will cause the bonus to be 0. + +` "updater" : {` +` "parameters" : [ 6, 2 ],` +` "type" : "GROWS_WITH_LEVEL"` +` }` + +Example: The following updater will cause a bonus to grow by 3 for every +20 levels. At first level, rounding will cause the bonus to be 1. + +` "updater" : {` +` "parameters" : [ 3 ],` +` "type" : "GROWS_WITH_LEVEL"` +` }` + +Remarks: + +- The rounding rules are designed to match the attack/defense bonus + progression for heroes with creature specialties in HMM3. +- There is no point in specifying val for a bonus with a + GROWS_WITH_LEVEL updater. + +## TIMES_HERO_LEVEL + +- Type: Simple +- Effect: Updates val to + +` val * heroLevel` + +Usage: + +` "updater" : "TIMES_HERO_LEVEL"` + +Remark: This updater is redundant, in the sense that GROWS_WITH_LEVEL +can also express the desired scaling by setting valPer20 to 20\*val. It +has been added for convenience. + +## TIMES_STACK_LEVEL + +- Type: Simple +- Effect: Updates val to + +` val * stackLevel` + +Usage: + +` "updater" : "TIMES_STACK_LEVEL"` + +Remark: The stack level for war machines is 0. + +## ARMY_MOVEMENT + +- Type: Complex +- Parameters: basePerSpeed, dividePerSpeed, additionalMultiplier, + maxValue +- Effect: Updates val to val+= max((floor(basePerSpeed / + dividePerSpeed)\* additionalMultiplier), maxValue) +- Remark: this updater is designed for MOVEMENT bonus to match H3 army + movement rules (in the example - actual movement updater, which + produces values same as in default movement.txt). +- Example: + +` "updater" : {` +` "parameters" : [ 20, 3, 10, 700 ],` +` "type" : "ARMY_MOVEMENT"` +` }` + +# Additional links + +- [Bonus system](Bonus_system "wikilink") +- [Bonus Format](Bonus_Format "wikilink") +- [Hero Format](Hero_Format "wikilink") \ No newline at end of file diff --git a/docs/modders/Bonus/List of bonus value types.md b/docs/modders/Bonus/List of bonus value types.md new file mode 100644 index 000000000..6aab87712 --- /dev/null +++ b/docs/modders/Bonus/List of bonus value types.md @@ -0,0 +1,31 @@ +Total value of Bonus is calculated using the following: + +- For each bonus source type we calculate new source value (for all + bonus value types except PERCENT_TO_SOURCE and + PERCENT_TO_TARGET_TYPE) using the following: + +` newVal = (val * (100 + PERCENT_TO_SOURCE) / 100))` + +PERCENT_TO_TARGET_TYPE applies as PERCENT_TO_SOURCE to targetSourceType +of bonus. + +- All bonus value types summarized and then used as subject of the + following formula: + +` clamp(((BASE_NUMBER * (100 + PERCENT_TO_BASE) / 100) + ADDITIVE_VALUE) * (100 + PERCENT_TO_ALL) / 100), INDEPENDENT_MAX, INDEPENDENT_MIN)` + +As for 1.2, semantics of INDEPENDENT_MAX and INDEPENDENT_MIN are +wrapped, and first means than bonus total value will be at least +INDEPENDENT_MAX, and second means than bonus value will be at most +INDEPENDENT_MIN. + +# List of all bonus value types + +- ADDITIVE_VALUE +- BASE_NUMBER +- PERCENT_TO_ALL +- PERCENT_TO_BASE +- INDEPENDENT_MAX +- INDEPENDENT_MIN +- PERCENT_TO_SOURCE (since 1.2) +- PERCENT_TO_TARGET_TYPE (since 1.2) \ No newline at end of file diff --git a/docs/modders/Building bonuses.md b/docs/modders/Building bonuses.md new file mode 100644 index 000000000..74dfc0e3f --- /dev/null +++ b/docs/modders/Building bonuses.md @@ -0,0 +1,169 @@ +Work-in-progress page do describe all bonuses provided by town buildings +for future configuration. + +## unique buildings + +Hardcoded functionalities, selectable but not configurable. In future +should be moved to scripting. + +Includes: + +- mystic pond +- treasury +- god of fire +- castle gates +- cover of darkness +- portal of summoning +- escape tunnel + +Function of all of these objects can be enabled by this: + +``` javascript + "function" : "castleGates" +``` + +## trade-related + +Hardcoded functionality for now due to complexity of these objects. +Temporary can be handles as unique buildings. Includes: + +- resource - resource +- resource - player +- artifact - resource +- resource - artifact +- creature - resource +- resource - skills +- creature - skeleton + +## hero visitables + +Buildings that give one or another bonus to visiting hero. All should be +handled via configurable objects system. + +Includes: + +- gives mana points +- gives movement points +- give bonus to visitor +- permanent bonus to hero + +## generic functions + +Generic town-specific functions that can be implemented as part of +CBuilding class. + +### unlock guild level + +``` javascript + "guildLevels" : 1 +``` + +### unlock hero recruitment + +``` javascript + "allowsHeroPurchase" : true +``` + +### unlock ship purchase + +``` javascript + "allowsShipPurchase" : true +``` + +### unlock building purchase + +``` javascript + "allowsBuildingPurchase" : true +``` + +### unlocks creatures + +``` javascript + "dwelling" : { "level" : 1, "creature" : "archer" } +``` + +### creature growth bonus + +Turn into town bonus? What about creature-specific bonuses from hordes? + +### gives resources + +``` javascript + "provides" : { "gold" : 500 } +``` + +### gives guild spells + +``` javascript + "guildSpells" : [5, 0, 0, 0, 0] +``` + +### gives thieves guild + +``` javascript + "thievesGuildLevels" : 1 +``` + +### gives fortifications + +``` javascript + "fortificationLevels" : 1 +``` + +### gives war machine + +``` javascript + "warMachine" : "ballista" +``` + +## simple bonuses + +Bonuses that can be made part of CBuilding. Note that due to how bonus +system works this bonuses won't be stackable. + +TODO: how to handle stackable bonuses like Necromancy Amplifier? + +Includes: + +- bonus to defender +- bonus to alliance +- bonus to scouting range +- bonus to player + +``` javascript +"bonuses" : +{ + "moraleToDefenders" : + { + "type": "MORALE", + "val" : 1, + "propagator" : ["VISITED_TOWN_AND_VISITOR"] + }, + "luckToTeam" : + { + "type" : "LUCK", + "val" : 2, + "propagator" : [ "TEAM_PROPAGATOR" ] + } +``` + +## misc + +Some other properties of town building that does not fall under "bonus" +category. + +### unique building + +Possible issue - with removing of fixed ID's buildings in different town +may no longer share same ID. However Capitol must be unique across all +town. Should be fixed somehow. + +``` javascript + "onePerPlayer" : true +``` + +### chance to be built on start + +``` javascript + "prebuiltChance" : 75 +``` \ No newline at end of file diff --git a/docs/modders/Map objects/Creature bank.md b/docs/modders/Map objects/Creature bank.md new file mode 100644 index 000000000..1e25111ac --- /dev/null +++ b/docs/modders/Map objects/Creature bank.md @@ -0,0 +1,66 @@ +This is description of fields for creature banks, part of [Object +Format](Object_Format "wikilink") + +``` javascript +{ + /// List of levels of this bank. On map loading, one of them will be randomly assigned to bank. + "levels": [ + { + /// Chance for this level to be active + "chance": 30, + + /// Description of guards, stacks will be ordered + /// on battlefield according to this scheme: + /// 4 7 1 + /// + /// 6 5 + /// + /// 3 2 + /// Possible fields: + /// amount - size of stack + /// type - string ID of creature for this stack + /// upgradeChance - chance (in percent) for this stack to be upgraded + "guards": [ + { "amount": 4, "type": "cyclop" }, + { "amount": 4, "type": "cyclop" }, + { "amount": 4, "type": "cyclop", "upgradeChance": 50 }, + { "amount": 4, "type": "cyclop" }, + { "amount": 4, "type": "cyclop" } + ], + + // How hard are guards of this level. Unused? + "combat_value": 506, + + /// Description of rewards granted for clearing bank + "reward" : { + + /// Approximate value of reward, known to AI. Unused? + "value": 10000, + + /// Granted resources + "resources": { + "wood" : 4, + "mercury" : 4, + "ore" : 4, + "sulfur" : 4, + "crystal" : 4, + "gems" : 4, + "gold" : 0 + }, + + /// Granted creatures, same format as guards + "creatures" : [ + { "amount": 4, "type": "wyvern" } + ], + + /// List of random artifacts + "artifacts": [ { "class" : "TREASURE" } ] + + /// List of spells + "spells" : [ { "level" : 5 } ] + } + } + } + ] +} +``` \ No newline at end of file diff --git a/docs/modders/Map objects/Dwelling.md b/docs/modders/Map objects/Dwelling.md new file mode 100644 index 000000000..7eab2325a --- /dev/null +++ b/docs/modders/Map objects/Dwelling.md @@ -0,0 +1,22 @@ +This is description of fields for creature banks, part of [Object +Format](Object_Format "wikilink") + +``` javascript +{ + /// List of creatures in this bank. Each list represents one "level" of bank + /// Creatures on the same level will have shared growth and available number (similar to towns) + /// Note that due to GUI limitation it is not recommended to have more than 4 creatures at once + "creatures" : [ + [ "airElemental", "stormElemental" ], + [ "waterElemental" ] + ], + + /// List of guards for this dwelling. Can have two possible values: + /// Boolean true/false - If set to "true", guards will be generated using H3 formula: + /// 3 week growth of first available creatures + /// List of objects - custom guards, each entry represent one stack in defender army + "guards" : [ + { "amount" : 12, "type" : "earthElemental" } + ] +} +``` \ No newline at end of file diff --git a/docs/modders/Random map template.md b/docs/modders/Random map template.md new file mode 100644 index 000000000..ddca51ff0 --- /dev/null +++ b/docs/modders/Random map template.md @@ -0,0 +1,101 @@ +Ideally, template format should be 100% compatible with OH3 format and +bring additional improvements. + +## List of currently available templates + +- Analogy +- Upgrade +- Golden Ring +- Unfair Game +- Jebus Cross + +## Template format + +``` javascript +/// Unique template name +"Triangle" : +{ + //optional name - useful to have several template variations with same name (since 0.99) + "name" : "Custom template name", + "description" : "Brief description of template, recommended setting or rules". + + /// Minimal and maximal size of the map. Possible formats: + /// Size code: s, m, l or xl for size with optional suffix "+u" for underground + /// Numeric size, e.g. 120x120x1 (width x height x depth). Note that right now depth can only be 0 or 1 + "minSize" : "m", + "maxSize" : "xl+u", + + /// Number of players that will be present on map (human or AI) + "players" : "2-4", + + /// Number of AI-only players + "cpu" : "2", + + ///Optional parameter allowing to prohibit some water modes. All modes are allowed if parameter is not specified + "allowedWaterContent" : ["none", "normal", "islands"] + + /// List of named zones, see below for format description + "zones" : + { + "zoneA" : { ... }, + "zoneB" : { ... }, + "zoneC" : { ... } + }, + "connections" : + [ + { "a" : "zoneA", "b" : "zoneB", "guard" : 5000, "road" : "false" }, + { "a" : "zoneA", "b" : "zoneC", "guard" : 5000, "road" : "random" }, + { "a" : "zoneB", "b" : "zoneC", "type" : "wide" } + //"type" can be "guarded" (default), "wide", "fictive" or "repulsive" + //"wide" connections have no border, or guard. "fictive" and "repulsive" connections are virtual - + //they do not create actual path, but only attract or repulse zones, respectively + ] +} +``` + +## Zone format + +``` javascript +{ + "type" : "playerStart", //"cpuStart" "treasure" "junction" + "size" : 2, //relative size of zone + "owner" : 1, //player owned this zone + "playerTowns" : { + "castles" : 1 + //"towns" : 1 + }, + "neutralTowns" : { + //"castles" : 1 + "towns" : 1 + }, + "townsAreSameType" : true, + "monsters" : "normal", //"weak" "strong", "none" - All treasures will be unguarded + + "terrainTypes" : [ "sand" ], //possible terrain types. All terrains will be available if not specified + "bannedTerrains" : ["lava", "asphalt"] //optional + + "matchTerrainToTown" : false, //if true, terrain for this zone will match native terrain of player faction + "minesLikeZone" : 1, + "treasureLikeZone" : 1 + "terrainTypeLikeZone" : 3 + + "allowedMonsters" : ["inferno", "necropolis"] //factions of monsters allowed on this zone + "bannedMonsters" : ["fortress", "stronghold", "conflux"] //These monsers will never appear in the zone + "allowedTowns" : ["castle", "tower", "rampart"] //towns allowed on this terrain + "bannedTowns" : ["necropolis"] //towns will never spawn on this terrain + + "mines" : { + "wood" : 1, + "ore" : 1, + }, + + "treasure" : [ + { + "min" : 2100, + "max": 3000, + "density" : 5 + } + ... + ] +} +``` \ No newline at end of file diff --git a/docs/players/Game mechanics.md b/docs/players/Game mechanics.md new file mode 100644 index 000000000..401f768f5 --- /dev/null +++ b/docs/players/Game mechanics.md @@ -0,0 +1,55 @@ +# List of bugs fixed in VCMI + +These bugs were present in original Shadow of Death game, however the +team decided to fix them to bring back desired behaviour. + +# List of game mechanics changes + +Some of H3 mechanics can't be straight considered as bug, but default +VCMI behaviour is different: + +- Dwellings. Remain creatures are accumulated instead of reset each + week. Can be disabled using DWELLINGS_ACCUMULATE_CREATURES. +- Pathfinding. Hero can't grab artifact while flying when all tiles + around it are guarded without triggering attack from guard. Original + behavior can be re-enabled using "originalMovementRules" pathfinder + option. +- Battles. Hero that won battle, but only have temporary summoned + creatures alive going to appear in tavern like if he retreated. Can + be disabled using WINNING_HERO_WITH_NO_TROOPS_RETREATS. +- Battles. Spells from artifacts like AOTD are autocasted on beginning + of the battle, not beginning of turn. Task on mantis: + [1](https://bugs.vcmi.eu/view.php?id=1347) +- Objects. Black market changes artifacts every month like town + artifact merchants do. Can be disabled using + BLACK_MARKET_MONTHLY_ARTIFACTS_CHANGE. +- Spells. Dimension Door spell doesn't allow to teleport to unexplored + tiles. Task on mantis to track this: + [2](https://bugs.vcmi.eu/view.php?id=2751). + +# List of extended game functionality + +- Quick army management in the garrison screen: + +` [LShift] + LClick – splits a half units from the selected stack into` +` an empty slot.` +` [LCtrl] + LClick – splits a single unit from the selected stack into` +` an empty slot.` +` [LCtrl] + [LShift] + LClick – split single units from the selected` +` stack into all empty hero/garrison slots` +` [Alt] + LClick – merge all splitted single units into one stack` +` [Alt] + [LCtrl] + LClick - move all units of selected stack to the city's garrison or to the met hero` +` [Alt] + [LShift] + LClick - dismiss selected stack` + +- Mouse click on castle icon in the town screen open quick recruitment + window, where we can purhase in fast way units. + +# Manuals and guides + +- \[? + Official Heroes of Might & Magic III user manual\] +- \[? + Strategija\] covers detailed machanics not mentioned in official + documents. +- \[? + New WoG features\] \ No newline at end of file diff --git a/docs/players/Installation on Android.md b/docs/players/Installation on Android.md new file mode 100644 index 000000000..0436c517d --- /dev/null +++ b/docs/players/Installation on Android.md @@ -0,0 +1,63 @@ +# Download and install VCMI + +**This app requires original heroes 3 sod / complete files to operate, +they are not supplied with this installer. it is recommended to purchase +version from gog.com. Heroes 3 "hd edition" (steam version) files are +not supported !!!** +Installation is a two step process, at first you need to install game, +then you need to upload Heroes3 original data files into your android +device. + +- Latest release on Google Play (recommended): + +- Latest release as .apk file: + +- Daily builds (unstable): + + +# Installing Heroes III data files + +- Install Heroes III on your PC or extract Heroes III data files from + gog installer + + + +- Connect your device to PC and enable file transfer. + + + +- Copy "Data", "Maps" and "Mp3" from Heroes III to any folder on + mobile device, then open VCMI, select Heroes III data import option, + then select the folder where you copied Heroes III data. + +# Troubleshooting / well known issues + +## The game crashes on start + +**Please double check that you copied original SoD/Complete game files +into your Android Device** + +## I installed google play version, but have a problem while installing daily builds + +**Solution:** Uninstall google play version first, before installing +daily build version. + +## I installed play version, but the screen is flashing / blank on its edges + +**Solution:** Should be fixed since VCMI 1.3 + +## The game always starts in 800x600 resolution, cannot effectively change it, also there is a lot of blank space on my widescreen device + +**Solution:** Should be fixed since VCMI 1.3 onwards. + +If you use version 1.2 or older - please download "VCMI-extras" mod from +VCMI Launcher. Resolution setting 1024x600 is better than original +800x600 for widescreen mobile phones. + +## Other problems + +- Please report about gameplay problem on forums: [Help & + Bugs](https://forum.vcmi.eu/c/international-board/help-bugs) or + [Discord](https://discord.gg/chBT42V) + +Make sure to specify your device and used version of Android. \ No newline at end of file diff --git a/docs/players/Installation on Linux.md b/docs/players/Installation on Linux.md new file mode 100644 index 000000000..b3772b1ba --- /dev/null +++ b/docs/players/Installation on Linux.md @@ -0,0 +1,158 @@ +VCMI requires data from original Heroes 3: Shadow of Death or Complete +editions. Data from native Linux version made by LOKI will not work. + +# Binaries installation + +## Ubuntu + +**Latest stable build from PPA (recommended)** + +Up-to-date releases can be found in our PPA here: + + +To install VCMI from PPA use: + + sudo apt-add-repository ppa:vcmi/ppa + sudo apt update + sudo apt install vcmi + +**Unstable testing build from PPA** + +We also provide latest, unstable builds mostly suitable for testing +here: + +In order to install from this PPA use: + + sudo add-apt-repository ppa:vcmi/vcmi-latest + sudo apt update + sudo apt install vcmi + +**From Ubuntu repository** + +VCMI stable builds available in "multiverse" repository. Learn how to +enable it in [Ubuntu +wiki](https://help.ubuntu.com/community/Repositories/Ubuntu). + +Once enabled, you can install VCMI using Ubuntu Store or in terminal +using following commands: + + sudo apt update + sudo apt install vcmi + +Note that version available in Ubuntu is outdated. Install via PPA is +preferred. + +## Debian + +Stable VCMI version is available in "contrib" repository. Learn how to +enable it in [Debian wiki](https://wiki.debian.org/SourcesList). + +To install VCMI from repository: + + sudo apt-get update + sudo apt-get install vcmi + +## Flatpak (distribution-agnostic) + +Latest public release build can be installed via Flatpak. + +Depending on your distribution, you may need to install flatpak itself. +You can find guide for your distribution here: + + +Once you have flatpak, you can install VCMI package which can be found +here: + +## Other distributions + +For other distributions, VCMI can be installed from 3rd-party +repositories listed below. +Note that these repositories are not supported by vcmi team and may not +be up to date. + +- Archlinux [vcmi](https://aur.archlinux.org/packages/vcmi/) + [vcmi-git](https://aur.archlinux.org/packages/vcmi-git/) +- openSUSE [1 Click + Install](https://software.opensuse.org/download.html?project=games&package=vcmi) + +If you are interested in providing builds for other distributions, +please let us know. + +## Compiling from source + +Please check following developer guide: [How to build VCMI +(Linux)](How_to_build_VCMI_(Linux) "wikilink") + +# Installing Heroes III data files + +To install VCMI you will need Heroes III: Shadow of Death or Complete +edition. + +## Install data using vcmibuilder script (recommended for non-Flatpak installs) + +To install Heroes 3 data using automated script you need any of: + +- Offline Installer downloaded from gog.com (both .exe and .bin files + are required) +- Directory with preinstalled game +- One or two CD's or CD images + +Run the script using options appropriate to your input files: + + vcmibuilder --cd1 /path/to/iso/or/cd --cd2 /path/to/second/cd + vcmibuilder --gog /path/to/gog.com/installer.exe + vcmibuilder --data /path/to/h3/data + +You should use only one of these commands. + +On flatpak install, it's also possible to run the script, but any path +seems to be interpreted from within the Flatpak sandbox: + + flatpak run --command=vcmibuilder eu.vcmi.VCMI --data /path/to/h3/data` + +## Install data using gog.com offline installer + +Download both files for the "offline backup game installers" and extract +them using innoextract tool + + innoextract --output-dir=~/Downloads/HoMM3 "setup_heroes_of_might_and_magic_3_complete_4.0_(28740).exe" + +(note that installer file name might be different) + +Once innoextract completes, start VCMI Launcher and choose to copy +existing files. Select the ~/Downloads/HoMM3 directory. Once copy is +complete, you can delete both offline installer files as well as +~/Downloads/HoMM3. + +## Install using existing Heroes III data + +Copy "Data", "Maps" and "Mp3" from Heroes III to: + + $HOME/.local/share/vcmi/ + +Or, in case of flatpak install to + + $HOME/.var/app/eu.vcmi.VCMI/data/vcmi/ + +On some distributions $XDG_DATA_HOME could differ so instead you may +need to use: + + $XDG_DATA_HOME/vcmi/ + +# Launching game + +To start the game type in console: + + vcmilauncher + +Or, to start game directly avoiding Launcher: + + vcmiclient + +VCMI should be also available via desktop environment menu or launcher +(Games/Strategy/VCMI) + +# Reporting bugs + +Please report any issues with packages according to [Bug reporting +guidelines](http://wiki.vcmi.eu/index.php?title=Bug_reporting_guidelines) \ No newline at end of file diff --git a/docs/players/Installation on Windows.md b/docs/players/Installation on Windows.md new file mode 100644 index 000000000..89c95d6e7 --- /dev/null +++ b/docs/players/Installation on Windows.md @@ -0,0 +1,51 @@ +# Step 1: Download and install VCMI + +Install one of following into new folder, same as when installing new +game: + +- Latest release (recommended): + +- Daily builds (unstable): + +- Please report about problems on GitHub: [Bug + Tracker](https://github.com/vcmi/vcmi/issues) + +# Step 2: Installing Heroes III data files + +**Since VCMI 1.2 you can skip this step, just run VCMI launcher and it +will help you with importing H3 data. For older releases you can follow +this step.** + +- Install Heroes III from disk or using GOG installer. + + + +- Copy "Data", "Maps" and "Mp3" from Heroes III to: + + + + %USERPROFILE%\Documents\My Games\vcmi\ + +Create this folder if it doesnt exist yet + +# Step 3: (for release 1.0.0 and above) connect to the mod repository + +- If that's your first installation, connection to the mod repository + will be configured automatically, you'll see mods available to + install from VCMI launcher + - We recommend you to install VCMI extras to support various + helpful UI tweaks and (before 1.3) support for different screen + resolutions + +# Step 3: (for old builds 0.99 and earlier) download and copy and enable Essential Package + +- Skip this step if you installed 1.0.0 or latest daily build +- For some technical reasons it wasn't included in game installation + package for legacy versions and needs to be downloaded and activated + seperately +- Download "VCMI essential files mods" from here + +- After unpacking, copy folder Mods to your main VCMI directory +- When launching game, please enable "VCMI essential files" as well as + its sub-elements: Andruids Bonus Icons, Bonus Icons, Spell Immunity + bonus icons, Extra resolutions and Default templates. \ No newline at end of file diff --git a/docs/players/Installation on iOS.md b/docs/players/Installation on iOS.md new file mode 100644 index 000000000..5d0073523 --- /dev/null +++ b/docs/players/Installation on iOS.md @@ -0,0 +1,98 @@ +You can run VCMI on iOS 12.0 and later, all devices are supported. If +you wish to run on iOS 10 or 11, you should build from source, see [How +to build VCMI (iOS)](How_to_build_VCMI_(iOS) "wikilink"). + +## Download and install VCMI + +The latest release (recommended): + + +Daily builds: + +To run on a non-jailbroken device you need to sign the IPA file, you +have the following options: + +- *\[Easiest way\]* [AltStore](https://altstore.io/) or + [Sideloadly](https://sideloadly.io/) - can be installed on Windows + or macOS, don't require dealing with signing on your own +- if you're on iOS 14.0-15.4.1, you can try + +- Get signer tool + [here](https://dantheman827.github.io/ios-app-signer/) and a guide + [here](https://forum.kodi.tv/showthread.php?tid=245978) (it's for + Kodi, but the logic is the same). Signing with this app can only be + done on macOS. +- [Create signing assets on macOS from + terminal](https://github.com/kambala-decapitator/xcode-auto-signing-assets). + In the command replace `your.bundle.id` with something like + `com.MY-NAME.vcmi`. After that use the above signer tool. +- [Sign from any + OS](https://github.com/indygreg/PyOxidizer/tree/main/tugger-code-signing). + You'd still need to find a way to create signing assets (private key + and provisioning profile) though. + +## Installing Heroes III data files + +*Note: if you don't need in-game videos, you can omit +downloading/copying file VIDEO.VID from data folder - it will save your +time and space. The same applies to the Mp3 directory.* + +### Installing data files with Finder or Windows explorer + +To play the game, you need to upload HoMM3 data files - **Data**, +**Maps** and **Mp3** directories - to the device. Use Finder (or iTunes, +if you're on Windows or your macOS is 10.14 or earlier) for that. You +can also add various [mods](https://wiki.vcmi.eu/Mod_list) by uploading +**Mods** directory. Follow [official Apple +guide](https://support.apple.com/en-us/HT210598) and place files into +VCMI app. Unfortunately, Finder doesn't display copy progress, give it +about 10 minutes to finish. + +### Installing data files using iOS device only + +If you have data somewhere on device or in shared folder or you have +downloaded it, you can copy it directly on your iPhone/iPad using Files +application. + +Just move/copy **Data**, **Maps** and **Mp3** folders into vcmi +application - it will be visible in Files along with other applications' +folders. + +### Installing data files with Xcode on macOS + +You can also upload files with Xcode. You need to prepare "container" +for that. + +1. Connect your device to your Mac +2. Start Xcode +3. Open Devices and Simulators window: Cmd+Shift+2 or Menu - Window - + Devices and Simulators +4. Select your device +5. Select VCMI +6. In the bottom find "three dots" or "cogwheel" button (it should be + next to + - buttons) - click it - select Download Container... +7. Place the game directories inside the downloaded container - + AppData - Documents +8. Click the "three dots" / "cogwheel" button in Xcode again - Replace + Container... - select the downloaded container +9. Wait until Xcode finishes copying, progress is visible (although it + might be "indefinite") + +## Game controls + +- Tap = left click +- Tap and hold (long press) = right click +- before v1.3: Pinch with 2 fingers = spacebar (visit current object) +- Tap in the bottom area (status bar) to activate chat/console in the + game + +You can start game directly (avoiding the launcher) by changing setting +in iOS Settings app - VCMI. + +## Reporting bugs + +- Please report about gameplay problem on forums: [Help & + Bugs](https://forum.vcmi.eu/c/international-board/help-bugs) +- Please report iOS-specific issues in [this forum + thread](https://forum.vcmi.eu/t/ios-port/820) or (better) at + [GitHub](https://github.com/vcmi/vcmi/issues) with **iOS** label \ No newline at end of file diff --git a/docs/players/Installation on macOS.md b/docs/players/Installation on macOS.md new file mode 100644 index 000000000..3f15113f6 --- /dev/null +++ b/docs/players/Installation on macOS.md @@ -0,0 +1,50 @@ +**For iOS installation look here: +** + +# Download and install VCMI + +- The latest release (recommended): + +- Daily builds (might be unstable) + - Intel (x86_64) builds: + + - Apple Silicon (arm64) builds: + + +If the app doesn't open, right-click the app bundle - select *Open* menu +item - press *Open* button. + +Please report about gameplay problem on forums: [Help & +Bugs](https://forum.vcmi.eu/c/international-board/help-bugs) + +If your problem is Mac-specific: DMG corrupted or if it doesn't start +please use following topic: + +- [VCMI for macOS](https://forum.vcmi.eu/t/macos-builds/550) + +Make sure to specify what hardware and macOS version you use. + +# Installing Heroes III data files + +1. Find a way to unpack Windows Heroes III or GOG installer. For + example, use `vcmibuilder` script inside app bundle or install the + game with [CrossOver](https://www.codeweavers.com/crossover) / + [Wineskin](https://github.com/Gcenx/WineskinServer). +2. Copy (or symlink) **Data**, **Maps** and **Mp3** directories from + Heroes III to: + + + + ~/Library/Application\ Support/vcmi/ + +# Connect to the mod repository (optional) + +- If that's your first installation, connection to the mod repository + will be configured automatically, you'll see mods available to + install from VCMI launcher + - We recommend you to install VCMI extras to support different + screen resolutions and active various helpful UI tools + - If you don't see mods available to install, go to settings tab + of the launcher and make sure that you have correct link in + "repositories" text field: + -