Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add experimental leveled characters support, better dungeons support and more #1715

Merged
merged 89 commits into from
Nov 4, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
89 commits
Select commit Hold shift + click to select a range
2f9a91c
wip
Pospelove Oct 2, 2023
c4c60d9
format
Pospelove Oct 2, 2023
cfc325b
less noisy papurus test
Pospelove Oct 3, 2023
d658e0e
deliver template chain to the client & fix hosted.includes(remoteId …
Pospelove Oct 3, 2023
5418228
wip
Pospelove Oct 3, 2023
10bf693
LCharHorse works!!!
Pospelove Oct 4, 2023
2880c67
crashes
Pospelove Oct 4, 2023
3455a95
wip
Pospelove Oct 4, 2023
dabf4fd
tweak
Pospelove Oct 4, 2023
29439eb
loadgame maintainance again
Pospelove Oct 4, 2023
34a5cb3
.
Pospelove Oct 4, 2023
23edf1c
Merge branch 'main' into lvln
Pospelove Oct 6, 2023
a40449a
fmt
Pospelove Oct 6, 2023
7800f11
fmt
Pospelove Oct 6, 2023
ed3798c
fmt
Pospelove Oct 6, 2023
6be0ef0
fmt
Pospelove Oct 6, 2023
5f887d7
fmt
Pospelove Oct 6, 2023
d4e4a04
fmt
Pospelove Oct 6, 2023
caa85fb
fmt
Pospelove Oct 6, 2023
36ca599
fmt
Pospelove Oct 6, 2023
459607b
fuu go back
Pospelove Oct 6, 2023
d4206bd
it seems template race/npc health works now
Pospelove Oct 7, 2023
5a05fe2
leveled draugrs now have armor and weapons
Pospelove Oct 8, 2023
2b6a3b2
reformat
Pospelove Oct 8, 2023
00b3381
reform
Pospelove Oct 8, 2023
183e238
loadtemplscript
Pospelove Oct 8, 2023
2c3dfc7
activation parents: beginning
Pospelove Oct 8, 2023
f13061c
tons of papyrus boilerplate
Pospelove Oct 8, 2023
29773d1
not so bad in activating childs
Pospelove Oct 8, 2023
64c1543
fix setopen. now one scripted door works
Pospelove Oct 8, 2023
4d78c79
make OnCellLoad alias for OnInit
Pospelove Oct 9, 2023
bf64d0b
get pillar puzzle to work
Pospelove Oct 10, 2023
6ccc1d9
add bsa script storage
Pospelove Oct 10, 2023
c97a87d
disable placeatme
Pospelove Oct 10, 2023
2453877
no exterior scripts plz
Pospelove Oct 11, 2023
2270de4
implement spsnippet placeatme for explosions & hack door in BleakFall…
Pospelove Oct 11, 2023
d0134fd
remove placeatme explosion for now & animation saves/restores in most…
Pospelove Oct 11, 2023
454f016
enable aggro & disable unique npcs
Pospelove Oct 12, 2023
0f9e921
i want fix npc death
Pospelove Oct 12, 2023
d0c4d18
will not fix. will just leave huge respawn timer for now. better thin…
Pospelove Oct 12, 2023
c0457d6
different respawn position and delay for npcs
Pospelove Oct 13, 2023
4834e8c
.
Pospelove Oct 14, 2023
33a67fa
enable mp disable command for npcs & stop sending spsnippets to npcs
Pospelove Oct 14, 2023
076c326
polishing
Pospelove Oct 14, 2023
a320cfc
recalculateworn -> equipbestweapon
Pospelove Oct 14, 2023
bac538e
LocationalDataUtils
Pospelove Oct 14, 2023
72ca39a
create method IsCreatedAsPlayer
Pospelove Oct 14, 2023
351fd2b
.
Pospelove Oct 14, 2023
3c49bcb
fix inc
Pospelove Oct 14, 2023
90b1dc5
upload logs for ubuntu
Pospelove Oct 14, 2023
40a8adb
remove --clean-after-build
Pospelove Oct 14, 2023
805a60b
yaml
Pospelove Oct 14, 2023
e2e68d3
.
Pospelove Oct 14, 2023
ee98f61
.
Pospelove Oct 14, 2023
dcb21f9
.
Pospelove Oct 14, 2023
b608050
.
Pospelove Oct 14, 2023
18c55b0
.
Pospelove Oct 14, 2023
9b6066a
.
Pospelove Oct 14, 2023
da000c3
rsm-bsa_patch
Pospelove Oct 14, 2023
abd3e46
rsm-bsa
Pospelove Oct 14, 2023
ed9d253
rsm-bsa
Pospelove Oct 14, 2023
4b37e67
patch structural binding
Pospelove Oct 14, 2023
a3ed3f5
fixcompile
Pospelove Oct 14, 2023
6847945
change respawn time
Pospelove Oct 14, 2023
252dcfd
fix papyrus test
Pospelove Oct 15, 2023
21cfd5f
linelint
Pospelove Oct 15, 2023
5e284a3
clang format
Pospelove Oct 15, 2023
59190f0
a bit better cmakelists
Pospelove Oct 15, 2023
ca18312
add bsa path early validation
Pospelove Oct 17, 2023
d8eb55a
useless refactor
Pospelove Oct 17, 2023
c4c1b60
format
Pospelove Oct 18, 2023
4d98632
add stupid tracing of lookupformbyid
Pospelove Oct 19, 2023
5d6f6d3
add comment
Pospelove Oct 19, 2023
da9406d
add more aggro races
Pospelove Oct 19, 2023
7c2f77c
tiny refact: extract GetEditorLocationalData func
Pospelove Oct 19, 2023
0d0b6d3
add NetImmerse script & refactor folders
Pospelove Oct 20, 2023
c481aff
create database_drivers & save_storages folders, fix tests
Pospelove Oct 20, 2023
86647d3
dont spawn dead actors
Pospelove Oct 20, 2023
7af9f44
fix-eof-rule
Pospelove Oct 20, 2023
c51dfdc
fix-inc
Pospelove Oct 20, 2023
1cd3561
.
Pospelove Oct 20, 2023
109c78b
reformat
Pospelove Oct 20, 2023
c3d385a
fix inc
Pospelove Oct 20, 2023
1f6abd8
add 'archives' cfg option docs
Pospelove Oct 20, 2023
957f6fb
fix build & upload pex
Pospelove Oct 22, 2023
9050cff
Debug.trace added
Pospelove Oct 22, 2023
dff9ba6
add missing header
Pospelove Oct 25, 2023
57f3f8e
renamevar
Pospelove Oct 26, 2023
19918b9
reformat
Pospelove Nov 4, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions .github/workflows/pr-ubuntu-docker.yml
Original file line number Diff line number Diff line change
Expand Up @@ -66,19 +66,33 @@ jobs:
chown -R skymp:skymp /src /home/skymp/.cmake-js

- name: CMake Configure
id: cmake_configure
uses: addnab/docker-run-action@v3
with:
image: ${{ env.SKYMP_VCPKG_DEPS_IMAGE }}
options: |
-v ${{github.workspace}}:/src
-v ${{github.workspace}}/.cmake-js:/home/skymp/.cmake-js
-u skymp
--name configure_container
run: |
cd /src \
&& ./build.sh --configure \
-DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} \
-DUNIT_DATA_DIR="/src/skyrim_data_files"

