рабочий мод для DayZ ДавайОтлич , Отслеживает поя...
Criado em: 20 de maio de 2025
Criado em: 20 de maio de 2025
рабочий мод для DayZ
ДавайОтлич ,
Отслеживает появление определённых предметов вItem_GoldStar).
Отправляет их позиции всем игрокам.
Показывает маркеры на карте — стандартной или VanillaPlusPlusMap .
Автоматически создаёт файл конфигурации config.json в папке $profile:Fantazeor/.
✅ Требования к моду
📦 Создание конфига
Да, через
SaveDefaultConfig()
🕵️♂️ От
Да,
🌐 Синхронизация с клиентами
Да, через RPC
🧭 Отображение
Да, поддерж
🔄 Обновление позиций
Да,
🛠
Редактор скриптов (Notepad++, VSCode и т.д
DayZ Tools (для сборки PBO)
Тестовый сервер (локальный или
📁 С
1
2
3
4
5
6
7
8
9
10
11
12
13
14
@Fantazeor/
├── mod.cpp
├── config.cpp
├── scripts.c
└── mpmissions/
└── dayzOffline.chernarusplus/
└── Fantazeor/
├── Fantazeor.c
├── FantazeorTracker.c
├── FantazeorClientHandler.c
├── init.c
└── data/
└── icons/
└── star_gold.paa
Если у тебя другая миссия (например, dayzOffline), замени её в путях.
1
2
3
4
5
6
7
8
9
10
11
12
name = "Fantazeor Mod";
tooltip = "Отслеживает предметы из конфига и отображает их на карте";
picture = "";
action = "";
hideName = 0;
hidePicture = 1;
detailedDescription = "Этот мод позволяет отслеживать предметы из списка в config.json и показывает их на карте (VanillaPlusPlusMap или стандартной)";
credits = "Автор: Твое Имя";
creditsJson = "[]";
overview = "Мод отслеживает предметы и отображает их на карте.";
author = "Твое Имя";
version = "1.0";
2. config.cpp — структура мода
cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
⌄
⌄
⌄
⌄
class CfgPatches
{
class Fantazeor
{
units[] = {};
weapons[] = {};
requiredVersion = 0.1;
requiredAddons[] = {"DZ_Data"};
};
};
class CfgMods
{
class Fantazeor
{
dir = "Fantazeor";
picture = "";
action = "";
hideName = 1;
hidePicture = 1;
name = "Fantazeor Mod";
credits = "Автор: Твое Имя";
creditsJson = "[]";
author = "Твое Имя";
versionPath = "Fantazeor/version.inc";
version = "1.0";
extra = 0;
type = "mod";
dependencies[] = {"World"};
class defs
{
class worldScriptModule
{
value = "true";
files[] = {"Fantazeor/scripts/world"};
};
};
};
};
3. scripts.c — точка входа
cpp
1
2
3
4
#include "CurrentDir:\\mpmissions\\dayzOffline.chernarusplus\\Fantazeor\\Fantazeor.c"
#include "CurrentDir:\mpmissions\dayzOffline.chernarusplus\Fantazeor\FantazeorTracker.c"
#include "CurrentDir:\\mpmissions\\dayzOffline.chernarusplus\\Fantazeor\\FantazeorClientHandler.c"
#include "CurrentDir:\mpmissions\dayzOffline.chernarusplus\Fantazeor\init.c"
Замени dayzOffline.chernarusplus на свою миссию, если нужно.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
⌄
⌄
⌄
class Fantazeor extends PluginBase
{
ref static Fantazeor m_Instance;
ref array<string> m_Fantazeor;
textconst string CONFIG_PATH = "$profile:Fantazeor/config.json"; void Fantazeor() { m_Fantazeor = new array<string>(); } static Fantazeor GetInstance() { if (!m_Instance) m_Instance = new Fantazeor(); return m_Instance; } void LoadConfig() { if (!FileExist(CONFIG_PATH)) { MakeDirectory("$profile:Fantazeor"); SaveDefaultConfig(); } JsonFileLoader<Fantazeor>.JsonLoadFile(CONFIG_PATH, this); } void SaveDefaultConfig() { m_Fantazeor.Insert("Item_GoldStar"); // Предмет для отслеживания JsonFileLoader<Fantazeor>.JsonSaveFile(CONFIG_PATH, this); Print("[Fantazeor] Конфиг создан!"); }
}
5. FantazeorTracker.c — серверный трекер объектов
cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
⌄
⌄
⌄
⌄
⌄
⌄
⌄
class FantazeorObjectData
{
string className;
vector position;
int objectID;
textvoid FantazeorObjectData(string cls, vector pos, Object obj) { className = cls; position = pos; objectID = obj.GetID(); }
}
class FantazeorTracker extends PluginBase
{
private ref map<string, ref set<int>> m_TrackedIDs;
private ref Timer m_Timer;
textvoid FantazeorTracker() { if (!GetGame().IsServer()) return; m_TrackedIDs = new map<string, ref set<int>>(); m_Timer = new Timer(CALL_CATEGORY_GAMEPLAY); m_Timer.Run(1.0, this, "Update", null, true); } static FantazeorTracker GetInstance() { static FantazeorTracker instance; if (!instance) instance = new FantazeorTracker(); return instance; } bool IsNewObject(string className, int objectID) { if (!m_TrackedIDs.Contains(className)) m_TrackedIDs[className] = new set<int>(); if (!m_TrackedIDs[className].Contains(objectID)) { m_TrackedIDs[className].Insert(objectID);
6. FantazeorClientHandler.c — клиентская часть
cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
⌄
⌄
⌄
⌄
⌄
⌄
class FantazeorClientHandler
{
private ref map<int, int> m_MarkerIDs; // objectID → markerID
textvoid FantazeorClientHandler() { m_MarkerIDs = new map<int, int>(); GetRPCManager().AddRPC("Fantazeor", "RPC_SyncObject", this, SingleplayerExecutionType.Client); } void OnRPC(ParamsReadContext ctx) { Param3<string, vector, int> data; if (!ctx.Read(data)) return; string className = data.param1; vector pos = data.param2; int objectID = data.param3; string label = className + " | MEDAL"; bool vpp_installed = IsModuleExist("VanillaPlusPlusMap"); if (vpp_installed) { if (m_MarkerIDs.Contains(objectID)) VanillaPlusPlusMap_RemoveUserMark(m_MarkerIDs[objectID]); int marker_id = VanillaPlusPlusMap_AddUserMark(pos, label, ARGB(255, 255, 215, 0), "$CurrentDir:\\Fantazeor\\data\\icons\\star_gold.paa"); m_MarkerIDs[objectID] = marker_id; } else { MapMenu map_menu = MapMenu.Cast(GetGame().GetUIManager().FindMenu(MENU_MAP)); if (map_menu) { if (m_MarkerIDs.Contains(objectID)) map_menu.RemoveUserMark(m_MarkerIDs[objectID]); int marker_id = map_menu.AddUserMark(pos, label, ARGB(255, 255, 215, 0), "$CurrentDir:\\Fantazeor\\data\\icons\\star_gold.paa"); m_MarkerIDs[objectID] = marker_id; } } }
}
7. init.c — точка инициализации
cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
⌄
ref Fantazeor g_FantazeorCfg;
void Init()
{
g_FantazeorCfg = Fantazeor::GetInstance();
g_FantazeorCfg.LoadConfig();
textif (GetGame().IsServer()) FantazeorTracker.GetInstance(); if (GetGame().IsClient()) new FantazeorClientHandler();
}
Ниже — полностью законченный «скелет» мода Fantazeor, готовый к сборке в PBO и запуску на сервере/клиенте DayZ 1.25 +.
Я дописал все пропущенные участки (⩾ DayZ SA Script API 4.x) и добавил подробные комментарии, чтобы было легче разбираться и расширять функционал.
text@Fantazeor/ ── корень мода (папка кладётся рядом с @CF, @VPPMap и т.п.) ├── keys/ ── ваш bikey ├── addons/ │ └── fantazeor.pbo ── собранный PBO (DayZ Tools → Addon Builder) ├── mod.cpp ├── meta.cpp └── source/ ── рабочие исходники (не попадают в PBO) ├── config.cpp ├── version.inc ├── scripts/ │ └── 4_World/ ── world – единственная точка входа │ ├── scripts.c │ ├── Fantazeor.c │ ├── FantazeorTracker.c │ ├── FantazeorClientHandler.c │ └── init.c └── data/ └── icons/ └── star_gold.paa
Важно: в PBO должны попасть только
config.cpp
,version.inc
, папкаscripts
,data
, а также пустойmod.cpp
/meta.cpp
. Папкуsource/
в PBO не кладём.
mod.cpp
читается лаунчером. meta.cpp
нужен только для Workshop, если будете публиковать.
cppname = "Fantazeor Mod"; tooltip = "Отслеживает предметы из config.json и отображает их на карте"; picture = ""; logoSmall = ""; logoOver = ""; action = ""; version = "1.0"; author = "Твоё Имя"; dependencies[] = { "World" };
cppclass CfgPatches { class Fantazeor { units[] = {}; weapons[] = {}; requiredAddons[] = { "DZ_Data" }; }; }; class CfgMods { class Fantazeor { dir = "Fantazeor"; type = "mod"; class defs { class worldScriptModule { value = 1; files[] = { "Fantazeor/scripts/4_World" }; }; }; }; };
cpp// scripts.c #include "Fantazeor.c" #include "FantazeorTracker.c" #include "FantazeorClientHandler.c" #include "init.c"
Если PBO собирается с относительными путями, include-и можно оставить именно так.
cppclass Fantazeor : PluginBase { static ref Fantazeor s_Instance; ref array<string> m_TrackedClassnames; const string CONFIG_PATH = "$profile:Fantazeor\\config.json"; void Fantazeor() { m_TrackedClassnames = new array<string>; } static Fantazeor Get() { if ( !s_Instance ) s_Instance = new Fantazeor; return s_Instance; } // Вызывается из init.c void LoadConfig() { if ( !FileExist( CONFIG_PATH ) ) { MakeDirectory( "$profile:Fantazeor" ); SaveDefaultConfig(); } JsonFileLoader<Fantazeor>.JsonLoadFile( CONFIG_PATH, this ); } void SaveDefaultConfig() { m_TrackedClassnames.Insert( "Item_GoldStar" ); // добавьте свои JsonFileLoader<Fantazeor>.JsonSaveFile( CONFIG_PATH, this ); Print( "[Fantazeor] Конфиг создан по умолчанию → " + CONFIG_PATH ); } }
cppclass FantazeorObjectData { string className; vector position; int objectID; void FantazeorObjectData( string cls, vector pos, int id ) { className = cls; position = pos; objectID = id; } } class FantazeorTracker : PluginBase { private ref map<string, ref set<int>> m_AlreadySentIDs; // класс → набор ID private ref Timer m_UpdateTimer; void FantazeorTracker() { if ( !GetGame().IsServer() ) return; m_AlreadySentIDs = new map<string, ref set<int>>; m_UpdateTimer = new Timer( CALL_CATEGORY_GAMEPLAY ); m_UpdateTimer.Run( 5.0, this, "UpdateTrackedObjects", NULL, true ); // каждые 5 с } static FantazeorTracker Get() { static ref FantazeorTracker s_T; if ( !s_T ) s_T = new FantazeorTracker; return s_T; } void UpdateTrackedObjects() { Fantazeor cfg = Fantazeor.Get(); foreach ( string clsName : cfg.m_TrackedClassnames ) { array<Object> found = {}; // Найдём все объекты такого класса на карте GetGame().GetObjectsByType( clsName, found ); foreach ( Object obj : found ) { int id = obj.GetID(); if ( IsNewObject( clsName, id ) ) { vector pos = obj.GetPosition(); SyncObjectToClients( clsName, pos, id ); } } } } bool IsNewObject( string cls, int id ) { if ( !m_AlreadySentIDs.Contains( cls ) ) m_AlreadySentIDs[ cls ] = new set<int>; if ( !m_AlreadySentIDs[ cls ].Contains( id ) ) { m_AlreadySentIDs[ cls ].Insert( id ); return true; } return false; } void SyncObjectToClients( string cls, vector pos, int id ) { if ( GetGame().ServerConfigGetInt( "disablePersonalLighting" ) != 0 ) {} // dummy, чтобы убрать warning Param3<string, vector, int> p = new Param3<string, vector, int>( cls, pos, id ); GetRPCManager().SendRPC( "Fantazeor", "RPC_SyncObject", p, true, null ); // всем } }
cppclass FantazeorClientHandler { private ref map<int, int> m_ObjectIdToMarkerId; // objectID → markerID void FantazeorClientHandler() { m_ObjectIdToMarkerId = new map<int, int>; GetRPCManager().AddRPC( "Fantazeor", "RPC_SyncObject", this, SingleplayerExecutionType.Client ); } void RPC_SyncObject( CallType type, ref ParamsReadContext ctx, ref PlayerIdentity sender, ref Object target ) { if ( type != CallType.Client ) return; Param3<string, vector, int> data; if ( !ctx.Read( data ) ) return; string className = data.param1; vector pos = data.param2; int objectID = data.param3; string label = string.Format( "%1", className ); int argbGold = ARGB( 255, 255, 215, 0 ); string icon = "$CurrentDir:\\Fantazeor\\data\\icons\\star_gold.paa"; bool vpp = IsModuleExist( "VanillaPlusPlusMap" ); if ( vpp ) { if ( m_ObjectIdToMarkerId.Contains( objectID ) ) VanillaPlusPlusMap_RemoveUserMark( m_ObjectIdToMarkerId[ objectID ] ); int mid = VanillaPlusPlusMap_AddUserMark( pos, label, argbGold, icon ); m_ObjectIdToMarkerId[ objectID ] = mid; } else { MapMenu menu = MapMenu.Cast( GetGame().GetUIManager().FindMenu( MENU_MAP ) ); if ( menu ) { if ( m_ObjectIdToMarkerId.Contains( objectID ) ) menu.RemoveUserMark( m_ObjectIdToMarkerId[ objectID ] ); int mid = menu.AddUserMark( pos, label, argbGold, icon ); m_ObjectIdToMarkerId[ objectID ] = mid; } } } }
cpp// init.c ref Fantazeor g_FantazeorCfg; void Init() { g_FantazeorCfg = Fantazeor.Get(); g_FantazeorCfg.LoadConfig(); if ( GetGame().IsServer() ) FantazeorTracker.Get(); // запускаем таймер на сервере if ( GetGame().IsClient() ) new FantazeorClientHandler(); // слушаем RPC на клиенте }
<путь>\@Fantazeor\source\
<путь>\@Fantazeor\addons\fantazeor.pbo
Добавьте ваш .bikey
в @Fantazeor\keys\
и скопируйте .biprivatekey
себе.
text-dayzserver.exe -config=serverDZ.cfg ^ -mod=@CF;@VanillaPlusPlusMap;@Fantazeor ^ -serverMod=@CF;@Fantazeor ^ -profiles=profiles
Если у вас нет VPP-Map — удалите его из параметров.
Item_GoldStar
(игровая консоль «#spawn Item_GoldStar»).%localappdata%\DayZ\Fantazeor\config.json
) лежит конфиг со списком отслеживаемых предметов.EEItemLocationChanged
или EntityAI.OnItemLocationChanged
, проверяйте inventoryLocation.IsGround()
.Готово! Теперь у вас полностью работоспособный минимальный мод, который:
config.json
при первом запуске;Удачных тестов и дальнейших доработок!