mirror of
https://github.com/ErikasKontenis/SabrehavenServer.git
synced 2025-10-14 06:34:55 +02:00
introduce bank account system
This commit is contained in:
@@ -19,6 +19,7 @@
|
||||
|
||||
#include "otpch.h"
|
||||
|
||||
#include "iologindata.h"
|
||||
#include "behaviourdatabase.h"
|
||||
#include "npc.h"
|
||||
#include "player.h"
|
||||
@@ -174,6 +175,9 @@ bool BehaviourDatabase::loadConditions(ScriptReader& script, NpcBehaviour* behav
|
||||
} else if (script.getSpecial() == '%') {
|
||||
condition->setCondition(BEHAVIOUR_TYPE_MESSAGE_COUNT, script.readNumber(), "");
|
||||
searchTerm = true;
|
||||
} else if (script.getSpecial() == '$') {
|
||||
condition->setCondition(BEHAVIOUR_TYPE_MESSAGE_COUNT_NO_LIMIT, script.readNumber(), "");
|
||||
searchTerm = true;
|
||||
} else if (script.getSpecial() == ',') {
|
||||
script.nextToken();
|
||||
continue;
|
||||
@@ -291,6 +295,9 @@ bool BehaviourDatabase::loadActions(ScriptReader& script, NpcBehaviour* behaviou
|
||||
} else if (identifier == "deposit") {
|
||||
action->type = BEHAVIOUR_TYPE_DEPOSIT;
|
||||
searchType = BEHAVIOUR_PARAMETER_ONE;
|
||||
} else if (identifier == "transfer") {
|
||||
action->type = BEHAVIOUR_TYPE_TRANSFER;
|
||||
searchType = BEHAVIOUR_PARAMETER_ONE;
|
||||
} else if (identifier == "bless") {
|
||||
action->type = BEHAVIOUR_TYPE_BLESS;
|
||||
searchType = BEHAVIOUR_PARAMETER_ONE;
|
||||
@@ -471,16 +478,24 @@ NpcBehaviourNode* BehaviourDatabase::readValue(ScriptReader& script)
|
||||
}
|
||||
|
||||
if (script.Token == SPECIAL) {
|
||||
if (script.getSpecial() != '%') {
|
||||
script.error("illegal character");
|
||||
return nullptr;
|
||||
if (script.getSpecial() == '%') {
|
||||
NpcBehaviourNode* node = new NpcBehaviourNode();
|
||||
node->type = BEHAVIOUR_TYPE_MESSAGE_COUNT;
|
||||
node->number = script.readNumber();
|
||||
script.nextToken();
|
||||
return node;
|
||||
}
|
||||
|
||||
NpcBehaviourNode* node = new NpcBehaviourNode();
|
||||
node->type = BEHAVIOUR_TYPE_MESSAGE_COUNT;
|
||||
node->number = script.readNumber();
|
||||
script.nextToken();
|
||||
return node;
|
||||
if (script.getSpecial() == '$') {
|
||||
NpcBehaviourNode* node = new NpcBehaviourNode();
|
||||
node->type = BEHAVIOUR_TYPE_MESSAGE_COUNT_NO_LIMIT;
|
||||
node->number = script.readNumber();
|
||||
script.nextToken();
|
||||
return node;
|
||||
}
|
||||
|
||||
script.error("illegal character");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
NpcBehaviourNode* node = nullptr;
|
||||
@@ -526,6 +541,9 @@ NpcBehaviourNode* BehaviourDatabase::readValue(ScriptReader& script)
|
||||
} else if (identifier == "balance") {
|
||||
node = new NpcBehaviourNode();
|
||||
node->type = BEHAVIOUR_TYPE_BALANCE;
|
||||
} else if (identifier == "transfertoplayernamestate") {
|
||||
node = new NpcBehaviourNode();
|
||||
node->type = BEHAVIOUR_TYPE_MESSAGE_TRANSFERTOPLAYERNAME_STATE;
|
||||
} else if (identifier == "spellknown") {
|
||||
node = new NpcBehaviourNode();
|
||||
node->type = BEHAVIOUR_TYPE_SPELLKNOWN;
|
||||
@@ -709,6 +727,13 @@ bool BehaviourDatabase::checkCondition(const NpcBehaviourCondition* condition, P
|
||||
}
|
||||
break;
|
||||
}
|
||||
case BEHAVIOUR_TYPE_MESSAGE_COUNT_NO_LIMIT: {
|
||||
int32_t value = searchDigitNoLimit(message);
|
||||
if (value < condition->number) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case BEHAVIOUR_TYPE_STRING:
|
||||
if (!searchWord(condition->string, message)) {
|
||||
return false;
|
||||
@@ -1011,6 +1036,32 @@ void BehaviourDatabase::checkAction(const NpcBehaviourAction* action, Player* pl
|
||||
player->setBankBalance(player->getBankBalance() + money);
|
||||
break;
|
||||
}
|
||||
case BEHAVIOUR_TYPE_TRANSFER: {
|
||||
int32_t money = evaluate(action->expression, player, message);
|
||||
uint16_t state = 0;
|
||||
Player* transferToPlayer = g_game.getPlayerByName(string);
|
||||
if (!transferToPlayer) {
|
||||
state = IOLoginData::canTransferMoneyToByName(string);
|
||||
}
|
||||
else {
|
||||
state = transferToPlayer->getVocationId() == 0 ? 1 : 2;
|
||||
}
|
||||
|
||||
if (state != 2) {
|
||||
break;
|
||||
}
|
||||
|
||||
player->setBankBalance(player->getBankBalance() - money);
|
||||
|
||||
if (!transferToPlayer) {
|
||||
IOLoginData::increaseBankBalance(string, money);
|
||||
}
|
||||
else {
|
||||
transferToPlayer->setBankBalance(transferToPlayer->getBankBalance() + money);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case BEHAVIOUR_TYPE_BLESS: {
|
||||
uint8_t number = static_cast<uint8_t>(evaluate(action->expression, player, message)) - 1;
|
||||
|
||||
@@ -1159,10 +1210,33 @@ int32_t BehaviourDatabase::evaluate(NpcBehaviourNode* node, Player* player, cons
|
||||
}
|
||||
return value;
|
||||
}
|
||||
case BEHAVIOUR_TYPE_MESSAGE_COUNT_NO_LIMIT: {
|
||||
int32_t value = searchDigitNoLimit(message);
|
||||
if (value < node->number) {
|
||||
return false;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
case BEHAVIOUR_TYPE_OPERATION:
|
||||
return checkOperation(player, node, message);
|
||||
case BEHAVIOUR_TYPE_BALANCE:
|
||||
return player->getBankBalance();
|
||||
case BEHAVIOUR_TYPE_MESSAGE_TRANSFERTOPLAYERNAME_STATE: {
|
||||
std::string lowerMessage = asLowerCaseString(message);
|
||||
if (lowerMessage.find("to ") != std::string::npos) {
|
||||
string = asCamelCaseString(message.substr(lowerMessage.find("to ") + 3, message.size()));
|
||||
}
|
||||
else {
|
||||
string = asCamelCaseString(message);
|
||||
}
|
||||
|
||||
Player* transferToPlayer = g_game.getPlayerByName(string);
|
||||
if (!transferToPlayer) {
|
||||
return IOLoginData::canTransferMoneyToByName(string);
|
||||
}
|
||||
|
||||
return transferToPlayer->getVocationId() == 0 ? 1 : 2;
|
||||
}
|
||||
case BEHAVIOUR_TYPE_SPELLKNOWN: {
|
||||
if (player->hasLearnedInstantSpell(string)) {
|
||||
return true;
|
||||
@@ -1217,6 +1291,17 @@ int32_t BehaviourDatabase::checkOperation(Player* player, NpcBehaviourNode* node
|
||||
}
|
||||
|
||||
int32_t BehaviourDatabase::searchDigit(const std::string& message)
|
||||
{
|
||||
int32_t value = searchDigitNoLimit(message);
|
||||
|
||||
if (value > 500) {
|
||||
value = 500;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
int32_t BehaviourDatabase::searchDigitNoLimit(const std::string& message)
|
||||
{
|
||||
int32_t start = -1;
|
||||
int32_t end = -1;
|
||||
@@ -1244,10 +1329,6 @@ int32_t BehaviourDatabase::searchDigit(const std::string& message)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (value > 500) {
|
||||
value = 500;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
@@ -1299,7 +1380,8 @@ std::string BehaviourDatabase::parseResponse(Player* player, const std::string&
|
||||
replaceString(response, "%D", std::to_string(data));
|
||||
replaceString(response, "%N", player->getName());
|
||||
replaceString(response, "%P", std::to_string(price));
|
||||
|
||||
replaceString(response, "%S", string);
|
||||
|
||||
int32_t worldTime = g_game.getLightHour();
|
||||
int32_t hours = std::floor<int32_t>(worldTime / 60);
|
||||
int32_t minutes = worldTime % 60;
|
||||
|
@@ -38,6 +38,8 @@ enum NpcBehaviourType_t
|
||||
BEHAVIOUR_TYPE_NUMBER, // return a number
|
||||
BEHAVIOUR_TYPE_OPERATION, // <, =, >, >=, <=, <>
|
||||
BEHAVIOUR_TYPE_MESSAGE_COUNT, // get quantity in player message
|
||||
BEHAVIOUR_TYPE_MESSAGE_COUNT_NO_LIMIT, // get quantity in player message without any max value restriction
|
||||
BEHAVIOUR_TYPE_MESSAGE_TRANSFERTOPLAYERNAME_STATE, // set player name parsed fro message to string object and return state if it is possible to transfer
|
||||
BEHAVIOUR_TYPE_IDLE, // idle npc
|
||||
BEHAVIOUR_TYPE_QUEUE, // queue talking creature
|
||||
BEHAVIOUR_TYPE_TOPIC, // get/set topic
|
||||
@@ -269,6 +271,7 @@ class BehaviourDatabase
|
||||
|
||||
int32_t checkOperation(Player* player, NpcBehaviourNode* node, const std::string& message);
|
||||
int32_t searchDigit(const std::string& message);
|
||||
int32_t searchDigitNoLimit(const std::string& message);
|
||||
bool searchWord(const std::string& pattern, const std::string& message);
|
||||
|
||||
std::string parseResponse(Player* player, const std::string& message);
|
||||
|
@@ -824,6 +824,20 @@ uint32_t IOLoginData::getGuidByName(const std::string& name)
|
||||
return result->getNumber<uint32_t>("id");
|
||||
}
|
||||
|
||||
// Return 0 means player not found, 1 player is without vocation, 2 player with vocation
|
||||
uint16_t IOLoginData::canTransferMoneyToByName(const std::string& name)
|
||||
{
|
||||
Database* db = Database::getInstance();
|
||||
|
||||
std::ostringstream query;
|
||||
query << "SELECT `vocation` FROM `players` WHERE `name` = " << db->escapeString(name);
|
||||
DBResult_ptr result = db->storeQuery(query.str());
|
||||
if (!result) {
|
||||
return 0;
|
||||
}
|
||||
return result->getNumber<uint16_t>("vocation") == 0 ? 1 : 2;
|
||||
}
|
||||
|
||||
bool IOLoginData::getGuidByNameEx(uint32_t& guid, bool& specialVip, std::string& name)
|
||||
{
|
||||
Database* db = Database::getInstance();
|
||||
@@ -899,6 +913,15 @@ void IOLoginData::increaseBankBalance(uint32_t guid, uint64_t bankBalance)
|
||||
Database::getInstance()->executeQuery(query.str());
|
||||
}
|
||||
|
||||
void IOLoginData::increaseBankBalance(std::string name, uint64_t bankBalance)
|
||||
{
|
||||
Database* db = Database::getInstance();
|
||||
|
||||
std::ostringstream query;
|
||||
query << "UPDATE `players` SET `balance` = `balance` + " << bankBalance << " WHERE `name` = " << db->escapeString(name);
|
||||
db->executeQuery(query.str());
|
||||
}
|
||||
|
||||
bool IOLoginData::hasBiddedOnHouse(uint32_t guid)
|
||||
{
|
||||
Database* db = Database::getInstance();
|
||||
|
@@ -44,11 +44,13 @@ class IOLoginData
|
||||
static bool loadPlayerByName(Player* player, const std::string& name);
|
||||
static bool loadPlayer(Player* player, DBResult_ptr result);
|
||||
static bool savePlayer(Player* player);
|
||||
static uint32_t getGuidByName(const std::string& name);
|
||||
static uint32_t getGuidByName(const std::string& name);
|
||||
static uint16_t canTransferMoneyToByName(const std::string& name);
|
||||
static bool getGuidByNameEx(uint32_t& guid, bool& specialVip, std::string& name);
|
||||
static std::string getNameByGuid(uint32_t guid);
|
||||
static bool formatPlayerName(std::string& name);
|
||||
static void increaseBankBalance(uint32_t guid, uint64_t bankBalance);
|
||||
static void increaseBankBalance(const std::string name, uint64_t bankBalance);
|
||||
static bool hasBiddedOnHouse(uint32_t guid);
|
||||
|
||||
static std::forward_list<VIPEntry> getVIPEntries(uint32_t accountId);
|
||||
|
@@ -360,6 +360,27 @@ std::string asUpperCaseString(std::string source)
|
||||
return source;
|
||||
}
|
||||
|
||||
std::string asCamelCaseString(std::string source) {
|
||||
bool active = true;
|
||||
|
||||
for (int i = 0; source[i] != '\0'; i++) {
|
||||
if (std::isalpha(source[i])) {
|
||||
if (active) {
|
||||
source[i] = std::toupper(source[i]);
|
||||
active = false;
|
||||
}
|
||||
else {
|
||||
source[i] = std::tolower(source[i]);
|
||||
}
|
||||
}
|
||||
else if (source[i] == ' ') {
|
||||
active = true;
|
||||
}
|
||||
}
|
||||
|
||||
return source;
|
||||
}
|
||||
|
||||
StringVec explodeString(const std::string& inString, const std::string& separator, int32_t limit/* = -1*/)
|
||||
{
|
||||
StringVec returnVector;
|
||||
|
@@ -41,6 +41,7 @@ void trim_left(std::string& source, char t);
|
||||
void toLowerCaseString(std::string& source);
|
||||
std::string asLowerCaseString(std::string source);
|
||||
std::string asUpperCaseString(std::string source);
|
||||
std::string asCamelCaseString(std::string source);
|
||||
|
||||
typedef std::vector<std::string> StringVec;
|
||||
typedef std::vector<int32_t> IntegerVec;
|
||||
|
Reference in New Issue
Block a user