- name: Copy log file from container to workspace
if: failure()
run: |
sudo docker cp configure_container:/src/vcpkg/buildtrees/rsm-bsa/install-x64-linux-dbg-out.log ${{github.workspace}}/install-x64-linux-dbg-out.log

- name: Upload vcpkg failure logs
if: failure()
uses: actions/upload-artifact@v2
with:
name: install-x64-linux-dbg-out.log
path: ${{github.workspace}}/install-x64-linux-dbg-out.log

- name: Upload compile_commands.json
uses: actions/upload-artifact@v3
with:
Expand Down
1 change: 1 addition & 0 deletions .linelint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ ignore:
- .git/
- '**/third_party'
- 'skymp5-scripts/'
- 'overlay_ports/rsm-bsa/*.patch'

rules:
end-of-file:
Expand Down
7 changes: 6 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,12 @@ endif()

set(VCPKG_OVERLAY_TRIPLETS "${CMAKE_CURRENT_LIST_DIR}/overlay_triplets")
set(VCPKG_OVERLAY_PORTS "${CMAKE_CURRENT_LIST_DIR}/overlay_ports")
set(VCPKG_INSTALL_OPTIONS --no-print-usage --clean-after-build)

if("$ENV{CI}" STREQUAL "true")
set(VCPKG_INSTALL_OPTIONS --no-print-usage)
else()
set(VCPKG_INSTALL_OPTIONS --no-print-usage --clean-after-build)
endif()

