Initial commit 2
This commit is contained in:
@ -0,0 +1,3 @@
|
||||
// Add
|
||||
|
||||
#define ENABLE_START_ITEMS
|
||||
95
Srcs-Server/game/src/#new files to add/start_item.cpp
Normal file
95
Srcs-Server/game/src/#new files to add/start_item.cpp
Normal file
@ -0,0 +1,95 @@
|
||||
#include "stdafx.h"
|
||||
|
||||
#include "start_item.h"
|
||||
|
||||
#include <fstream>
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
std::vector<BaseItem> g_vecCommonItems;
|
||||
std::vector<BaseItem> g_vecSharedItems;
|
||||
std::unordered_map<BYTE, std::vector<BaseItem>> g_umapJobItems;
|
||||
|
||||
bool LoadStarterItemsFromJSON()
|
||||
{
|
||||
const std::string strPath = LocaleService_GetBasePath() + "/give_basic_weapon.json";
|
||||
std::ifstream ifsFile(strPath);
|
||||
if (!ifsFile.is_open())
|
||||
{
|
||||
sys_err("StarterItems: Failed to open %s", strPath.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
nlohmann::json jRoot;
|
||||
try
|
||||
{
|
||||
ifsFile >> jRoot;
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
sys_err("StarterItems: JSON parse error: %s", e.what());
|
||||
return false;
|
||||
}
|
||||
|
||||
// validate required fields
|
||||
if (!jRoot.contains("common") || !jRoot.contains("shared") || !jRoot.contains("jobs"))
|
||||
{
|
||||
sys_err("StarterItems: Missing required sections in JSON");
|
||||
return false;
|
||||
}
|
||||
|
||||
std::vector<BaseItem> vecCommonItems;
|
||||
std::vector<BaseItem> vecSharedItems;
|
||||
std::unordered_map<BYTE, std::vector<BaseItem>> umapJobItems;
|
||||
|
||||
auto fnParseItem = [](const nlohmann::json& jItem) -> BaseItem {
|
||||
BaseItem stItem;
|
||||
stItem.vnum = jItem["vnum"];
|
||||
stItem.pos = jItem["pos"];
|
||||
stItem.is_equipment = jItem["equip"];
|
||||
stItem.count = jItem.value("count", 1);
|
||||
|
||||
if (jItem.contains("sockets") && jItem["sockets"].is_array())
|
||||
{
|
||||
const auto& jSockets = jItem["sockets"];
|
||||
for (size_t i = 0; i < MIN(jSockets.size(), stItem.sockets.size()); ++i)
|
||||
stItem.sockets[i] = jSockets[i];
|
||||
}
|
||||
|
||||
if (jItem.contains("attrs") && jItem["attrs"].is_array())
|
||||
{
|
||||
const auto& jAttrs = jItem["attrs"];
|
||||
for (size_t i = 0; i < MIN(jAttrs.size(), stItem.attrs.size()); ++i)
|
||||
{
|
||||
stItem.attrs[i].bType = jAttrs[i].value("type", 0);
|
||||
stItem.attrs[i].sValue = jAttrs[i].value("value", 0);
|
||||
}
|
||||
}
|
||||
|
||||
return stItem;
|
||||
};
|
||||
|
||||
for (const auto& jItem : jRoot["common"])
|
||||
vecCommonItems.emplace_back(fnParseItem(jItem));
|
||||
|
||||
for (const auto& jItem : jRoot["shared"])
|
||||
vecSharedItems.emplace_back(fnParseItem(jItem));
|
||||
|
||||
for (const auto& [strKey, jItems] : jRoot["jobs"].items())
|
||||
{
|
||||
BYTE byJob = static_cast<BYTE>(std::stoi(strKey));
|
||||
if (!jItems.is_array())
|
||||
continue;
|
||||
|
||||
auto& vecJob = umapJobItems[byJob];
|
||||
for (const auto& jItem : jItems)
|
||||
vecJob.emplace_back(fnParseItem(jItem));
|
||||
}
|
||||
|
||||
// commit parsed items
|
||||
g_vecCommonItems = std::move(vecCommonItems);
|
||||
g_vecSharedItems = std::move(vecSharedItems);
|
||||
g_umapJobItems = std::move(umapJobItems);
|
||||
|
||||
sys_log(0, "StarterItems: Loaded successfully from %s", strPath.c_str());
|
||||
return true;
|
||||
}
|
||||
20
Srcs-Server/game/src/#new files to add/start_item.h
Normal file
20
Srcs-Server/game/src/#new files to add/start_item.h
Normal file
@ -0,0 +1,20 @@
|
||||
#pragma once
|
||||
#include "locale_service.h"
|
||||
|
||||
#include "../../common/tables.h"
|
||||
#include "../../common/item_length.h"
|
||||
|
||||
struct BaseItem
|
||||
{
|
||||
DWORD vnum;
|
||||
BYTE pos;
|
||||
bool is_equipment;
|
||||
BYTE count{1};
|
||||
std::array<long, ITEM_SOCKET_MAX_NUM> sockets{};
|
||||
std::array<TPlayerItemAttribute, ITEM_ATTRIBUTE_MAX_NUM> attrs{};
|
||||
};
|
||||
|
||||
extern std::vector<BaseItem> g_vecCommonItems;
|
||||
extern std::vector<BaseItem> g_vecSharedItems;
|
||||
extern std::unordered_map<BYTE, std::vector<BaseItem>> g_umapJobItems;
|
||||
extern bool LoadStarterItemsFromJSON();
|
||||
7
Srcs-Server/game/src/Makefile
Normal file
7
Srcs-Server/game/src/Makefile
Normal file
@ -0,0 +1,7 @@
|
||||
## 1.) Look for
|
||||
|
||||
DragonSoul.cpp
|
||||
|
||||
# replace with:
|
||||
|
||||
DragonSoul.cpp start_item.cpp
|
||||
37
Srcs-Server/game/src/cmd_gm.cpp
Normal file
37
Srcs-Server/game/src/cmd_gm.cpp
Normal file
@ -0,0 +1,37 @@
|
||||
/// 1.) Search at the begin of the file
|
||||
|
||||
#include "unique_item.h"
|
||||
#include "DragonSoul.h"
|
||||
|
||||
// and add under, this:
|
||||
|
||||
#ifdef ENABLE_START_ITEMS
|
||||
#include "start_item.h"
|
||||
#endif
|
||||
|
||||
/// 2.) Search in void CHARACTER::MountVnum(DWORD vnum):
|
||||
|
||||
//RELOAD_ADMIN
|
||||
case 'a':
|
||||
ch->ChatPacket(CHAT_TYPE_INFO, "Reloading Admin infomation.");
|
||||
db_clientdesc->DBPacket(HEADER_GD_RELOAD_ADMIN, 0, NULL, 0);
|
||||
sys_log(0, "Reloading admin infomation.");
|
||||
break;
|
||||
//END_RELOAD_ADMIN
|
||||
case 'c': // cube
|
||||
// ·ÎÄà ÇÁ·Î¼¼½º¸¸ °»»êÇÑ´Ù.
|
||||
Cube_init ();
|
||||
break;
|
||||
|
||||
default:
|
||||
{
|
||||
|
||||
// and add under, this:
|
||||
|
||||
#ifdef ENABLE_START_ITEMS
|
||||
if (strstr(arg1, "give_basic_weapon"))
|
||||
{
|
||||
ch->ChatPacket(CHAT_TYPE_INFO, "Reloading: give_basic_weapon");
|
||||
LoadStarterItemsFromJSON();
|
||||
}
|
||||
#endif
|
||||
111
Srcs-Server/game/src/input_db.cpp
Normal file
111
Srcs-Server/game/src/input_db.cpp
Normal file
@ -0,0 +1,111 @@
|
||||
/// 1.) Search at the begin of the file
|
||||
|
||||
#include "map_location.h"
|
||||
|
||||
#include "DragonSoul.h"
|
||||
|
||||
// and add under, this:
|
||||
|
||||
#ifdef ENABLE_START_ITEMS
|
||||
#include "start_item.h"
|
||||
#endif
|
||||
|
||||
/// 2.) Scroll a bit down and look for
|
||||
|
||||
extern void gm_insert(const char * name, BYTE level);
|
||||
extern BYTE gm_get_level(const char * name, const char * host, const char* account);
|
||||
extern void gm_host_insert(const char * host);
|
||||
|
||||
// and add under, this:
|
||||
|
||||
#ifdef ENABLE_START_ITEMS
|
||||
extern bool RaceToJob(unsigned race, unsigned* ret_job);
|
||||
#endif
|
||||
|
||||
/// 3.) Search:
|
||||
|
||||
void CInputDB::PlayerCreateSuccess(LPDESC d, const char * data)
|
||||
{
|
||||
[...]
|
||||
}
|
||||
|
||||
// and add UPPER, this:
|
||||
|
||||
#ifdef ENABLE_START_ITEMS
|
||||
static void PlayerCreateGiveBasicItems(const DWORD dwPlayerID, const BYTE byJob)
|
||||
{
|
||||
// extract real job
|
||||
unsigned int real_job = 0;
|
||||
RaceToJob(byJob, &real_job);
|
||||
|
||||
// helper lambda to give items
|
||||
auto fnGiveItem = [&](const BaseItem& item)
|
||||
{
|
||||
if (!item.vnum)
|
||||
return;
|
||||
|
||||
TPlayerItem t{};
|
||||
t.id = ITEM_MANAGER::instance().GetNewID();
|
||||
t.owner = dwPlayerID;
|
||||
t.window = item.is_equipment ? EQUIPMENT : INVENTORY;
|
||||
t.pos = item.pos;
|
||||
t.vnum = item.vnum;
|
||||
t.count = item.count;
|
||||
|
||||
std::copy(item.sockets.begin(), item.sockets.end(), t.alSockets);
|
||||
std::copy(item.attrs.begin(), item.attrs.end(), t.aAttr);
|
||||
|
||||
db_clientdesc->DBPacketHeader(HEADER_GD_ITEM_SAVE, 0, sizeof(t));
|
||||
db_clientdesc->Packet(&t, sizeof(t));
|
||||
};
|
||||
|
||||
// items giving
|
||||
for (const auto& item : g_vecCommonItems)
|
||||
fnGiveItem(item);
|
||||
|
||||
for (const auto& item : g_vecSharedItems)
|
||||
fnGiveItem(item);
|
||||
|
||||
if (auto it = g_umapJobItems.find(real_job); it != g_umapJobItems.end())
|
||||
{
|
||||
for (const auto& item : it->second)
|
||||
fnGiveItem(item);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/// 3.) Search always inside void CInputDB::PlayerCreateSuccess(LPDESC d, const char * data):
|
||||
|
||||
TPacketGCPlayerCreateSuccess pack{};
|
||||
|
||||
pack.header = HEADER_GC_CHARACTER_CREATE_SUCCESS;
|
||||
pack.bAccountCharacterIndex = pPacketDB->bAccountCharacterIndex;
|
||||
pack.player = pPacketDB->player;
|
||||
|
||||
d->Packet(&pack, sizeof(TPacketGCPlayerCreateSuccess));
|
||||
|
||||
|
||||
// and add under (like before the function end), this:
|
||||
|
||||
#ifdef ENABLE_START_ITEMS
|
||||
// Base items
|
||||
PlayerCreateGiveBasicItems(pPacketDB->player.dwID, pPacketDB->player.byJob);
|
||||
#endif
|
||||
|
||||
// like:
|
||||
/*
|
||||
....
|
||||
pack.header = HEADER_GC_CHARACTER_CREATE_SUCCESS;
|
||||
pack.bAccountCharacterIndex = pPacketDB->bAccountCharacterIndex;
|
||||
pack.player = pPacketDB->player;
|
||||
|
||||
d->Packet(&pack, sizeof(TPacketGCPlayerCreateSuccess));
|
||||
|
||||
#ifdef ENABLE_START_ITEMS
|
||||
// Base items
|
||||
PlayerCreateGiveBasicItems(pPacketDB->player.dwID, pPacketDB->player.byJob);
|
||||
#endif
|
||||
|
||||
LogManager::instance().CharLog(pack.player.dwID, 0, 0, 0, "CREATE PLAYER", "", d->GetHostName());
|
||||
}
|
||||
*/
|
||||
22
Srcs-Server/game/src/main.cpp
Normal file
22
Srcs-Server/game/src/main.cpp
Normal file
@ -0,0 +1,22 @@
|
||||
/// 1.) Search at the begin of the file
|
||||
|
||||
#include "skill_power.h"
|
||||
#include "DragonSoul.h"
|
||||
|
||||
// and add under, this:
|
||||
|
||||
#ifdef ENABLE_START_ITEMS
|
||||
#include "start_item.h"
|
||||
#endif
|
||||
|
||||
/// 2.) Search inside int main(int argc, char **argv):
|
||||
|
||||
Blend_Item_init();
|
||||
ani_init();
|
||||
PanamaLoad();
|
||||
|
||||
// and add under, this:
|
||||
|
||||
#ifdef ENABLE_START_ITEMS
|
||||
LoadStarterItemsFromJSON();
|
||||
#endif
|
||||
Reference in New Issue
Block a user