Skip to content

Commit

Permalink
Merge branch 'dev/new-features' into dev/master
Browse files Browse the repository at this point in the history
  • Loading branch information
JellyBitz committed Aug 10, 2021
2 parents 379ccd7 + ee38fe2 commit 5f093db
Show file tree
Hide file tree
Showing 6 changed files with 148 additions and 51 deletions.
10 changes: 10 additions & 0 deletions README.CLIENT.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,16 @@ This is a compilations of ASM/editions for vSRO (1.188) that you'll need to chan
006BA767 | 68 FFE30B54 | push 540BE3FF |
```

### SERVER_RESURRECT_SAME_POINT_LEVEL_MAX

0xA = 10

```
00645688 | 3C 0A | cmp al,A | Show message
00797E21 | 3C 0A | cmp al,A | Unlock action
```

### RACE_CH_TOTAL_MASTERIES

0x14A = 330, 0xDC = 220
Expand Down
31 changes: 24 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,13 @@ Customize Silkroad Online server files (v1.188) behavior through DLL injection.

1. Make a backup from your `SR_GameServer.exe` and `SR_ShardManager.exe` just in case something goes wrong
2. Download, install, and execute [*Stud_PE*](http://www.cgsoftlabs.ro/zip/Stud_PE.zip)
3. Drag & drop `SR_GameServer.exe` into *Stud_PE*
4. Go to `Functions` tab, right click into any line at left blue panel and click `Add New Import`
5. Click `Dll Select` and find `vSRO-GameServer.dll`
6. Click `Select func` and select the one there, then `OK`
7. Click `Add to list` and click `ADD`, then `OK`
8. Extract `vSRO-ServerAddon.bin.zip` to the same folder where is located `SR_GameServer.exe`
9. Done! Just repeat Step 3 to 7 using `SR_ShardManager.exe` and `vSRO-ShardManager.dll`
3. Extract `vSRO-ServerAddon.bin.zip` to the folder where your server files are located
4. Drag & drop `SR_GameServer.exe` into *Stud_PE*
5. Go to `Functions` tab, right click into any line at left blue panel and click `Add New Import`
6. Click `Dll Select` and find `vSRO-GameServer.dll`
7. Click `Select func` and select the one there, then `OK`
8. Click `Add to list` and click `ADD`, then `OK`
9. Done! Just repeat Step 4 to 8 using `SR_ShardManager.exe` and `vSRO-ShardManager.dll`

## Gameserver Actions

Expand Down Expand Up @@ -342,6 +342,23 @@ VALUES
);
```

18. Updates PVP cape type from player
```sql
INSERT INTO [SRO_VT_SHARD].[dbo].[_ExeGameServer]
(
Action_ID,
CharName16,
Param02 -- PVP Type (0 = None, 1 = Red, 2 = Gray, 3 = Blue, 4 = White, 5 = Yellow)
)
VALUES
(
18,
'JellyBitz',
5 -- Yellow (All are enemies)
);
```


### Action Result Code