if("$ENV{CI}" STREQUAL "true" AND WIN32)
# The same submodule but moved to a larger disk in Windows CI. See action files:
Expand Down
3 changes: 3 additions & 0 deletions cmake/link_vcpkg_dependencies.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -57,5 +57,8 @@ function(link_vcpkg_dependencies)

find_package(OpenSSL REQUIRED)
target_link_libraries(${target} PUBLIC OpenSSL::SSL OpenSSL::Crypto)

find_package(bsa CONFIG REQUIRED)
target_link_libraries(${target} PUBLIC bsa::bsa)
endforeach()
endfunction()
18 changes: 18 additions & 0 deletions docs/docs_server_configuration_reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,24 @@ Absolute paths work but aren't accessible via `uiPort`. External tooling wouldn'
}
```

## archives

Specify BSA archives that will be loaded by the server.

At this moment, used only for compiled Papyrus scripts.

Relative/absolute paths work similar to esp/esm.

```json5
{
// ...
"archives": [
"Skyrim - Misc.bsa"
]
// ...
}
```

## lang

The language, the translation of which will be obtained from the string files located in Data/strings
Expand Down
1 change: 1 addition & 0 deletions docs/release/dev/sp-added-evaluate-lvl-character.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Added experimental `TESModPlatform.EvaluateLeveledNpc` native. It is unstable and shouldn't be used in user plugins. This native is required for SkyMP.
7 changes: 7 additions & 0 deletions libespm/include/libespm/ACHR.h
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#pragma once
#include "REFR.h"
#include "RecordHeader.h"

#pragma pack(push, 1)
Expand All @@ -11,6 +12,12 @@ class ACHR final : public RecordHeader
static constexpr auto kType = "ACHR";

bool StartsDead() const noexcept;

struct Data : public REFR::Data
{
};

Data GetData(CompressedFieldsCache& compressedFieldsCache) const noexcept;
};

static_assert(sizeof(ACHR) == sizeof(RecordHeader));
Expand Down
37 changes: 2 additions & 35 deletions libespm/include/libespm/LVLI.h
Original file line number Diff line number Diff line change
@@ -1,50 +1,17 @@
#pragma once
#include "RecordHeader.h"
#include "LeveledListBase.h"

#pragma pack(push, 1)

namespace espm {

class LVLI final : public RecordHeader
class LVLI final : public LeveledListBase
{
public:
static constexpr auto kType = "LVLI";

enum LeveledItemFlags
{
AllLevels = 0x01, //(sets it to calculate for all entries < player level,
// choosing randomly from all the entries under)
Each = 0x02, // (sets it to repeat a check every time the list is called
// (if it's called multiple times), otherwise it will use the
// same result for all counts.)
UseAll = 0x04, // (use all entries when the list is called)
SpecialLoot = 0x08,
};

struct Entry
{
char type[4] = { 'L', 'V', 'L', 'O' };
uint16_t dataSize = 0;
uint32_t level = 0;
uint32_t formId = 0;
uint32_t count = 0;
};

struct Data
{
const char* editorId = "";
uint8_t chanceNone = 0;
uint8_t leveledItemFlags = 0;
uint32_t chanceNoneGlobalId = 0;
uint8_t numEntries = 0;
const Entry* entries = nullptr;
};

Data GetData(CompressedFieldsCache& compressedFieldsCache) const noexcept;
};

static_assert(sizeof(LVLI) == sizeof(RecordHeader));
static_assert(sizeof(LVLI::Entry) == 18);

}

Expand Down
18 changes: 18 additions & 0 deletions libespm/include/libespm/LVLN.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#pragma once
#include "LeveledListBase.h"

#pragma pack(push, 1)

namespace espm {

class LVLN final : public LeveledListBase
{
public:
static constexpr auto kType = "LVLN";
};

static_assert(sizeof(LVLN) == sizeof(RecordHeader));

}

#pragma pack(pop)
49 changes: 49 additions & 0 deletions libespm/include/libespm/LeveledListBase.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
#pragma once
#include "RecordHeader.h"

#pragma pack(push, 1)

namespace espm {

class LeveledListBase : public RecordHeader
{
public:
enum LeveledItemFlags
{
AllLevels = 0x01, //(sets it to calculate for all entries < player level,
// choosing randomly from all the entries under)
Each = 0x02, // (sets it to repeat a check every time the list is called
// (if it's called multiple times), otherwise it will use the
// same result for all counts.)
UseAll = 0x04, // (use all entries when the list is called)
SpecialLoot = 0x08,
};

struct Entry
{
char type[4] = { 'L', 'V', 'L', 'O' };
uint16_t dataSize = 0;
uint32_t level = 0;
uint32_t formId = 0;
uint32_t count = 0;
};

struct Data
{
const char* editorId = "";
uint8_t chanceNone = 0;
uint8_t leveledItemFlags = 0;
uint32_t chanceNoneGlobalId = 0;
uint8_t numEntries = 0;
const Entry* entries = nullptr;
};

Data GetData(CompressedFieldsCache& compressedFieldsCache) const noexcept;
};

static_assert(sizeof(LeveledListBase) == sizeof(RecordHeader));
static_assert(sizeof(LeveledListBase::Entry) == 18);

}

#pragma pack(pop)
41 changes: 41 additions & 0 deletions libespm/include/libespm/NPC_.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,44 @@ class NPC_ final : public RecordHeader
int8_t rank = 0;
};

enum TemplateFlags : uint16_t
{
// (Destructible Object; Traits tab, including race, gender, height,
// weight, voice type, death item; Sounds tab; Animation tab; Character Gen
// tabs)
UseTraits = 0x01,
// (Stats tab, including level, autocalc, skills, health/magicka/stamina,
// speed, bleedout, class)
UseStats = 0x02,
// (both factions and assigned crime faction)
UseFactions = 0x04,
// (both spells and perks)
UseSpelllist = 0x08,
// (AI Data tab, including aggression/confidence/morality, combat style and
// gift filter)
UseAIData = 0x10,
// (only the basic Packages listed on the AI Packages tab; rest of tab
// controlled by Def Pack List)
UseAIPackages = 0x20,
// Unused?
Unused = 0x40,
// (including name and short name, and flags for Essential, Protected,
// Respawn, Summonable, Simple Actor, and Doesn't affect stealth meter)
UseBaseData = 0x80,
// (Inventory tab, including all outfits and geared-up item -- but not
// death item)
UseInventory = 0x100,
// Scripts
UseScript = 0x200,
// (the dropdown-selected package lists on the AI Packages tab)
UseDefPackList = 0x400,
// (Attack Data tab, including override from behavior graph race, events,
// and data)
UseAttackData = 0x800,
// Keywords
UseKeywords = 0x1000
};

struct Data
{
uint32_t defaultOutfitId = 0;
Expand All @@ -30,13 +68,16 @@ class NPC_ final : public RecordHeader
std::vector<Faction> factions;

bool isEssential = false;
bool isUnique = false;
bool isProtected = false;

uint32_t race = 0;
int16_t healthOffset = 0;
int16_t magickaOffset = 0;
int16_t staminaOffset = 0;
ObjectBounds objectBounds = {};
uint32_t baseTemplate = 0;
uint16_t templateDataFlags = 0;
};

Data GetData(CompressedFieldsCache& compressedFieldsCache) const noexcept;
Expand Down
12 changes: 11 additions & 1 deletion libespm/include/libespm/REFR.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

namespace espm {

class REFR final : public RecordHeader
class REFR : public RecordHeader
{
public:
static constexpr auto kType = "REFR";
Expand All @@ -23,6 +23,12 @@ class REFR final : public RecordHeader
float rotRadians[3];
};

struct ActivationParentInfo
{
uint32_t refrId = 0;
float delay = 0.f;
};

struct Data
{
uint32_t baseId = 0;
Expand All @@ -31,6 +37,10 @@ class REFR final : public RecordHeader
const DoorTeleport* teleport = nullptr;
const float* boundsDiv2 = nullptr;
uint32_t count = 0;
uint8_t isParentActivationOnly = 0;
std::vector<ActivationParentInfo> activationParents;
uint32_t linkedRefKeywordId = 0;
uint32_t linkedRefId = 0;
};

Data GetData(CompressedFieldsCache& compressedFieldsCache) const noexcept;
Expand Down
1 change: 1 addition & 0 deletions libespm/include/libespm/Records.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include "KYWD.h"
#include "LIGH.h"
#include "LVLI.h"
#include "LVLN.h"
#include "MGEF.h"
#include "NAVM.h"
#include "NPC_.h"
Expand Down
12 changes: 12 additions & 0 deletions libespm/src/ACHR.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,16 @@ bool ACHR::StartsDead() const noexcept
return this->flags & 0x200;
}

ACHR::Data ACHR::GetData(
CompressedFieldsCache& compressedFieldsCache) const noexcept
{
REFR::Data data =
reinterpret_cast<const espm::REFR*>(this)->GetData(compressedFieldsCache);

ACHR::Data res;
static_cast<REFR::Data&>(res) = data;

return res;
}

}
4 changes: 2 additions & 2 deletions libespm/src/LVLI.cpp → libespm/src/LeveledListBase.cpp
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
#include "libespm/LVLI.h"
#include "libespm/LeveledListBase.h"
#include "libespm/RecordHeaderAccess.h"
#include <cstring>

namespace espm {

LVLI::Data LVLI::GetData(
LeveledListBase::Data LeveledListBase::GetData(
CompressedFieldsCache& compressedFieldsCache) const noexcept
{
Data result;
Expand Down
7 changes: 6 additions & 1 deletion libespm/src/NPC_.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,14 @@ NPC_::Data NPC_::GetData(
} else if (!std::memcmp(type, "ACBS", 4)) {
const uint32_t flags = *reinterpret_cast<const uint32_t*>(data);

result.isEssential = !!(flags & 0x02);
result.isEssential = !!(flags & 0x2);
result.isUnique = !!(flags & 0x20);
result.isProtected = !!(flags & 0x800);
result.magickaOffset = *reinterpret_cast<const int16_t*>(data + 4);
result.staminaOffset = *reinterpret_cast<const int16_t*>(data + 6);
result.healthOffset = *reinterpret_cast<const int16_t*>(data + 20);
result.templateDataFlags =
*reinterpret_cast<const uint16_t*>(data + 18);

} else if (!std::memcmp(type, "RNAM", 4)) {
result.race = *reinterpret_cast<const uint32_t*>(data);
Expand All @@ -39,6 +42,8 @@ NPC_::Data NPC_::GetData(
}
} else if (!std::memcmp(type, "SPLO", 4)) {
result.spells.emplace(*reinterpret_cast<const uint32_t*>(data));
} else if (!std::memcmp(type, "TPLT", 4)) {
result.baseTemplate = (*reinterpret_cast<const uint32_t*>(data));
}
},
compressedFieldsCache);
Expand Down
Loading
Loading