Merge branch 'master' of gitlab.com:veloren/veloren into sharp/small-fixes

This commit is contained in:
Joshua Yanovski 2020-05-21 17:53:57 +02:00
commit f8376fd5dc
107 changed files with 1382 additions and 234 deletions

View File

@ -9,6 +9,18 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added
- Added context-sensitive crosshair
### Changed
- Improved camera aiming
### Removed
## [0.6.0] - 2020-05-16
### Added
- Added music system
- Added zoomable and rotatable minimap
- Added rotating orientation marker to main-map
@ -73,6 +85,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Added tab completion in chat for player names and chat commands
- Added server persistence for character stats
- Added a popup when setting your character's waypoint
- Added dungeon arenas
- Added dungeon bosses and rare boss loot
- Added 2 sets of armour. One Steel and one Leather.
### Changed
@ -96,7 +112,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Removed
## [0.5.0] - 2019-01-31
## [0.5.0] - 2020-01-31
### Added
@ -260,9 +276,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
_0.1.0 was part of the legacy engine_
[unreleased]: https://gitlab.com/veloren/veloren/compare?from=v0.5.0&to=master
[0.0.5]: https://gitlab.com/veloren/veloren/compare?from=v0.4.0&to=v0.5.0
[0.0.4]: https://gitlab.com/veloren/veloren/compare?from=v0.3.0&to=v0.4.0
[0.0.3]: https://gitlab.com/veloren/veloren/compare?from=v0.2.0&to=v0.3.0
[0.0.2]: https://gitlab.com/veloren/veloren/compare?from=7d17f8b67a2a6d5aa00730f028cedc430fd5075a&to=v0.2.0
[0.0.1]: https://gitlab.com/veloren/game
[unreleased]: https://gitlab.com/veloren/veloren/compare?from=v0.6.0&to=master
[0.6.0]: https://gitlab.com/veloren/veloren/compare?from=v0.5.0&to=v0.6.0
[0.5.0]: https://gitlab.com/veloren/veloren/compare?from=v0.4.0&to=v0.5.0
[0.4.0]: https://gitlab.com/veloren/veloren/compare?from=v0.3.0&to=v0.4.0
[0.3.0]: https://gitlab.com/veloren/veloren/compare?from=v0.2.0&to=v0.3.0
[0.2.0]: https://gitlab.com/veloren/veloren/compare?from=7d17f8b67a2a6d5aa00730f028cedc430fd5075a&to=v0.2.0
[0.1.0]: https://gitlab.com/veloren/game

14
Cargo.lock generated
View File