```C++
Expand Down
143 changes: 100 additions & 43 deletions vSRO-GameServer/AppManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
bool AppManager::m_IsInitialized;
DatabaseLink AppManager::m_dbLink, AppManager::m_dbLinkHelper, AppManager::m_dbUniqueLog;
bool AppManager::m_IsRunningDatabaseFetch;
std::string AppManager::m_CTF_ITEM_WINNING_REWARD, AppManager::m_CTF_ITEM_KILLING_REWARD, AppManager::m_BA_ITEM_REWARD;

void AppManager::Initialize()
{
Expand Down Expand Up @@ -51,11 +52,14 @@ void AppManager::InitConfigFile()
ini.SetLongValue("Server", "STALL_PRICE_LIMIT", 9999999999, "; Maximum price that can be stalled");
ini.SetLongValue("Server", "PARTY_MOB_MEMBERS_REQUIRED", 2, "; Party members required to find monsters party type");
ini.SetLongValue("Server", "PARTY_MOB_SPAWN_PROBABILITY", 50, "; % Probability for party mob spawns");
ini.SetLongValue("Server", "PENALTY_DROP_PROBABILITY", 5, "; % Probability to drop an item when a player dies");
ini.SetLongValue("Server", "PK_LEVEL_REQUIRED", 20, "; Level required to kill other player");
ini.SetLongValue("Server", "PENALTY_DROP_LEVEL_MIN", 10, "; Minimum level to apply drop penalty");
ini.SetLongValue("Server", "PENALTY_DROP_PROBABILITY", 5, "; % Probability to drop an item when a player dies");
ini.SetLongValue("Server", "RESURRECT_SAME_POINT_LEVEL_MAX", 10, "; Maximum level for resurrect at the same map position");
ini.SetLongValue("Server", "NPC_RETURN_DEAD_LEVEL_MAX", 20, "; Maximum level for using \"Return to last dead point\" from NPC Guide");
ini.SetLongValue("Server", "BEGINNER_MARK_LEVEL_MAX", 19, "; Maximum level to show the beginner mark");
ini.SetLongValue("Job", "LEVEL_MAX", 7, "; Maximum level that can be reached on job suit");
ini.SetBoolValue("Job", "DISABLE_MOB_SPAWN", false, "; Disable Thief/Hunter monster spawn while trading");
ini.SetLongValue("Race", "CH_TOTAL_MASTERIES", 330, "; Masteries amount Chinese will obtain");
ini.SetLongValue("Guild", "MEMBERS_LIMIT_LEVEL1", 15, "; Guild members capacity at level 1");
ini.SetLongValue("Guild", "MEMBERS_LIMIT_LEVEL2", 20, "; Guild members capacity at level 2");
Expand All @@ -66,16 +70,18 @@ void AppManager::InitConfigFile()
ini.SetLongValue("Guild", "STORAGE_SLOTS_INCREASE", 30, "; Storage slots increased per level");
ini.SetLongValue("Guild", "UNION_LIMIT", 8, "; Union participants limit");
ini.SetLongValue("Guild", "UNION_CHAT_PARTICIPANTS", 12, "; Union chat participants allowed by guild");
ini.SetLongValue("Academy", "GRADUATE_BEGINNER_LEVEL", 40, "; Graduation level for the beginner members");
ini.SetLongValue("Academy", "DISBAND_PENALTY_TIME", 604800, "; Penalty time (seconds) to create again the group");
ini.SetLongValue("Alchemy", "FUSING_DELAY", 3, "; Waiting delay (seconds) after fusing alchemy elements");
ini.SetValue("Event","CTF_ITEM_REWARD","ITEM_ETC_E070919_TROPHY","; Item reward from Capture The Flag");
ini.SetLongValue("Event", "CTF_ITEM_REWARD_AMOUNT", 1, "; Amount to obtain per every kill");
ini.SetLongValue("Alchemy", "STONE_ASTRAL_VALUE", 4, "; Value from astral stones used to stop and prevent +0");
ini.SetValue("Event", "CTF_ITEM_WIN_REWARD", "ITEM_ETC_E080723_ICETROPHY", "; Item reward from winning Capture The Flag");
ini.SetLongValue("Event", "CTF_ITEM_WIN_REWARD_AMOUNT", 1, "; Amount to obtain by winning");
ini.SetValue("Event", "CTF_ITEM_KILL_REWARD", "ITEM_ETC_E080723_ICETROPHY", "; Item reward from killing at Capture The Flag");
ini.SetLongValue("Event", "CTF_ITEM_KILL_REWARD_AMOUNT", 1, "; Amount to obtain by kill");
ini.SetValue("Event","BA_ITEM_REWARD","ITEM_ETC_ARENA_COIN","; Item reward from Battle Arena");
ini.SetLongValue("Event", "BA_ITEM_REWARD_GJ_W_AMOUNT", 7, "; Amount to obtain winning on Guild/Job mode");
ini.SetLongValue("Event", "BA_ITEM_REWARD_GJ_L_AMOUNT", 2, "; Amount to obtain loosing");
ini.SetLongValue("Event", "BA_ITEM_REWARD_PR_W_AMOUNT", 7, "; Amount to obtain winning on Party/Random mode");
ini.SetLongValue("Event", "BA_ITEM_REWARD_PR_L_AMOUNT", 2, "; Amount to obtain loosing");
ini.SetLongValue("Event", "BA_ITEM_REWARD_PR_W_AMOUNT", 5, "; Amount to obtain winning on Party/Random mode");
ini.SetLongValue("Event", "BA_ITEM_REWARD_PR_L_AMOUNT", 1, "; Amount to obtain loosing");
ini.SetLongValue("Fix", "AGENT_SERVER_CAPACITY", 1000, "; Set capacity supported by the connected agent server");
ini.SetBoolValue("Fix", "HIGH_RATES_CONFIG", true, "; Fix rates (ExpRatio/1000) to use higher values than 2500");
ini.SetBoolValue("Fix", "UNIQUE_LOGS", true, "; Log unique spawn/killed into _AddLogChar as EventID = 32/33");
Expand Down Expand Up @@ -228,12 +234,24 @@ void AppManager::InitPatchValues()
printf(" - SERVER_PK_LEVEL_REQUIRED (%d) -> (%d)\r\n", byteValue, newValue);
WriteMemoryValue<uint8_t>(0x005295DA + 1, newValue);
}
if (ReadMemoryValue<uint8_t>(0x004E6A33 + 1, byteValue))
{
uint8_t newValue = ini.GetLongValue("Server", "PENALTY_DROP_LEVEL_MIN", 10);
printf(" - SERVER_PENALTY_DROP_LEVEL_MIN (%d) -> (%d)\r\n", byteValue, newValue);
WriteMemoryValue<uint8_t>(0x004E6A33 + 1, newValue);
}
if (ReadMemoryValue<uint8_t>(0x004E696D + 1, byteValue))
{
uint8_t newValue = ini.GetLongValue("Server", "PENALTY_DROP_PROBABILITY", 5);
printf(" - SERVER_PENALTY_DROP_PROBABILITY (%d) -> (%d)\r\n", byteValue, newValue);
WriteMemoryValue<uint8_t>(0x004E696D + 1, newValue);
}
if (ReadMemoryValue<uint8_t>(0x0051017F + 1, byteValue))
{
uint8_t newValue = ini.GetLongValue("Server", "RESURRECT_SAME_POINT_LEVEL_MAX", 10);
printf(" - SERVER_RESURRECT_SAME_POINT_LEVEL_MAX (%d) -> (%d)\r\n", byteValue, newValue);
WriteMemoryValue<uint8_t>(0x0051017F + 1, newValue);
}
if (ReadMemoryValue<uint8_t>(0x004F36F3 + 1, byteValue))
{
uint8_t newValue = ini.GetLongValue("Server", "NPC_RETURN_DEAD_LEVEL_MAX", 20);
Expand All @@ -255,7 +273,12 @@ void AppManager::InitPatchValues()
printf(" - JOB_LEVEL_MAX (%d) -> (%d)\r\n", byteValue, newValue);
WriteMemoryValue<uint8_t>(0x0060DE69 + 3, newValue);
}

if (ini.GetBoolValue("Job", "DISABLE_MOB_SPAWN", false))
{
printf(" - JOB_DISABLE_MOB_SPAWN\r\n");
WriteMemoryValue<uint16_t>(0x0060C4AB, 0xC031); // mov eax,esi -> xor eax,eax
}

// Race
if (ReadMemoryValue<uint32_t>(0x0059C5E6 + 1, uintValue))
{
Expand Down Expand Up @@ -327,13 +350,6 @@ void AppManager::InitPatchValues()
}

// Academy
if (ReadMemoryValue<uint8_t>(0x00519883 + 2, byteValue))
{
uint8_t newValue = ini.GetLongValue("Academy", "GRADUATE_BEGINNER_LEVEL", 40);
printf(" - ACADEMY_GRADUATE_BEGINNER_LEVEL (%d) -> (%d)\r\n", byteValue, newValue);
WriteMemoryValue<uint8_t>(0x00519883 + 2, newValue);
WriteMemoryValue<uint8_t>(0x005196CD + 1, newValue);
}
if (ReadMemoryValue<uint32_t>(0x005DD36A + 1, uintValue))
{
uint32_t newValue = ini.GetLongValue("Academy", "DISBAND_PENALTY_TIME", 604800);
Expand All @@ -349,42 +365,71 @@ void AppManager::InitPatchValues()
printf(" - ALCHEMY_FUSING_DELAY (%d) -> (%d)\r\n", byteValue, newValue);
WriteMemoryValue<uint8_t>(0x0052ADAA + 6, newValue);
}
if (ReadMemoryValue<uint8_t>(0x00506D92 + 2, byteValue))
{
uint8_t newValue = ini.GetLongValue("Alchemy", "STONE_ASTRAL_VALUE", 4);
printf(" - ALCHEMY_STONE_ASTRAL_VALUE (%d) -> (%d)\r\n", byteValue, newValue);
WriteMemoryValue<uint8_t>(0x00506D92 + 2, newValue);
WriteMemoryValue<uint8_t>(0x00506DD2 + 1, newValue);
}

// Event
{
const char* newValue = ini.GetValue("Event", "CTF_ITEM_REWARD", "ITEM_ETC_E070919_TROPHY");
auto newValueLen = strlen(newValue);
// Change value if it's not empty and the CodeName is shorter than 128 bytes
if (newValueLen != 0 && newValueLen <= 128)
auto currentValue = ReadMemoryString(0x00646D42 + 1);
if (!currentValue.empty())
{
auto currentValue = ReadMemoryString(0x00646D42 + 1);
printf(" - EVENT_CTF_ITEM_REWARD (%s) -> (%s)\r\n", currentValue.c_str(), newValue);
// Overwrites new char* into empty memory
WriteMemoryString(0x00AD8FFD - 130, newValue);
// Set char* pointer to the new value
WriteMemoryValue<uint32_t>(0x00646D42 + 1, 0x00AD8FFD - 130);
WriteMemoryValue<uint32_t>(0x005F19A9 + 1, 0x00AD8FFD - 130);
WriteMemoryValue<uint32_t>(0x00876935 + 6, 0x00AD8FFD - 130);
m_CTF_ITEM_WINNING_REWARD = ini.GetValue("Event", "CTF_ITEM_WIN_REWARD", "ITEM_ETC_E080723_ICETROPHY");
auto newValueLen = m_CTF_ITEM_WINNING_REWARD.size();
// Check value it's not empty and shorter than 128 bytes
if (newValueLen != 0 && newValueLen <= 128)
{
printf(" - EVENT_CTF_ITEM_WIN_REWARD (%s) -> (%s)\r\n", currentValue.c_str(), m_CTF_ITEM_WINNING_REWARD.c_str());
// Set char* pointer to the new value
WriteMemoryValue<uint32_t>(0x00646D42 + 1, (uint32_t)m_CTF_ITEM_WINNING_REWARD.c_str()); // Winning Reward
WriteMemoryValue<uint32_t>(0x00876935 + 6, (uint32_t)m_CTF_ITEM_WINNING_REWARD.c_str()); // Just in case, something about Quest reward required probably
}
}
}
if (ReadMemoryValue<uint8_t>(0x00646C93 + 4, byteValue))
if (ReadMemoryValue<uint8_t>(0x00646D40 + 1, byteValue))
{
uint8_t newValue = ini.GetLongValue("Event", "CTF_ITEM_REWARD_AMOUNT", 1);
printf(" - EVENT_CTF_ITEM_REWARD_AMOUNT (%d) -> (%d)\r\n", byteValue, newValue);
WriteMemoryValue<uint8_t>(0x00646C93 + 4, newValue);
uint8_t newValue = ini.GetLongValue("Event", "CTF_ITEM_WIN_REWARD_AMOUNT", 1);
printf(" - EVENT_CTF_ITEM_WIN_REWARD_AMOUNT (%d) -> (%d)\r\n", byteValue, newValue);
WriteMemoryValue<uint8_t>(0x00646D40 + 1, newValue);
}
{
const char* newValue = ini.GetValue("Event", "BA_ITEM_REWARD", "ITEM_ETC_ARENA_COIN");
auto newValueLen = strlen(newValue);
// Change value if it's not empty and the CodeName is shorter than 128 bytes
if (newValueLen != 0 && newValueLen <= 128)
auto currentValue = ReadMemoryString(0x005F19A9 + 1);
if (!currentValue.empty())
{
auto currentValue = ReadMemoryString(0x006691C6 + 1);
printf(" - EVENT_BA_ITEM_REWARD (%s) -> (%s)\r\n", currentValue.c_str(), newValue);
// Overwrites new char* into empty memory
WriteMemoryString(0x00AD8FFD - 130 - 130, newValue);
// Set char* pointer to the new value
WriteMemoryValue<uint32_t>(0x006691C6 + 1, 0x00AD8FFD - 130 - 130);
m_CTF_ITEM_KILLING_REWARD = ini.GetValue("Event", "CTF_ITEM_KILL_REWARD", "ITEM_ETC_E080723_ICETROPHY");
auto newValueLen = m_CTF_ITEM_KILLING_REWARD.size();
// Check value it's not empty and shorter than 128 bytes
if (newValueLen != 0 && newValueLen <= 128)
{
printf(" - EVENT_CTF_ITEM_KILL_REWARD (%s) -> (%s)\r\n", currentValue.c_str(), m_CTF_ITEM_KILLING_REWARD.c_str());
// Set char* pointer to the new value
WriteMemoryValue<uint32_t>(0x005F19A9 + 1, (uint32_t)m_CTF_ITEM_KILLING_REWARD.c_str()); // Killing Reward
}
}
}
if (ReadMemoryValue<uint8_t>(0x005F1997 + 1, byteValue))
{
uint8_t newValue = ini.GetLongValue("Event", "CTF_ITEM_KILL_REWARD_AMOUNT", 1);
printf(" - EVENT_CTF_ITEM_KILL_REWARD_AMOUNT (%d) -> (%d)\r\n", byteValue, newValue);
WriteMemoryValue<uint8_t>(0x005F1997 + 1, newValue);
}
{
auto currentValue = ReadMemoryString(0x006691C6 + 1);
if (!currentValue.empty())
{
m_BA_ITEM_REWARD = ini.GetValue("Event", "BA_ITEM_REWARD", "ITEM_ETC_ARENA_COIN");
auto newValueLen = m_BA_ITEM_REWARD.size();
// Check value it's not empty and shorter than 128 bytes
if (newValueLen != 0 && newValueLen <= 128)
{
printf(" - EVENT_BA_ITEM_REWARD (%s) -> (%s)\r\n", currentValue.c_str(), m_BA_ITEM_REWARD.c_str());
// Set char* pointer to the new value
WriteMemoryValue<uint32_t>(0x006691C6 + 1, (uint32_t)m_BA_ITEM_REWARD.c_str());
}
}
}
if (ReadMemoryValue<uint8_t>(0x00669158 + 4, byteValue))
Expand All @@ -401,13 +446,13 @@ void AppManager::InitPatchValues()
}
if (ReadMemoryValue<uint8_t>(0x0066915F + 4, byteValue))
{
uint8_t newValue = ini.GetLongValue("Event", "BA_ITEM_REWARD_PR_W_AMOUNT", 7);
uint8_t newValue = ini.GetLongValue("Event", "BA_ITEM_REWARD_PR_W_AMOUNT", 5);
printf(" - EVENT_BA_ITEM_REWARD_PR_W_AMOUNT (%d) -> (%d)\r\n", byteValue, newValue);
WriteMemoryValue<uint8_t>(0x0066915F + 4, newValue);
}
if (ReadMemoryValue<uint8_t>(0x0066917A + 4, byteValue))
{
uint8_t newValue = ini.GetLongValue("Event", "BA_ITEM_REWARD_PR_L_AMOUNT", 2);
uint8_t newValue = ini.GetLongValue("Event", "BA_ITEM_REWARD_PR_L_AMOUNT", 1);
printf(" - EVENT_BA_ITEM_REWARD_PR_L_AMOUNT (%d) -> (%d)\r\n", byteValue, newValue);
WriteMemoryValue<uint8_t>(0x0066917A + 4, newValue);
}
Expand Down Expand Up @@ -477,7 +522,7 @@ void AppManager::InitDatabaseFetch()
connString << "SERVER=" << ini.GetValue("Sql", "HOST", "localhost") << ", " << ini.GetValue("Sql", "PORT", "1433") << ";";
connString << "DATABASE=" << ini.GetValue("Sql", "DB_SHARD", "SRO_VT_SHARD") << ";";
connString << "UID=" << ini.GetValue("Sql", "USER", "sa") << ";";
connString << "PWD=" << ini.GetValue("Sql", "PASS", "12341") << ";";
connString << "PWD=" << ini.GetValue("Sql", "PASS", "1234") << ";";

if (m_dbLink.sqlConn.Open((SQLWCHAR*)connString.str().c_str()) && m_dbLink.sqlCmd.Open(m_dbLink.sqlConn)
&& m_dbLinkHelper.sqlConn.Open((SQLWCHAR*)connString.str().c_str()) && m_dbLinkHelper.sqlCmd.Open(m_dbLinkHelper.sqlConn))
Expand Down Expand Up @@ -842,6 +887,18 @@ DWORD WINAPI AppManager::DatabaseFetchThread()
actionResult = FETCH_ACTION_STATE::CHARNAME_NOT_FOUND;
}
} break;
case 18: // Update PVP cape type
{
SQLUSMALLINT cParam02;
if (m_dbLink.sqlCmd.GetData(5, SQL_C_USHORT, &cParam02, 0, NULL))
{
CGObjPC* player = CGObjManager::GetObjPCByCharName16(cCharName);
if (player)
player->UpdatePVPCapeType(cParam02);
else
actionResult = FETCH_ACTION_STATE::CHARNAME_NOT_FOUND;
}
} break;
case 3312: // For testing references
{
CGObjPC* player = CGObjManager::GetObjPCByCharName16(cCharName);
Expand Down
5 changes: 5 additions & 0 deletions vSRO-GameServer/AppManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include "Database/SQLConnection.h"
#include "Database/SQLCommand.h"
#include <cstdint>
#include <string>

// All states fetching can generate
enum FETCH_ACTION_STATE {
Expand Down Expand Up @@ -31,6 +32,10 @@ class AppManager
static DatabaseLink m_dbLink, m_dbLinkHelper, m_dbUniqueLog;
// Flag to keep thread safe
static bool m_IsRunningDatabaseFetch;
// Keeps in memory the value assigned
static std::string m_CTF_ITEM_WINNING_REWARD;
static std::string m_CTF_ITEM_KILLING_REWARD;
static std::string m_BA_ITEM_REWARD;
public: // Public Methods
// Initialize manager
static void Initialize();
Expand Down
8 changes: 7 additions & 1 deletion vSRO-GameServer/Silkroad/Object/CGObjPC.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ void CGObjPC::UpdateGold(int64_t Offset)
}
void CGObjPC::UpdateHwan(uint8_t Level)
{
reinterpret_cast<void(__thiscall*)(CGObjPC*, uint8_t)>(0x004A9F40)(this, Level);
return CallVirtual<void(__thiscall*)(CGObjPC*, uint8_t)>(this, 197)(this, Level);
}
void CGObjPC::UpdateExperience(int64_t ExpOffset)
{
Expand All @@ -46,6 +46,12 @@ void CGObjPC::UpdateHPMP(int32_t Health, int32_t Mana, uint16_t DisplayEffectTyp
{
CallVirtual<void(__thiscall*)(CGObjPC*, int32_t, int32_t, uint16_t)>(this, 194)(this, Health, Mana, DisplayEffectType);
}
void CGObjPC::UpdatePVPCapeType(uint8_t CapeType)
{
// Avoid unnecesary updates
if (CapeType <= 5)
reinterpret_cast<void(__thiscall*)(CGObjPC*, uint8_t)>(0x004F0E90)(this, CapeType);
}
bool CGObjPC::MoveTo(uint16_t RegionId, float PosX, float PosY, float PosZ)
{
uint32_t gwid = 0;
Expand Down
2 changes: 2 additions & 0 deletions vSRO-GameServer/Silkroad/Object/CGObjPC.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ class CGObjPC : public CGObjChar
void AddSPExperience(uint32_t SPExpOffset);
// Updates the HP and MP
void UpdateHPMP(int32_t Health, int32_t Mana, uint16_t DisplayEffectType);
// Updates the cape state from PVP
void UpdatePVPCapeType(uint8_t CapeType);
// Moves the player to the map location. Return success
bool MoveTo(uint16_t RegionId, float PosX, float PosY, float PosZ);
// Moves the player to the gameworld and map location. Return success
Expand Down

0 comments on commit 5f093db

Please sign in to comment.