@ -4959,7 +4959,7 @@ dependencies = [
[[package]]
name = "veloren-chat-cli"
version = "0.5.0"
version = "0.6.0"
dependencies = [
"log 0.4.8",
"pretty_env_logger",
@ -4969,7 +4969,7 @@ dependencies = [
[[package]]
name = "veloren-client"
version = "0.5.0"
version = "0.6.0"
dependencies = [
"authc",
"byteorder 1.3.4",
@ -4988,7 +4988,7 @@ dependencies = [
[[package]]
name = "veloren-common"
version = "0.5.0"
version = "0.6.0"
dependencies = [
"authc",
"bincode",
@ -5020,7 +5020,7 @@ dependencies = [
[[package]]
name = "veloren-server"
version = "0.5.0"
version = "0.6.0"
dependencies = [
"authc",
"chrono",
@ -5051,7 +5051,7 @@ dependencies = [
[[package]]
name = "veloren-server-cli"
version = "0.5.0"
version = "0.6.0"
dependencies = [
"log 0.4.8",
"pretty_env_logger",
@ -5061,7 +5061,7 @@ dependencies = [
[[package]]
name = "veloren-voxygen"
version = "0.5.0"
version = "0.6.0"
dependencies = [
"authc",
"backtrace",
@ -5113,7 +5113,7 @@ dependencies = [
[[package]]
name = "veloren-world"
version = "0.5.0"
version = "0.6.0"
dependencies = [
"arr_macro",
"bincode",

View File

@ -1,5 +1,5 @@
<p align="center">
<img alt="Veloren logo on a screenshot" src="https://i.redd.it/balynnef4x531.png">
<img alt="Veloren logo on a screenshot" src="https://cdn.discordapp.com/attachments/541307708146581519/712295605170602075/logo.png">
</p>
[![pipeline status](https://gitlab.com/veloren/veloren/badges/master/pipeline.svg)](https://gitlab.com/veloren/veloren/commits/master)
@ -36,7 +36,7 @@ This will be needed to play on auth-enabled servers, including the official serv
Currently we provide 64-bit builds for Linux and Windows which can be downloaded on the official website:
[https://www.veloren.net](https://veloren.net/welcome)
*Note: Mac and 32-bit systems are supported but you need to [compile the game for them yourself](https://book.veloren.net/compile/index.html).*
_Note: Mac and 32-bit systems are supported but you need to [compile the game for them yourself](https://book.veloren.net/compile/index.html)._
Due to rapid developement stable versions become outdated fast and might be **incompatible with the public server**.
@ -59,6 +59,7 @@ If you want to compile Veloren yourself, take a look at the [How to Compile Guid
[AUR latest master](https://aur.archlinux.org/packages/veloren-git): `yay -Syu veloren-git`
## F.A.Q.
### **Q:** How is this game licensed?
**A:** **It's free to play, modify and distribute. Forever.** Since it is a community project, we decided to license it under the **GNU GPL 3.0** license which means it will always stay free and open source.

View File

@ -0,0 +1,8 @@
Item(
name: "Leather Belt",
description: "A belt made from simple leather.",
kind: Armor(
kind: Belt(Leather2),
stats: (20),
),
)

View File

@ -0,0 +1,8 @@
Item(
name: "Steel Belt",
description: "A belt made from Steel.",
kind: Armor(
kind: Belt(Steel0),
stats: (20),
),
)

View File

@ -0,0 +1,8 @@
Item(
name: "Leather Cuirass",
description: "A cuirass made of simple leather",
kind: Armor(
kind: Chest(Leather2),
stats: (20),
),
)

View File

@ -0,0 +1,8 @@
Item(
name: "Steel Cuirass",
description: "A cuirass of steel plate",
kind: Armor(
kind: Chest(Steel0),
stats: (20),
),
)

View File

@ -0,0 +1,8 @@
Item(
name: "Leather Boots",
description: "Boots made of simple leather",
kind: Armor(
kind: Foot(Leather2),
stats: (20),
),
)

View File

@ -0,0 +1,8 @@
Item(
name: "Steel Boots",
description: "Boots plated in steel",
kind: Armor(
kind: Foot(Steel0),
stats: (20),
),
)

View File

@ -0,0 +1,8 @@
Item(
name: "Leather Gloves",
description: "Gloves made of simple leather",
kind: Armor(
kind: Hand(Leather2),
stats: (20),
),
)

View File

@ -0,0 +1,8 @@
Item(
name: "Steel Gauntlets",
description: "Gauntlets made of steel",
kind: Armor(
kind: Hand(Steel0),
stats: (20),
),
)

View File

@ -0,0 +1,8 @@
Item(
name: "Leather Leg Armour",
description: "Leg armour made of simple leather",
kind: Armor(
kind: Pants(Leather2),
stats: (20),
),
)

View File

@ -0,0 +1,8 @@
Item(
name: "Steel Chausses",
description: "Leg armour made of steel plates",
kind: Armor(
kind: Pants(Steel0),
stats: (20),
),
)

View File

@ -0,0 +1,8 @@
Item(
name: "Leather Shoulder Pad",
description: "A simple shoulder pad made of leather",
kind: Armor(
kind: Shoulder(Leather2),
stats: (20),
),
)

View File

@ -0,0 +1,8 @@
Item(
name: "Steel Shoulder Pad",
description: "A simple shoulder pad made of steel",
kind: Armor(
kind: Shoulder(Steel0),
stats: (20),
),
)

View File

@ -0,0 +1,12 @@
Item(
name: "Black Lantern",
description: "Used by city guards.",
kind: Lantern(
(
kind: Black0,
color: (r: 255, g: 190, b: 75),
strength_thousandths: 3000,
flicker_thousandths: 300,
),
),
)

View File

@ -0,0 +1,12 @@
Item(
name: "Magic Lantern",
description: "Illuminates even the darkest dungeon\nA great monster was slain for this item",
kind: Lantern(
(
kind: Blue0,
color: (r: 220, g: 220, b: 255),
strength_thousandths: 6500,
flicker_thousandths: 300,
),
),
)

View File

@ -0,0 +1,12 @@
Item(
name: "Powerful Potion",
description: "Restores 100 Health\nA great monster was slain for this item\n\n<Right-Click to use>",
kind: Consumable(
kind: Potion,
effect: Health((
amount: 100,
cause: Item,
)),
amount: 15,
),
)

View File

@ -0,0 +1,8 @@
Item(
name: "Potion of Skill",
description: "Provides 250 XP to the drinker\n\n<Right-Click to use>",
kind: Consumable(
kind: Potion,
effect: Xp(250),
),
)

View File

@ -1,5 +1,14 @@
// TODO: Re-add tunes that are not fitting general outside day/night situations
(
tracks: [
(
title: "Into The Dark Forest",
path: "voxygen.audio.soundtrack.into_the_dark_forest",
length: 184.0,
timing: Some(Night),
artist: "Aeronic",
),
(
title: "Field Grazing",
path: "voxygen.audio.soundtrack.field_grazing",
@ -14,13 +23,13 @@
timing: Some(Night),
artist: "Aeronic",
),
(
title: "Snowtop Volume",
/*(
title: "Snowtop Volume", //Snow Region
path: "voxygen.audio.soundtrack.snowtop_volume",
length: 89.0,
timing: Some(Day),
artist: "Aeronic",
),
),*/
(
title: "Mineral Deposits",
path: "voxygen.audio.soundtrack.mineral_deposits",
@ -42,13 +51,13 @@
timing: Some(Night),
artist: "Aeronic",
),
(
title: "Rest Assured",
/*(
title: "Rest Assured", // Town/Shop
path: "voxygen.audio.soundtrack.rest_assured",
length: 185.0,
timing: Some(Day),
artist: "badbbad",
),
),*/
(
title: "Just The Beginning",
path: "voxygen.audio.soundtrack.just_the_beginning",
@ -70,13 +79,13 @@
timing: Some(Night),
artist: "badbbad",
),
(
/*( // Dungeon
title: "Down The Rabbit Hole",
path: "voxygen.audio.soundtrack.down_the_rabbit_hole",
length: 244.0,
timing: Some(Night),
artist: "badbbad",
),
),*/
(
title: "Between The Fairies",
path: "voxygen.audio.soundtrack.between_the_fairies",

BIN
assets/voxygen/audio/soundtrack/into_the_dark_forest.ogg (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/voxygen/background/bg_1.png (Stored with Git LFS)

Binary file not shown.

BIN
assets/voxygen/background/bg_12.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/voxygen/background/bg_13.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/voxygen/background/bg_14.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/voxygen/background/bg_15.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/voxygen/background/bg_16.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/voxygen/background/bg_3.png (Stored with Git LFS)

Binary file not shown.

BIN
assets/voxygen/background/bg_main.png (Stored with Git LFS)

Binary file not shown.

BIN
assets/voxygen/element/help.png (Stored with Git LFS)

Binary file not shown.

View File

@ -54,7 +54,7 @@ VoxygenLocalization(
"common.controls": "Tastenbelegung",
"common.video": "Grafik",
"common.sound": "Audio",
"common.resume": "Weiter",
"common.resume": "Zurück",
"common.characters": "Charaktere",
"common.close": "Schließen",
"common.yes": "Ja",
@ -136,6 +136,7 @@ eurer erstellen Charaktere gespeichert."#,
"main.login.already_logged_in": "Ihr seid bereits eingelogged",
"main.login.network_error": "Netzwerkfehler",
"main.login.failed_sending_request": "Authentifizierung fehlgeschlagen",
"main.login.invalid_character": "Ungültiger Charakter",
"main.login.client_crashed": "Client abgestürzt",
/// End Main screen section
@ -146,6 +147,7 @@ eurer erstellen Charaktere gespeichert."#,
"hud.show_tips": "Tips zeigen.",
"hud.quests": "Quests",
"hud.you_died": "Ihr seid gestorben.",
"hud.waypoint_saved": "Wegpunkt gesichert",
"hud.press_key_to_show_keybindings_fmt": "Drückt {key} um die Tastenbelegung zu zeigen",
"hud.press_key_to_show_debug_info_fmt": "Drückt {key} um die Debug-Info zu zeigen",
@ -173,7 +175,7 @@ Sammelt diese mit Rechts-Klick auf.
Um diese zu nutzen öffnet euer Inventar mit 'B'.
Doppelklickt den Gegenstand in eurer Tasche, um dieses zu nutzen.
Doppelklickt den Gegenstand in eurer Tasche, um diesen zu nutzen.
Um Items wegzuwerfen klickt sie einmal im Inventar an
@ -182,7 +184,7 @@ und klickt dann außerhalb der Tasche.
Die Nächte in Veloren können sehr dunkel werden.
Um eure Laterne anzuzünden gebt /lantern in den Chat ein.
Drückt 'G' um eure Laterne einzuschalten.
Ihr wollt endlich spielen und dafür euren Cursor befreien,
@ -317,6 +319,7 @@ Viel Spaß in der Welt von Veloren, Abenteurer!"#,
"gameinput.climb": "Klettern",
"gameinput.climbdown": "Runter klettern",
"gameinput.wallleap": "Wandsprung",
"gameinput.togglelantern": "Laterne ein-/ausschalten",
"gameinput.mount": "Aufsteigen",
"gameinput.enter": "Betreten",
"gameinput.command": "Befehl",
@ -336,11 +339,14 @@ Viel Spaß in der Welt von Veloren, Abenteurer!"#,
/// End GameInput section
/// Start chracter selection section
"char_selection.loading_characters": "Lade Charaktere...",
"char_selection.delete_permanently": "Diesen Charakter unwiderruflich löschen?",
"char_selection.deleting_character": "Lösche Charakter...",
"char_selection.change_server": "Server wechseln.",
"char_selection.enter_world": "Betreten",
"char_selection.logout": "Logout",
"char_selection.logout": "Ausloggen",
"char_selection.create_charater": "Charakter erstellen",
"char_selection.creating_character": "Erstelle Charakter...",
"char_selection.character_creation": "Charakter Erstellung",
"char_selection.create_new_charater": "Neuen Charakter erstellen",
@ -356,6 +362,7 @@ Viel Spaß in der Welt von Veloren, Abenteurer!"#,
"char_selection.skin": "Hautton",
"char_selection.eyebrows": "Augenbrauen",
"char_selection.accessories": "Accessoires",
"char_selection.create_info_name": "Euer Charakter braucht einen Namen!",
/// End chracter selection section
/// Start character window section
"character_window.character_name": "Charakter",

View File

@ -182,7 +182,7 @@ Throw them away by clicking them once and clicking outside of the bag
Nights can get pretty dark in Veloren.
Equip your lantern and light it by pressing G.
Light your lantern by pressing 'G'
Want to free your cursor to close this window? Press TAB!
@ -351,7 +351,7 @@ Enjoy your stay in the World of Veloren."#,
"char_selection.human_default": "Human Default",
"char_selection.level_fmt": "Level {level_nb}",
"char_selection.uncanny_valley": "Uncanny Valley",
"char_selection.uncanny_valley": "Wilderness",
"char_selection.plains_of_uncertainty": "Plains of Uncertainty",
"char_selection.beard": "Beard",
"char_selection.hair_style": "Hair Style",
@ -361,6 +361,7 @@ Enjoy your stay in the World of Veloren."#,
"char_selection.skin": "Skin",
"char_selection.eyebrows": "Eyebrows",
"char_selection.accessories": "Accessories",
"char_selection.create_info_name": "Your Character needs a name!",
/// End chracter selection section

View File

@ -17,7 +17,7 @@
VoxygenLocalization(
metadata: (
language_name: "Italiano",
language_identifier: "it",
language_identifier: "it_IT",
),
convert_utf8_to_ascii: false,
fonts: {

View File

@ -0,0 +1,369 @@
/// Localization for "global" Russian
VoxygenLocalization(
metadata: (
language_name: "Русский",
language_identifier: "ru_RU",
),
convert_utf8_to_ascii: false,
fonts: {
"opensans": Font (
asset_key: "voxygen.font.OpenSans-Regular",
scale_ratio: 1.0,
),
"metamorph": Font (
asset_key: "voxygen.font.Metamorphous-Regular",
scale_ratio: 1.0,
),
"alkhemi": Font (
asset_key: "voxygen.font.Alkhemikal",
scale_ratio: 1.0,
),
"wizard": Font (
asset_key: "voxygen.font.wizard",
scale_ratio: 1.0,
),
"cyri": Font (
asset_key: "voxygen.font.haxrcorp_4089_cyrillic_altgr_extended",
scale_ratio: 1.0,
),
},
string_map: {
/// Start Common section
// Texts used in multiple locations with the same formatting
"common.username": "Имя пользователя",
"common.singleplayer": "Одиночная игра",
"common.multiplayer": "Мультиплеер",
"common.servers": "Сервера",
"common.quit": "Выход",
"common.settings": "Настройки",
"common.languages": "Язык",
"common.interface": "Интерфейс",
"common.gameplay": "Геймплей",
"common.controls": "Управление",
"common.video": "Видео",
"common.sound": "Звук",
"common.resume": "Продолжить",
"common.characters": "Персонажи",
"common.close": "Закрыть",
"common.yes": "Да",
"common.no": "Нет",
"common.back": "Назад",
"common.create": "Создать",
"common.okay": "Хорошо",
"common.accept": "Принять",
"common.disclaimer": "Дисклеймер",
"common.cancel": "Отмена",
"common.none": "Нет",
"common.error": "Ошибка",
"common.fatal_error": "Критическая ошибка",
// Message when connection to the server is lost
"common.connection_lost": r#"Соединение потеряно!
Сервер перезагрузился?
Клиент обновлен до последней версии?"#,
"common.races.orc": "Орк",
"common.races.human": "Человек",
"common.races.dwarf": "Дварф",
"common.races.elf": "Эльф",
"common.races.undead": "Нежить",
"common.races.danari": "Данари",
"common.weapons.axe": "Топор",
"common.weapons.sword": "Меч",
"common.weapons.staff": "Посох",
"common.weapons.bow": "Лук",
"common.weapons.hammer": "Молот",
/// End Common section
/// Start Main screen section
"main.connecting": "Подключение",
"main.creating_world": "Создание мира",
// Welcome notice that appears the first time Veloren is started
"main.notice": r#"Добро пожаловать в Veloren-Alpha!
Прежде чем начать веселье, прими во внимание следующие вещи:
- Это очень ранняя альфа. Тут есть баги, крайне незавершенный геймплей, неотполированные механики и отсутсвующие фичи.
- Если у вас есть конструктивный фидбек или сообщение об ошибке, вы можете связаться с нами через Reddit, GitLab или наш Discord-сервер.
- Veloren лицензирован GPL 3 open-source licence. Это означает, игра бесплатна, ее можно модифицировать и переделывать на свой вкус (при условии, что готовая работа тоже лицензирована GPL 3).
- Veloren - некоммерческий проект, каждый работает над ним добровольно.
Если тебе нравится, что ты видишь, милости просим присоедниться к команде разработчиков или худождественной команде!
- 'Воксельная РПГ' - самобытный жанр. ФПС тоже привыкли называть 'Клонами Дума'.
Как и они, мы пытаемся построить нишу. Эта игра не клон, ее развитие в будущем будет отличаться от существующих игр.
Спасибо за прочтение, мы надеемся, вам понравится игра!
~ Команда разработчиков Veloren"#,
// Login process description
"main.login_process": r#"Информация по входу:
Если у вас есть проблемы со входом:
Обратите внимание, что теперь вам нужен аккаунт
играть на серверах с включенной аутентификацией.
Вы можете создать аккаунт тут:
https://account.veloren.net."#,
"main.login.server_not_found": "Сервер не найден",
"main.login.authentication_error": "Ошибка аутентификации на сервер",
"main.login.server_full": "Сервер полон",
"main.login.untrusted_auth_server": "Аутентификация не пройдена",
"main.login.outdated_client_or_server": "ServerWentMad: Возможно, версии несовместимы. Проверьте наличие обновлений.",
"main.login.timeout": "Timeout: Сервер не ответил вовремя. (Перегрузка или проблемы с сетью).",
"main.login.server_shut_down": "Сервер выключен",
"main.login.already_logged_in": "Вы уже вошли на сервер.",
"main.login.network_error": "Ошибка сети",
"main.login.failed_sending_request": "Запрос аутентификации провален",
"main.login.client_crashed": "Клиент вылетел",
/// End Main screen section
/// Start HUD Section
"hud.do_not_show_on_startup": "Не показывать это при запуске",
"hud.show_tips": "Показать советы",
"hud.quests": "Квесты",
"hud.you_died": "Вы мертвы",
"hud.press_key_to_show_keybindings_fmt": "Нажмите {key}, чтобы посмотреть раскладку",
"hud.press_key_to_show_debug_info_fmt": "Нажмите {key}, чтобы показать панель отладки",
"hud.press_key_to_toggle_keybindings_fmt": "Нажмите {key}, чтобы привязать клавишу",
"hud.press_key_to_toggle_debug_info_fmt": "Нажмите {key}, чтобы переназначить панель отладки",
// Respawn message
"hud.press_key_to_respawn": r#"Нажмите {key}, чтобы возродиться на последнем костре, который вы посетили."#,
// Welcome message
"hud.welcome": r#"Добро пожаловать в Veloren-Alpha!,
Немного советов перед тем началом игры:
НАИБОЛЕЕ ВАЖНО: Чтобы установить точку спауна, напишите /waypoint в чат.
Это возможно, даже если вы уже мертвы!
Нажмите F1, чтобы увидеть доступые команды.
Напишите /help, чтобы увидеть команды чата.
В мире есть сундуки и другие рандомно генерируемые объекты!
Нажмите ПКМ, чтобы собрать их.
Чтобы использовать то, что мы нашли в сундуках, откройте свой инвентарь 'B'.
Двойной клик на предмет в инвентаре использует или экипирует его.
Чтобы выкинуть их, кликните на предмет, а потом кликите вне инвентаря.
Ночи в Veloren могут быть довольно темными.
Зажгите свой фонарь, написав /lantern в чат.
Хотите увидеть курсор, чтобы закрыть это окно? Нажмите TAB!
Наслаждайтесь миром Veloren."#,
// Inventory
"hud.bag.inventory": "Инвентарь",
"hud.bag.stats_title": "Статы",
"hud.bag.exp": "Опыт",
"hud.bag.armor": "Броня",
"hud.bag.stats": "Статы",
"hud.bag.head": "Голова",
"hud.bag.neck": "Шея",
"hud.bag.tabard": "Накидка",
"hud.bag.shoulders": "Плечи",
"hud.bag.chest": "Нагрудник",
"hud.bag.hands": "Руки",
"hud.bag.lantern": "Фонарь",
"hud.bag.belt": "Пояс",
"hud.bag.ring": "Кольцо",
"hud.bag.back": "Спина",
"hud.bag.legs": "Ноги",
"hud.bag.feet": "Ботинки",
"hud.bag.mainhand": "Главная рука",
"hud.bag.offhand": "Второстепенная рука",
// Map and Questlog
"hud.map.map_title": "Карта",
"hud.map.qlog_title": "Квесты",
// Settings
"hud.settings.general": "Общие",
"hud.settings.none": "Нет",
"hud.settings.press_behavior.toggle": "Переключить",
"hud.settings.press_behavior.hold": "Держать",
"hud.settings.help_window": "Окно помощи",
"hud.settings.debug_info": "Панель отладки",
"hud.settings.tips_on_startup": "Советы на старте",
"hud.settings.ui_scale": "Размер интерфейса",
"hud.settings.relative_scaling": "Относительное масштабирование",
"hud.settings.custom_scaling": "Пользовательское масштабирование",
"hud.settings.crosshair": "Перекрестие",
"hud.settings.transparency": "Прозрачность",
"hud.settings.hotbar": "Хотбар",
"hud.settings.toggle_shortcuts": "Отображать ярлыки",
"hud.settings.toggle_bar_experience": "Отображать полоску опыта",
"hud.settings.scrolling_combat_text": "Боевой журнал",
"hud.settings.single_damage_number": "Отдельные числа урона",
"hud.settings.cumulated_damage": "Суммарный урон",
"hud.settings.incoming_damage": "Входящий урон",
"hud.settings.cumulated_incoming_damage": "Суммарный входящий урон",
"hud.settings.energybar_numbers": "Отображение полоски энергии",
"hud.settings.values": "Значение",
"hud.settings.percentages": "Проценты",
"hud.settings.chat": "Чат",
"hud.settings.background_transparency": "Прозрачность заднего фона",
"hud.settings.pan_sensitivity": "Чувствительность камеры",
"hud.settings.zoom_sensitivity": "Чувствительность зума",
"hud.settings.invert_scroll_zoom": "Инвертировать прокрутку зума",
"hud.settings.invert_mouse_y_axis": "Инвертировать ось Y",
"hud.settings.free_look_behavior": "Настройка свободной камеры",
"hud.settings.view_distance": "Дальность прорисовки",
"hud.settings.maximum_fps": "Максимум FPS",
"hud.settings.fov": "Поле зрения (градусы)",
"hud.settings.gamma": "Гамма",
"hud.settings.antialiasing_mode": "Сглаживание",
"hud.settings.cloud_rendering_mode": "Рендер облаков",
"hud.settings.fluid_rendering_mode": "Рендер жидкостей",
"hud.settings.fluid_rendering_mode.cheap": "Низко",
"hud.settings.fluid_rendering_mode.shiny": "Высоко",
"hud.settings.cloud_rendering_mode.regular": "Обычно",
"hud.settings.fullscreen": "Полный экран",
"hud.settings.save_window_size": "Сохранить размер окна",
"hud.settings.music_volume": "Громкость музыки",
"hud.settings.sound_effect_volume": "Громкость звуковых эффектов",
"hud.settings.audio_device": "Устройство аудио",
"hud.settings.awaitingkey": "Нажми клавишу...",
"hud.social": "Социальное",
"hud.social.online": "Онлайн",
"hud.social.friends": "Друзья",
"hud.social.not_yet_available": "Пока недоступно",
"hud.social.faction": "Фракция",
"hud.social.play_online_fmt": "{nb_player} игрок(ов) онлайн",
"hud.spell": "Заклинание",
"hud.free_look_indicator": "Свободная камера активна",
/// End HUD section
/// Start GameInput section
"gameinput.primary": "Основная атака",
"gameinput.secondary": "Второстепенная атака/Блок/Прицел",
"gameinput.slot1": "Быстрый слот 1",
"gameinput.slot2": "Быстрый слот 2",
"gameinput.slot3": "Быстрый слот 3",
"gameinput.slot4": "Быстрый слот 4",
"gameinput.slot5": "Быстрый слот 5",
"gameinput.slot6": "Быстрый слот 6",
"gameinput.slot7": "Быстрый слот 7",
"gameinput.slot8": "Быстрый слот 8",
"gameinput.slot9": "Быстрый слот 9",
"gameinput.slot10": "Быстрый слот 10",
"gameinput.swaploadout": "Сменить снаряжение",
"gameinput.togglecursor": "Отображать курсор курсор",
"gameinput.help": "Отображать окно помощи",
"gameinput.toggleinterface": "Отображать интерфейс",
"gameinput.toggledebug": "Отображать FPS и экран отладки",
"gameinput.screenshot": "Сделать скриншот",
"gameinput.toggleingameui": "Отображать неймтеги",
"gameinput.fullscreen": "Включить полный экран",
"gameinput.moveforward": "Двигаться вперед",
"gameinput.moveleft": "Двигаться влево",
"gameinput.moveright": "Двигаться вправо",
"gameinput.moveback": "Двигаться назад",
"gameinput.jump": "Прыжок",
"gameinput.glide": "Глайдер",
"gameinput.roll": "Кувырок",
"gameinput.climb": "Карабкаться",
"gameinput.climbdown": "Карабкаться вниз",
"gameinput.wallleap": "Прыжок от стены",
"gameinput.mount": "Оседлать",
"gameinput.enter": "Войти",
"gameinput.command": "Командовать",
"gameinput.escape": "Выйти",
"gameinput.map": "Карта",
"gameinput.bag": "Рюкзак",
"gameinput.social": "Социальное",
"gameinput.sit": "Сесть",
"gameinput.spellbook": "Заклинания",
"gameinput.settings": "Найстройки",
"gameinput.respawn": "Возродиться",
"gameinput.charge": "Зарядить",
"gameinput.togglewield": "Достать/убрать оружие",
"gameinput.interact": "Взаимодействовать",
"gameinput.freelook": "Свободная камера",
/// End GameInput section
/// Start chracter selection section
"char_selection.delete_permanently": "Навсегда удалить этого персонажа?",
"char_selection.change_server": "Сменить сервер",
"char_selection.enter_world": "Войти в мир",
"char_selection.logout": "Выйти в меню",
"char_selection.create_new_charater": "Создать нового персонажа",
"char_selection.character_creation": "Создание персонажа",
"char_selection.human_default": "Стандартный человек",
"char_selection.level_fmt": "Уровень {level_nb}",
"char_selection.uncanny_valley": "Uncanny Valley",
"char_selection.plains_of_uncertainty": "Plains of Uncertainty",
"char_selection.beard": "Борода",
"char_selection.hair_style": "Прическа",
"char_selection.hair_color": "Цвет волос",
"char_selection.chest_color": "Цвет нагрудника",
"char_selection.eye_color": "Цвет глаз",
"char_selection.skin": "Кожа",
"char_selection.eyebrows": "Брови",
"char_selection.accessories": "Аксессуары",
/// End chracter selection section
/// Start character window section
"character_window.character_name": "Имя персонажа",
// Charater stats
"character_window.character_stats": r#"Стойкость
Выносливость
Сила воли
"#,
/// Start character window section
/// Start Escape Menu Section
"esc_menu.logout": "Выйти в меню",
"esc_menu.quit_game": "Выйти из игры",
/// End Escape Menu Section
}
)

View File

@ -263,6 +263,31 @@
"voxel.armor.shoulder.plate_right-0",
(0.0, 0.0, 0.0), (-90.0, 130.0, 0.0), 1.2,
),
//Steel0 Armor
Armor(Chest(Steel0)): VoxTrans(
"voxel.armor.chest.steel-0",
(0.0, 0.0, 0.0), (-90.0, 180.0, 0.0), 1.2,
),
Armor(Pants(Steel0)): VoxTrans(
"voxel.armor.pants.steel-0",
(0.0, 0.0, 0.0), (-90.0, 180.0, 0.0), 1.2,
),
Armor(Belt(Steel0)): VoxTrans(
"voxel.armor.belt.steel-0",
(0.0, 0.0, 0.0), (-90.0, 180.0, 0.0), 1.8,
),
Armor(Foot(Steel0)): VoxTrans(
"voxel.armor.foot.steel-0",
(0.0, 0.0, 0.0), (-95.0, 140.0, 0.0), 1.1,
),
Armor(Hand(Steel0)): VoxTrans(
"voxel.armor.hand.steel_right-0",
(0.0, -1.0, 0.0), (-90.0, 135.0, 0.0), 1.0,
),
Armor(Shoulder(Steel0)): VoxTrans(
"voxel.armor.shoulder.steel_right-0",
(0.0, 0.0, 0.0), (-90.0, 130.0, 0.0), 1.2,
),
//Leather0 Armor
Armor(Chest(Leather0)): VoxTrans(
"voxel.armor.chest.leather-0",
@ -284,12 +309,38 @@
"voxel.armor.hand.leather_right-0",
(0.0, -1.0, 0.0), (-90.0, 135.0, 0.0), 1.0,
),
Armor(Shoulder(Leather0)): VoxTrans(
"voxel.armor.shoulder.leather_right-0",
(0.0, 0.0, 0.0), (-90.0, 130.0, 0.0), 1.2,
),
//Leather1 Armor
Armor(Shoulder(Leather1)): VoxTrans(
"voxel.armor.shoulder.leather_right-1",
(0.0, 0.0, 0.0), (-90.0, 130.0, 0.0), 1.2,
),
Armor(Shoulder(Leather0)): VoxTrans(
"voxel.armor.shoulder.leather_right-0",
//Leather2 Armor
Armor(Chest(Leather2)): VoxTrans(
"voxel.armor.chest.leather-2",
(0.0, 0.0, 0.0), (-90.0, 180.0, 0.0), 1.2,
),
Armor(Pants(Leather2)): VoxTrans(
"voxel.armor.pants.leather-2",
(0.0, 0.0, 0.0), (-90.0, 180.0, 0.0), 1.2,
),
Armor(Belt(Leather2)): VoxTrans(
"voxel.armor.belt.leather-2",
(0.0, 0.0, 0.0), (-90.0, 180.0, 0.0), 1.8,
),
Armor(Foot(Leather2)): VoxTrans(
"voxel.armor.foot.leather-2",
(0.0, 0.0, 0.0), (-95.0, 140.0, 0.0), 1.1,
),
Armor(Hand(Leather2)): VoxTrans(
"voxel.armor.hand.leather_right-2",
(0.0, -1.0, 0.0), (-90.0, 135.0, 0.0), 1.0,
),
Armor(Shoulder(Leather2)): VoxTrans(
"voxel.armor.shoulder.leather_right-2",
(0.0, 0.0, 0.0), (-90.0, 130.0, 0.0), 1.2,
),
//Linen Cloth

View File

@ -124,7 +124,7 @@ void main() {
vec3 color = mix(mix(surf_color, fog_color, fog_level), clouds.rgb, clouds.a);
if ((flags & 1) == 1 && int(cam_mode) == 1) {
float distance = distance(vec3(cam_pos), vec3(model_mat * vec4(vec3(0), 1))) - 2;
float distance = distance(vec3(cam_pos), focus_pos.xyz) - 2;
float opacity = clamp(distance / distance_divider, 0, 1);

View File

@ -57,6 +57,8 @@ void main() {
combined_mat *
vec4(pos, 1)).xyz;
f_pos.z -= 25.0 * pow(distance(focus_pos.xy, f_pos.xy) / view_distance.x, 20.0);
f_col = srgb_to_linear(vec3((uvec3(v_col) >> uvec3(0, 8, 16)) & uvec3(0xFFu)) / 255.0);
f_ao = float(v_ao_bone & 0x3u) / 4.0;

View File

@ -44,7 +44,7 @@ uniform u_bones {
out vec4 tgt_color;
void main() {
float distance = distance(vec3(cam_pos), vec3(model_mat * vec4(vec3(0), 1))) - 2;
float distance = distance(vec3(cam_pos), focus_pos.xyz) - 2;
float opacity = clamp(distance / distance_divider, 0, 1);

BIN
assets/voxygen/voxel/armor/belt/leather-2.vox (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/voxygen/voxel/armor/belt/steel-0.vox (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/voxygen/voxel/armor/chest/leather-2.vox (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/voxygen/voxel/armor/chest/steel-0.vox (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/voxygen/voxel/armor/foot/leather-2.vox (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/voxygen/voxel/armor/foot/steel-0.vox (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/voxygen/voxel/armor/hand/leather_left-2.vox (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/voxygen/voxel/armor/hand/leather_right-2.vox (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/voxygen/voxel/armor/hand/steel_left-0.vox (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/voxygen/voxel/armor/hand/steel_right-0.vox (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/voxygen/voxel/armor/pants/leather-2.vox (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/voxygen/voxel/armor/pants/steel-0.vox (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/voxygen/voxel/armor/shoulder/leather_left-2.vox (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/voxygen/voxel/armor/shoulder/leather_right-2.vox (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/voxygen/voxel/armor/shoulder/steel_left-0.vox (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/voxygen/voxel/armor/shoulder/steel_right-0.vox (Stored with Git LFS) Normal file

Binary file not shown.

View File

@ -52,5 +52,13 @@
vox_spec: ("armor.belt.cultist", (-5.0, -3.5, 1.0)),
color: None
),
Leather2:(
vox_spec: ("armor.belt.leather-2", (-5.0, -3.5, 2.0)),
color: None
),
Steel0:(
vox_spec: ("armor.belt.steel-0", (-5.0, -4.5, 2.0)),
color: None
),
},
))

View File

@ -110,5 +110,14 @@
vox_spec: ("armor.chest.cultist", (-7.0, -3.5, 2.0)),
color: Some((57, 81, 132))
),
Steel0:(
vox_spec: ("armor.chest.steel-0", (-8.0, -4.5, 2.0)),
color: None
),
Leather2:(
vox_spec: ("armor.chest.leather-2", (-7.0, -3.5, 2.0)),
color: None
),
},
))
)
)

View File

@ -44,5 +44,13 @@
vox_spec: ("armor.foot.cultist", (-2.5, -3.5, -9.0)),
color: None
),
Steel0:(
vox_spec: ("armor.foot.steel-0", (-2.5, -3.5, -9.0)),
color: None
),
Leather2:(
vox_spec: ("armor.foot.leather-2", (-2.5, -3.5, -9.0)),
color: None
),
},
))

View File

@ -100,6 +100,25 @@
color: Some((57, 81, 132))
)
),
Steel0: (
left: (
vox_spec: ("armor.hand.steel_left-0", (-1.5, -1.5, -7.0)),
color: None
),
right: (
vox_spec: ("armor.hand.steel_right-0", (-1.5, -1.5, -7.0)),
color: None
)
),
Leather2: (
left: (
vox_spec: ("armor.hand.leather_left-2", (-1.5, -1.5, -7.0)),
color: None
),
right: (
vox_spec: ("armor.hand.leather_right-2", (-1.5, -1.5, -7.0)),
color: None
)
),
},
))

View File

@ -68,5 +68,13 @@
vox_spec: ("armor.pants.cultist", (-5.0, -3.5, 1.0)),
color: Some((57, 81, 132))
),
Steel0:(
vox_spec: ("armor.pants.steel-0", (-6.0, -4.5, 1.0)),
color: None
),
Leather2:(
vox_spec: ("armor.pants.leather-2", (-5.0, -3.5, 1.0)),
color: None
),
},
))

View File

@ -131,5 +131,25 @@
color: Some((57, 81, 132))
)
),
Steel0: (
left: (
vox_spec: ("armor.shoulder.steel_left-0", (-5.0, -4.5 , 0.0)),
color: None
),
right: (
vox_spec: ("armor.shoulder.steel_right-0", (-1.0, -4.5, 0.0)),
color: None
)
),
Leather2: (
left: (
vox_spec: ("armor.shoulder.leather_left-2", (-5.0, -3.8, -0.9)),
color: None
),
right: (
vox_spec: ("armor.shoulder.leather_right-2", (-1.0, -3.8, -0.9)),
color: None
)
),
},
))

Binary file not shown.

View File

@ -1,6 +1,6 @@
[package]
name = "veloren-chat-cli"
version = "0.5.0"
version = "0.6.0"
authors = ["Joshua Barretto <joshua.s.barretto@gmail.com>"]
edition = "2018"

View File

@ -1,6 +1,6 @@
[package]
name = "veloren-client"
version = "0.5.0"
version = "0.6.0"
authors = ["Joshua Barretto <joshua.s.barretto@gmail.com>"]
edition = "2018"

View File

@ -1,6 +1,6 @@
[package]
name = "veloren-common"
version = "0.5.0"
version = "0.6.0"
authors = ["Joshua Barretto <joshua.s.barretto@gmail.com>", "Maciej Ćwięka <mckol363@gmail.com>", "Imbris <imbrisf@gmail.com>"]
edition = "2018"

View File

@ -296,7 +296,7 @@ lazy_static! {
}
// System paths
#[cfg(target_os = "linux")]
#[cfg(all(unix, not(target_os = "macos"), not(target_os = "ios"), not(target_os = "android")))]
{
if let Ok(result) = std::env::var("XDG_DATA_HOME") {
paths.push(format!("{}/veloren/assets", result).into());

View File

@ -55,10 +55,9 @@ impl<'a, SpeciesMeta> core::ops::Index<&'a Species> for AllSpecies<SpeciesMeta>
pub const ALL_SPECIES: [Species; 2] = [Species::Ogre, Species::Cyclops];
impl<'a, SpeciesMeta: 'a> IntoIterator for &'a AllSpecies<SpeciesMeta> {
type IntoIter = std::iter::Copied<std::slice::Iter<'static, Self::Item>>;
type Item = Species;
type IntoIter = impl Iterator<Item = Self::Item>;
fn into_iter(self) -> Self::IntoIter { ALL_SPECIES.iter().copied() }
}

View File

@ -82,10 +82,9 @@ pub const ALL_SPECIES: [Species; 8] = [
];
impl<'a, SpeciesMeta: 'a> IntoIterator for &'a AllSpecies<SpeciesMeta> {
type IntoIter = std::iter::Copied<std::slice::Iter<'static, Self::Item>>;
type Item = Species;
type IntoIter = impl Iterator<Item = Self::Item>;
fn into_iter(self) -> Self::IntoIter { ALL_SPECIES.iter().copied() }
}

View File

@ -72,10 +72,9 @@ pub const ALL_SPECIES: [Species; 6] = [
];
impl<'a, SpeciesMeta: 'a> IntoIterator for &'a AllSpecies<SpeciesMeta> {
type IntoIter = std::iter::Copied<std::slice::Iter<'static, Self::Item>>;
type Item = Species;
type IntoIter = impl Iterator<Item = Self::Item>;
fn into_iter(self) -> Self::IntoIter { ALL_SPECIES.iter().copied() }
}

View File

@ -52,10 +52,9 @@ impl<'a, SpeciesMeta> core::ops::Index<&'a Species> for AllSpecies<SpeciesMeta>
pub const ALL_SPECIES: [Species; 1] = [Species::Reddragon];
impl<'a, SpeciesMeta: 'a> IntoIterator for &'a AllSpecies<SpeciesMeta> {
type IntoIter = std::iter::Copied<std::slice::Iter<'static, Self::Item>>;
type Item = Species;
type IntoIter = impl Iterator<Item = Self::Item>;
fn into_iter(self) -> Self::IntoIter { ALL_SPECIES.iter().copied() }
}

View File

@ -52,10 +52,9 @@ impl<'a, SpeciesMeta> core::ops::Index<&'a Species> for AllSpecies<SpeciesMeta>
pub const ALL_SPECIES: [Species; 1] = [Species::StoneGolem];
impl<'a, SpeciesMeta: 'a> IntoIterator for &'a AllSpecies<SpeciesMeta> {
type IntoIter = std::iter::Copied<std::slice::Iter<'static, Self::Item>>;
type Item = Species;
type IntoIter = impl Iterator<Item = Self::Item>;
fn into_iter(self) -> Self::IntoIter { ALL_SPECIES.iter().copied() }
}

View File

@ -105,10 +105,9 @@ pub const ALL_RACES: [Race; 6] = [
];
impl<'a, SpeciesMeta: 'a> IntoIterator for &'a AllSpecies<SpeciesMeta> {
type IntoIter = std::iter::Copied<std::slice::Iter<'static, Self::Item>>;
type Item = Race;
type IntoIter = impl Iterator<Item = Self::Item>;
fn into_iter(self) -> Self::IntoIter { ALL_RACES.iter().copied() }
}

View File

@ -82,10 +82,9 @@ pub const ALL_SPECIES: [Species; 8] = [
];
impl<'a, SpeciesMeta: 'a> IntoIterator for &'a AllSpecies<SpeciesMeta> {
type IntoIter = std::iter::Copied<std::slice::Iter<'static, Self::Item>>;
type Item = Species;
type IntoIter = impl Iterator<Item = Self::Item>;
fn into_iter(self) -> Self::IntoIter { ALL_SPECIES.iter().copied() }
}

View File

@ -102,10 +102,9 @@ pub const ALL_SPECIES: [Species; 13] = [
];
impl<'a, SpeciesMeta: 'a> IntoIterator for &'a AllSpecies<SpeciesMeta> {
type IntoIter = std::iter::Copied<std::slice::Iter<'static, Self::Item>>;
type Item = Species;
type IntoIter = impl Iterator<Item = Self::Item>;
fn into_iter(self) -> Self::IntoIter { ALL_SPECIES.iter().copied() }
}

View File

@ -91,6 +91,17 @@ impl CharacterState {
}
}
pub fn is_aimed(&self) -> bool {
match self {
CharacterState::BasicMelee(_)
| CharacterState::BasicRanged(_)
| CharacterState::DashMelee(_)
| CharacterState::TripleStrike(_)
| CharacterState::BasicBlock => true,
_ => false,
}
}
pub fn is_block(&self) -> bool {
match self {
CharacterState::BasicBlock => true,

View File

@ -27,8 +27,10 @@ pub enum Chest {
WorkerOrange1 = 24,
CultistPurple = 25,
CultistBlue = 26,
Steel0 = 27,
Leather2 = 28,
}
pub const ALL_CHESTS: [Chest; 26] = [
pub const ALL_CHESTS: [Chest; 28] = [
Chest::Blue,
Chest::Brown,
Chest::Dark,
@ -55,6 +57,8 @@ pub const ALL_CHESTS: [Chest; 26] = [
Chest::WorkerOrange1,
Chest::CultistPurple,
Chest::CultistBlue,
Chest::Steel0,
Chest::Leather2,
];
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
@ -72,8 +76,11 @@ pub enum Belt {
ClothBlue0 = 9,
ClothGreen0 = 10,
Cultist = 11,
Leather2 = 12,
Steel0 = 13,
}
pub const ALL_BELTS: [Belt; 12] = [
pub const ALL_BELTS: [Belt; 14] = [
Belt::None,
Belt::Dark,
Belt::TurqCloth,
@ -86,6 +93,8 @@ pub const ALL_BELTS: [Belt; 12] = [
Belt::ClothBlue0,
Belt::ClothGreen0,
Belt::Cultist,
Belt::Leather2,
Belt::Steel0,
];
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
@ -108,8 +117,10 @@ pub enum Pants {
WorkerBlue0 = 14,
CultistPurple = 15,
CultistBlue = 16,
Steel0 = 17,
Leather2 = 18,
}
pub const ALL_PANTS: [Pants; 17] = [
pub const ALL_PANTS: [Pants; 19] = [
Pants::None,
Pants::Blue,
Pants::Brown,
@ -127,6 +138,8 @@ pub const ALL_PANTS: [Pants; 17] = [
Pants::WorkerBlue0,
Pants::CultistPurple,
Pants::CultistBlue,
Pants::Steel0,
Pants::Leather2,
];
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
@ -141,8 +154,10 @@ pub enum Hand {
ClothGreen0 = 7,
CultistPurple = 8,
CultistBlue = 9,
Steel0 = 10,
Leather2 = 11,
}
pub const ALL_HANDS: [Hand; 9] = [
pub const ALL_HANDS: [Hand; 11] = [
Hand::Cloth,
Hand::Assassin,
Hand::Plate0,
@ -152,6 +167,8 @@ pub const ALL_HANDS: [Hand; 9] = [
Hand::ClothGreen0,
Hand::CultistPurple,
Hand::CultistBlue,
Hand::Steel0,
Hand::Leather2,
];
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
@ -167,8 +184,11 @@ pub enum Foot {
ClothBlue0 = 8,
ClothGreen0 = 9,
Cultist = 10,
Steel0 = 11,
Leather2 = 12,
}
pub const ALL_FEET: [Foot; 10] = [
pub const ALL_FEET: [Foot; 12] = [
Foot::Dark,
Foot::Sandal0,
Foot::Jester,
@ -179,6 +199,8 @@ pub const ALL_FEET: [Foot; 10] = [
Foot::ClothBlue0,
Foot::ClothGreen0,
Foot::Cultist,
Foot::Steel0,
Foot::Leather2,
];
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
@ -195,8 +217,10 @@ pub enum Shoulder {
ClothGreen0 = 9,
CultistPurple = 10,
CultistBlue = 11,
Steel0 = 12,
Leather2 = 13,
}
pub const ALL_SHOULDERS: [Shoulder; 11] = [
pub const ALL_SHOULDERS: [Shoulder; 13] = [
Shoulder::Brown1,
Shoulder::Chain,
Shoulder::Assassin,
@ -208,6 +232,8 @@ pub const ALL_SHOULDERS: [Shoulder; 11] = [
Shoulder::ClothGreen0,
Shoulder::CultistPurple,
Shoulder::CultistBlue,
Shoulder::Steel0,
Shoulder::Leather2,
];
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[repr(u32)]

View File

@ -123,6 +123,8 @@ impl Item {
}
}
pub fn expect_from_asset(asset: &str) -> Self { (*assets::load_expect::<Self>(asset)).clone() }
pub fn set_amount(&mut self, give_amount: u32) -> Result<(), assets::Error> {
use ItemKind::*;
match self.kind {
@ -235,3 +237,10 @@ impl Item {
impl Component for Item {
type Storage = FlaggedStorage<Self, IDVStorage<Self>>;
}
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct ItemDrop(pub Item);
impl Component for ItemDrop {
type Storage = FlaggedStorage<Self, IDVStorage<Self>>;
}

View File

@ -3,7 +3,6 @@ pub mod slot;
use crate::assets;
use item::{Consumable, Item, ItemKind};
use rand::{seq::SliceRandom, thread_rng};
use specs::{Component, FlaggedStorage, HashMapStorage};
use specs_idvs::IDVStorage;
use std::ops::Not;
@ -305,15 +304,6 @@ impl Default for Inventory {
};
inventory.push(assets::load_expect_cloned("common.items.cheese"));
inventory.push(assets::load_expect_cloned("common.items.apple"));
let mut rng = thread_rng();
let starter_lantern = [
"common.items.lantern.black_0",
"common.items.lantern.red_0",
"common.items.lantern.blue_0",
]
.choose(&mut rng)
.unwrap();
inventory.push(assets::load_expect_cloned(starter_lantern));
inventory
}
}

View File

@ -8,7 +8,7 @@ lazy_static! {
}
/// The `Default` inventory should contain 3 items: cheese, apple, lantern
#[test]
fn create_default_count() { assert_eq!(Inventory::default().count(), 3) }
fn create_default_count() { assert_eq!(Inventory::default().count(), 2) }
/// Attempting to push into a full inventory should return the same item.
#[test]

View File

@ -31,7 +31,9 @@ pub use controller::{
pub use energy::{Energy, EnergySource};
pub use inputs::CanBuild;
pub use inventory::{
item, item::Item, slot, Inventory, InventoryUpdate, InventoryUpdateEvent, MAX_PICKUP_RANGE_SQR,
item,
item::{Item, ItemDrop},
slot, Inventory, InventoryUpdate, InventoryUpdateEvent, MAX_PICKUP_RANGE_SQR,
};
pub use last::Last;
pub use location::{Waypoint, WaypointArea};

View File

@ -1,5 +1,5 @@
use crate::{comp, sync::Uid, util::Dir};
use comp::{item::ToolKind, InventoryUpdateEvent};
use comp::{item::ToolKind, InventoryUpdateEvent, Item};
use parking_lot::Mutex;
use serde::Deserialize;
use specs::Entity as EcsEntity;
@ -107,6 +107,7 @@ pub enum ServerEvent {
agent: comp::Agent,
alignment: comp::Alignment,
scale: comp::Scale,
drop_item: Option<Item>,
},
CreateWaypoint(Vec3<f32>),
ClientDisconnect(EcsEntity),

View File

@ -16,6 +16,9 @@ pub struct EntityInfo {
pub body: Body,
pub name: Option<String>,
pub main_tool: Option<Item>,
pub scale: f32,
pub level: Option<u32>,
pub loot_drop: Option<Item>,
}
impl EntityInfo {
@ -28,6 +31,9 @@ impl EntityInfo {
body: Body::Humanoid(humanoid::Body::random()),
name: None,
main_tool: Some(Item::empty()),
scale: 1.0,
level: None,
loot_drop: None,
}
}
@ -68,6 +74,21 @@ impl EntityInfo {
self
}
pub fn with_loot_drop(mut self, loot_drop: Item) -> Self {
self.loot_drop = Some(loot_drop);
self
}
pub fn with_scale(mut self, scale: f32) -> Self {
self.scale = scale;
self
}
pub fn with_level(mut self, level: u32) -> Self {
self.level = Some(level);
self
}
pub fn with_automatic_name(mut self) -> Self {
self.name = match &self.body {
Body::Humanoid(body) => Some(get_npc_name(&NPC_NAMES.humanoid, body.race)),

View File

@ -153,6 +153,7 @@ impl State {
ecs.register::<comp::Waypoint>();
ecs.register::<comp::Projectile>();
ecs.register::<comp::Attacking>();
ecs.register::<comp::ItemDrop>();
// Register synced resources used by the ECS.
ecs.insert(TimeOfDay(0.0));

View File

@ -1,6 +1,6 @@
[package]
name = "veloren-server-cli"
version = "0.5.0"
version = "0.6.0"
authors = ["Joshua Barretto <joshua.s.barretto@gmail.com>"]
edition = "2018"

View File

@ -1,6 +1,6 @@
[package]
name = "veloren-server"
version = "0.5.0"
version = "0.6.0"
authors = ["Joshua Barretto <joshua.s.barretto@gmail.com>"]
edition = "2018"

View File

@ -1,8 +1,8 @@
use crate::{sys, Server, StateExt};
use common::{
comp::{
self, Agent, Alignment, Body, Gravity, LightEmitter, Loadout, Pos, Projectile, Scale,
Stats, Vel, WaypointArea,
self, Agent, Alignment, Body, Gravity, Item, ItemDrop, LightEmitter, Loadout, Pos,
Projectile, Scale, Stats, Vel, WaypointArea,
},
util::Dir,
};
@ -32,14 +32,22 @@ pub fn handle_create_npc(
agent: Agent,
alignment: Alignment,
scale: Scale,
drop_item: Option<Item>,
) {
server
let entity = server
.state
.create_npc(pos, stats, loadout, body)
.with(agent)
.with(scale)
.with(alignment)
.build();
.with(alignment);
let entity = if let Some(drop_item) = drop_item {
entity.with(ItemDrop(drop_item))
} else {
entity
};
entity.build();
}
pub fn handle_shoot(

View File

@ -106,10 +106,17 @@ pub fn handle_destroy(server: &mut Server, entity: EcsEntity, cause: HealthSourc
.ecs()
.write_storage()
.insert(entity, Body::Object(object::Body::Pouch));
let _ = state.ecs().write_storage().insert(
entity,
assets::load_expect_cloned::<Item>("common.items.cheese"),
);
let mut item_drops = state.ecs().write_storage::<comp::ItemDrop>();
let item = if let Some(item_drop) = item_drops.get(entity).cloned() {
item_drops.remove(entity);
item_drop.0
} else {
assets::load_expect_cloned::<Item>("common.items.cheese")
};
let _ = state.ecs().write_storage().insert(entity, item);
state.ecs().write_storage::<comp::Stats>().remove(entity);
state.ecs().write_storage::<comp::Agent>().remove(entity);
state

View File

@ -84,7 +84,10 @@ impl Server {
agent,
alignment,
scale,
} => handle_create_npc(self, pos, stats, loadout, body, agent, alignment, scale),
drop_item,
} => handle_create_npc(
self, pos, stats, loadout, body, agent, alignment, scale, drop_item,
),
ServerEvent::CreateWaypoint(pos) => handle_create_waypoint(self, pos),
ServerEvent::ClientDisconnect(entity) => {
frontend_events.push(handle_client_disconnect(self, entity))

View File

@ -42,7 +42,6 @@ pub fn handle_exit_ingame(server: &mut Server, entity: EcsEntity) {
}
pub fn handle_client_disconnect(server: &mut Server, entity: EcsEntity) -> Event {
let db_dir = &server.server_settings.persistence_db_dir.clone();
let state = server.state_mut();
// Tell other clients to remove from player list
@ -73,12 +72,13 @@ pub fn handle_client_disconnect(server: &mut Server, entity: EcsEntity) -> Event
}
// Sync the player's character data to the database
if let (Some(player), Some(stats)) = (
if let (Some(player), Some(stats), updater) = (
state.read_storage::<Player>().get(entity),
state.read_storage::<comp::Stats>().get(entity),
state.ecs().read_resource::<persistence::stats::Updater>(),
) {
if let Some(character_id) = player.character_id {
persistence::stats::update_item(character_id, stats, db_dir);
updater.update(character_id, stats);
}
}

View File

@ -94,6 +94,12 @@ impl Server {
.insert(AuthProvider::new(settings.auth_server_address.clone()));
state.ecs_mut().insert(Tick(0));
state.ecs_mut().insert(ChunkGenerator::new());
state.ecs_mut().insert(persistence::stats::Updater::new(
settings.persistence_db_dir.clone(),
));
state.ecs_mut().insert(crate::settings::PersistenceDBDir(
settings.persistence_db_dir.clone(),
));
// System timers for performance monitoring
state.ecs_mut().insert(sys::EntitySyncTimer::default());
@ -117,9 +123,6 @@ impl Server {
// Server-only components
state.ecs_mut().register::<RegionSubscription>();
state.ecs_mut().register::<Client>();
state.ecs_mut().insert(crate::settings::PersistenceDBDir(
settings.persistence_db_dir.clone(),
));
#[cfg(feature = "worldgen")]
let world = World::generate(settings.world_seed, WorldOpts {

View File

@ -2,12 +2,13 @@ extern crate diesel;
use super::{establish_connection, models::StatsUpdate, schema};
use crate::comp;
use crossbeam::channel;
use diesel::prelude::*;
fn update(character_id: i32, stats: &comp::Stats, connection: &SqliteConnection) {
fn update(character_id: i32, stats: &StatsUpdate, connection: &SqliteConnection) {
if let Err(error) =
diesel::update(schema::stats::table.filter(schema::stats::character_id.eq(character_id)))
.set(&StatsUpdate::from(stats))
.set(stats)
.execute(connection)
{
log::warn!(
@ -18,12 +19,58 @@ fn update(character_id: i32, stats: &comp::Stats, connection: &SqliteConnection)
}
}
pub fn update_item(character_id: i32, stats: &comp::Stats, db_dir: &str) {
update(character_id, stats, &establish_connection(db_dir));
}
pub fn batch_update<'a>(updates: impl Iterator<Item = (i32, &'a comp::Stats)>, db_dir: &str) {
fn batch_update(updates: impl Iterator<Item = (i32, StatsUpdate)>, db_dir: &str) {
let connection = establish_connection(db_dir);
if let Err(err) = connection.transaction::<_, diesel::result::Error, _>(|| {
updates.for_each(|(character_id, stats_update)| {
update(character_id, &stats_update, &connection)
});
updates.for_each(|(character_id, stats)| update(character_id, stats, &connection));
Ok(())
}) {
log::error!("Error during stats batch update transaction: {:?}", err);
}
}
pub struct Updater {
update_tx: Option<channel::Sender<Vec<(i32, StatsUpdate)>>>,
handle: Option<std::thread::JoinHandle<()>>,
}
impl Updater {
pub fn new(db_dir: String) -> Self {
let (update_tx, update_rx) = channel::unbounded::<Vec<(i32, StatsUpdate)>>();
let handle = std::thread::spawn(move || {
while let Ok(updates) = update_rx.recv() {
batch_update(updates.into_iter(), &db_dir);
}
});
Self {
update_tx: Some(update_tx),
handle: Some(handle),
}
}
pub fn batch_update<'a>(&self, updates: impl Iterator<Item = (i32, &'a comp::Stats)>) {
let updates = updates
.map(|(id, stats)| (id, StatsUpdate::from(stats)))
.collect();
if let Err(err) = self.update_tx.as_ref().unwrap().send(updates) {
log::error!("Could not send stats updates: {:?}", err);
}
}
pub fn update(&self, character_id: i32, stats: &comp::Stats) {
self.batch_update(std::iter::once((character_id, stats)));
}
}
impl Drop for Updater {
fn drop(&mut self) {
drop(self.update_tx.take());
if let Err(err) = self.handle.take().unwrap().join() {
log::error!("Error from joining stats update thread: {:?}", err);
}
}
}

View File

@ -240,7 +240,9 @@ impl StateExt for State {
back: None,
ring: None,
neck: None,
lantern: None,
lantern: Some(assets::load_expect_cloned(
"common.items.armor.starter.lantern",
)),
head: None,
tabard: None,
}

View File

@ -1,6 +1,5 @@
use crate::{
persistence::stats,
settings::PersistenceDBDir,
sys::{SysScheduler, SysTimer},
};
use common::comp::{Player, Stats};
@ -12,25 +11,22 @@ impl<'a> System<'a> for Sys {
type SystemData = (
ReadStorage<'a, Player>,
ReadStorage<'a, Stats>,
ReadExpect<'a, PersistenceDBDir>,
ReadExpect<'a, stats::Updater>,
Write<'a, SysScheduler<Self>>,
Write<'a, SysTimer<Self>>,
);
fn run(
&mut self,
(players, player_stats, persistence_db_dir, mut scheduler, mut timer): Self::SystemData,
(players, player_stats, updater, mut scheduler, mut timer): Self::SystemData,
) {
if scheduler.should_run() {
timer.start();
stats::batch_update(
updater.batch_update(
(&players, &player_stats)
.join()
.filter_map(|(player, stats)| player.character_id.map(|id| (id, stats))),
&persistence_db_dir.0,
);
timer.end();
}
}

View File

@ -2,7 +2,7 @@ use super::SysTimer;
use crate::{chunk_generator::ChunkGenerator, client::Client, Tick};
use common::{
assets,
comp::{self, item, CharacterAbility, ItemConfig, Player, Pos},
comp::{self, item, Alignment, CharacterAbility, ItemConfig, Player, Pos},
event::{EventBus, ServerEvent},
generation::get_npc_name,
msg::ServerMsg,
@ -245,20 +245,30 @@ impl<'a> System<'a> for Sys {
},
};
let mut scale = 1.0;
let mut scale = entity.scale;
// TODO: Remove this and implement scaling or level depending on stuff like
// species instead
stats.level.set_level(rand::thread_rng().gen_range(1, 9));
stats.level.set_level(
entity.level.unwrap_or_else(|| {
(rand::thread_rng().gen_range(1, 9) as f32 * scale) as u32
}),
);
// Replace stuff if it's a boss
if entity.is_giant {
if rand::random::<f32>() < 0.65 {
let body_new = comp::humanoid::Body::random();
body = comp::Body::Humanoid(body_new);
let adjective = if let Alignment::Enemy = entity.alignment {
"Angry"
} else {
"Gentle"
};
stats = comp::Stats::new(
format!(
"Gentle {} Giant",
"{} Giant {}",
adjective,
get_npc_name(&NPC_NAMES.humanoid, body_new.race)
),
body,
@ -336,6 +346,7 @@ impl<'a> System<'a> for Sys {
alignment,
agent: comp::Agent::default().with_patrol_origin(entity.pos),
scale: comp::Scale(scale),
drop_item: entity.loot_drop,
})
}
}

View File

@ -1,6 +1,6 @@
[package]
name = "veloren-voxygen"
version = "0.5.0"
version = "0.6.0"
authors = ["Joshua Barretto <joshua.s.barretto@gmail.com>", "Imbris <imbrisf@gmail.com>"]
edition = "2018"
default-run = "veloren-voxygen"

View File

@ -207,6 +207,11 @@ pub struct DebugInfo {
pub num_figures_visible: u32,
}
pub struct HudInfo {
pub is_aiming: bool,
pub is_first_person: bool,
}
pub enum Event {
SendMessage(String),
AdjustMousePan(u32),
@ -457,6 +462,7 @@ pub struct Hud {
slot_manager: slots::SlotManager,
hotbar: hotbar::State,
events: Vec<Event>,
crosshair_opacity: f32,
}
impl Hud {
@ -531,6 +537,7 @@ impl Hud {
slot_manager,
hotbar: hotbar::State::new(),
events: Vec::new(),
crosshair_opacity: 0.0,
}
}
@ -546,6 +553,7 @@ impl Hud {
global_state: &GlobalState,
debug_info: DebugInfo,
dt: Duration,
info: HudInfo,
) -> Vec<Event> {
let mut events = std::mem::replace(&mut self.events, Vec::new());
let (ref mut ui_widgets, ref mut tooltip_manager) = self.ui.set_widgets();
@ -604,7 +612,14 @@ impl Hud {
.set(self.ids.death_bg, ui_widgets);
}
// Crosshair
if !self.show.help && !stats.is_dead {
let show_crosshair = (info.is_aiming || info.is_first_person) && !stats.is_dead;
self.crosshair_opacity = Lerp::lerp(
self.crosshair_opacity,
if show_crosshair { 1.0 } else { 0.0 },
5.0 * dt.as_secs_f32(),
);
if !self.show.help {
Image::new(
// TODO: Do we want to match on this every frame?
match global_state.settings.gameplay.crosshair_type {
@ -619,7 +634,7 @@ impl Hud {
1.0,
1.0,
1.0,
global_state.settings.gameplay.crosshair_transp,
self.crosshair_opacity * global_state.settings.gameplay.crosshair_transp,
)))
.set(self.ids.crosshair_outer, ui_widgets);
Image::new(self.imgs.crosshair_inner)
@ -2338,6 +2353,7 @@ impl Hud {
debug_info: DebugInfo,
camera: &Camera,
dt: Duration,
info: HudInfo,
) -> Vec<Event> {
// conrod eats tabs. Un-eat a tabstop so tab completion can work
if self.ui.ui.global_input().events().any(|event| {
@ -2363,7 +2379,7 @@ impl Hud {
if let Some(maybe_id) = self.to_focus.take() {
self.ui.focus_widget(maybe_id);
}
let events = self.update_layout(client, global_state, debug_info, dt);
let events = self.update_layout(client, global_state, debug_info, dt, info);
let camera::Dependents {
view_mat, proj_mat, ..
} = camera.dependents();

View File

@ -891,18 +891,45 @@ impl CharSelectionUi {
to_select = true;
}
// Create Button
if Button::image(self.imgs.button)
let create_button = Button::image(self.imgs.button)
.bottom_right_with_margins_on(ui_widgets.window, 10.0, 10.0)
.w_h(150.0, 40.0)
.hover_image(self.imgs.button_hover)
.press_image(self.imgs.button_press)
.hover_image(if *name != "Character Name" && *name != "" {
self.imgs.button_hover
} else {
self.imgs.button
})
.press_image(if *name != "Character Name" && *name != "" {
self.imgs.button_press
} else {
self.imgs.button
})
.label(&self.voxygen_i18n.get("common.create"))
.label_font_id(self.fonts.cyri.conrod_id)
.label_color(
/* if self.mode { TEXT_COLOR } else { */ TEXT_COLOR, /* , } */
)
.label_color(if *name != "Character Name" && *name != "" {
TEXT_COLOR
} else {
TEXT_COLOR_2
})
.label_font_size(self.fonts.cyri.scale(20))
.label_y(conrod_core::position::Relative::Scalar(3.0))
.label_y(conrod_core::position::Relative::Scalar(3.0));
if *name == "Character Name" || *name == "" {
//TODO: We need a server side list of disallowed names and certain naming rules
if create_button
.with_tooltip(
tooltip_manager,
&self.voxygen_i18n.get("char_selection.create_info_name"),
"",
&tooltip_human,
)
.bottom_offset(55.0)
.x_offset(-10.0)
.set(self.ids.create_button, ui_widgets)
.was_clicked()
{}
} else {
if create_button
.set(self.ids.create_button, ui_widgets)
.was_clicked()
{
@ -916,6 +943,7 @@ impl CharSelectionUi {
to_select = true;
}
}
// Character Name Input
Rectangle::fill_with([320.0, 50.0], color::rgba(0.0, 0.0, 0.0, 0.97))
.mid_bottom_with_margin_on(ui_widgets.window, 20.0)

View File

@ -179,6 +179,11 @@ impl MainMenuUi {
"voxygen.background.bg_9",
"voxygen.background.bg_10",
"voxygen.background.bg_11",
"voxygen.background.bg_12",
"voxygen.background.bg_13",
"voxygen.background.bg_14",
"voxygen.background.bg_15",
"voxygen.background.bg_16",
];
let mut rng = thread_rng();

View File

@ -169,9 +169,10 @@ impl Camera {
pub fn zoom_switch(&mut self, delta: f32) {
if delta > 0_f32 || self.mode != CameraMode::FirstPerson {
let t = self.tgt_dist + delta;
const MIN_THIRD_PERSON: f32 = 2.35;
match self.mode {
CameraMode::ThirdPerson => {
if t < 1_f32 {
if t < MIN_THIRD_PERSON {
self.set_mode(CameraMode::FirstPerson);
} else {
self.tgt_dist = t;
@ -179,16 +180,16 @@ impl Camera {
},
CameraMode::FirstPerson => {
self.set_mode(CameraMode::ThirdPerson);
self.tgt_dist = 1_f32;
self.tgt_dist = MIN_THIRD_PERSON;
},
}
}
}
/// Get the distance of the camera from the target
pub fn get_distance(&self) -> f32 { self.tgt_dist }
/// Get the distance of the camera from the focus
pub fn get_distance(&self) -> f32 { self.dist }
/// Set the distance of the camera from the target (i.e., zoom).
/// Set the distance of the camera from the focus (i.e., zoom).
pub fn set_distance(&mut self, dist: f32) { self.tgt_dist = dist; }
pub fn update(&mut self, time: f64, dt: f32, smoothing_enabled: bool) {
@ -198,16 +199,33 @@ impl Camera {
self.dist = f32::lerp(
self.dist,
self.tgt_dist,
(delta as f32) / self.interp_time(),
0.65 * (delta as f32) / self.interp_time(),
);
}
if (self.focus - self.tgt_focus).magnitude() > 0.01 {
self.focus = Vec3::lerp(
if (self.focus - self.tgt_focus).magnitude_squared() > 0.001 {
let lerped_focus = Lerp::lerp(
self.focus,
self.tgt_focus,
(delta as f32) / self.interp_time(),
(delta as f32) / self.interp_time()
* if matches!(self.mode, CameraMode::FirstPerson) {
2.0
} else {
1.0
},
);
// Snap when close enough in x/y, but lerp otherwise
if (self.focus.xy() - self.tgt_focus.xy()).magnitude_squared() > 2.0f32.powf(2.0) {
self.focus.x = lerped_focus.x;
self.focus.y = lerped_focus.y;
} else {
self.focus.x = self.tgt_focus.x;
self.focus.y = self.tgt_focus.y;
}
// Always lerp in z
self.focus.z = lerped_focus.z;
}
let lerp_angle = |a: f32, b: f32, rate: f32| {
@ -281,5 +299,13 @@ impl Camera {
}
/// Get the mode of the camera
pub fn get_mode(&self) -> CameraMode { self.mode }
pub fn get_mode(&self) -> CameraMode {
// Perfom a bit of a trick... don't report first-person until the camera has
// lerped close enough to the player.
match self.mode {
CameraMode::FirstPerson if self.dist < 0.5 => CameraMode::FirstPerson,
CameraMode::FirstPerson => CameraMode::ThirdPerson,
mode => mode,
}
}
}

View File

@ -95,6 +95,7 @@ pub struct SceneData<'a> {
pub mouse_smoothing: bool,
pub sprite_render_distance: f32,
pub figure_lod_render_distance: f32,
pub is_aiming: bool,
}
impl Scene {
@ -220,7 +221,8 @@ impl Scene {
let is_running = ecs
.read_storage::<comp::Vel>()
.get(scene_data.player_entity)
.map(|v| v.0.magnitude_squared() > RUNNING_THRESHOLD.powi(2));
.map(|v| v.0.magnitude_squared() > RUNNING_THRESHOLD.powi(2))
.unwrap_or(false);
let on_ground = ecs
.read_storage::<comp::PhysicsState>()
@ -251,18 +253,18 @@ impl Scene {
CameraMode::FirstPerson => {
if player_rolling {
player_scale * 0.8
} else if is_running.unwrap_or(false) && on_ground.unwrap_or(false) {
player_scale * 1.6 + (scene_data.state.get_time() as f32 * 17.0).sin() * 0.05
} else if is_running && on_ground.unwrap_or(false) {
player_scale * 1.65 + (scene_data.state.get_time() as f32 * 17.0).sin() * 0.05
} else {
player_scale * 1.6
player_scale * 1.65
}
},
CameraMode::ThirdPerson => 1.2,
CameraMode::ThirdPerson if scene_data.is_aiming => player_scale * 2.1,
CameraMode::ThirdPerson => player_scale * 1.65,
};
self.camera.set_focus_pos(
player_pos + Vec3::unit_z() * (up + dist * 0.15 - tilt.min(0.0) * dist * 0.4),
);
self.camera
.set_focus_pos(player_pos + Vec3::unit_z() * (up - tilt.min(0.0).sin() * dist * 0.6));
// Tick camera for interpolation.
self.camera.update(

View File

@ -1,6 +1,6 @@
use crate::{
ecs::MyEntity,
hud::{DebugInfo, Event as HudEvent, Hud, PressBehavior},
hud::{DebugInfo, Event as HudEvent, Hud, HudInfo, PressBehavior},
i18n::{i18n_asset_key, VoxygenLocalization},
key_state::KeyState,
menu::char_selection::CharSelectionState,
@ -170,6 +170,25 @@ impl PlayState for SessionState {
_ => cam_pos, // Should never happen, but a safe fallback
};
let (is_aiming, aim_dir_offset) = {
let client = self.client.borrow();
let is_aiming = client
.state()
.read_storage::<comp::CharacterState>()
.get(client.entity())
.map(|cs| cs.is_aimed())
.unwrap_or(false);
(
is_aiming,
if is_aiming {
Vec3::unit_z() * 0.025
} else {
Vec3::zero()
},
)
};
let cam_dir: Vec3<f32> = Vec3::from(view_mat.inverted() * -Vec4::unit_z());
// Check to see whether we're aiming at anything
@ -184,22 +203,17 @@ impl PlayState for SessionState {
let cam_dist = cam_ray.0;
if let Ok(Some(_)) = cam_ray.1 {
// The ray hit something, is it within pickup range?
let select_pos = if player_pos.distance_squared(cam_pos + cam_dir * cam_dist)
<= MAX_PICKUP_RANGE_SQR
match cam_ray.1 {
Ok(Some(_))
if player_pos.distance_squared(cam_pos + cam_dir * cam_dist)
<= MAX_PICKUP_RANGE_SQR =>
{
Some((cam_pos + cam_dir * cam_dist).map(|e| e.floor() as i32))
} else {
None
};
(
Some((cam_pos + cam_dir * (cam_dist - 0.01)).map(|e| e.floor() as i32)),
select_pos,
Some((cam_pos + cam_dir * cam_dist).map(|e| e.floor() as i32)),
)
} else {
(None, None)
},
_ => (None, None),
}
};
@ -227,7 +241,7 @@ impl PlayState for SessionState {
},
Event::InputUpdate(GameInput::Primary, state) => {
// Check the existence of CanBuild component. If it's here, use LMB to
// place blocks, if not, use it to attack
// break blocks, if not, use it to attack
let mut client = self.client.borrow_mut();
if state
&& client
@ -236,8 +250,8 @@ impl PlayState for SessionState {
.get(client.entity())
.is_some()
{
if let Some(build_pos) = build_pos {
client.place_block(build_pos, self.selected_block);
if let Some(select_pos) = select_pos {
client.remove_block(select_pos);
}
} else {
self.inputs.primary.set_state(state);
@ -256,8 +270,8 @@ impl PlayState for SessionState {
.get(client.entity())
.is_some()
{
if let Some(select_pos) = select_pos {
client.remove_block(select_pos);
if let Some(build_pos) = build_pos {
client.place_block(build_pos, self.selected_block);
}
} else {
self.inputs.secondary.set_state(state);
@ -444,7 +458,7 @@ impl PlayState for SessionState {
if !free_look {
ori = self.scene.camera().get_orientation();
self.inputs.look_dir = Dir::from_unnormalized(cam_dir).unwrap();
self.inputs.look_dir = Dir::from_unnormalized(cam_dir + aim_dir_offset).unwrap();
}
// Calculate the movement input vector of the player from the current key
// presses and the camera direction.
@ -520,6 +534,13 @@ impl PlayState for SessionState {
},
&self.scene.camera(),
clock.get_last_delta(),
HudInfo {
is_aiming,
is_first_person: matches!(
self.scene.camera().get_mode(),
camera::CameraMode::FirstPerson
),
},
);
// Look for changes in the localization files
@ -762,6 +783,7 @@ impl PlayState for SessionState {
.graphics
.figure_lod_render_distance
as f32,
is_aiming,
};
// Runs if either in a multiplayer server or the singleplayer server is unpaused

Some files were not shown because too many files have changed in this diff Show More