mirror of
https://github.com/ErikasKontenis/SabrehavenServer.git
synced 2025-05-03 19:09:19 +02:00
introduce bank account system
This commit is contained in:
parent
00efade0a1
commit
ad7a761167
@ -82,3 +82,57 @@ Topic=99 -> "Well, can I help you with something else
|
||||
#Topic=99,"yes",Count(3035)>=Price -> "Here you are.", Create(3043), Amount=Price, Delete(3035)
|
||||
#Topic=99,"yes" -> "Sorry, you don't have so many platinum coins."
|
||||
#Topic=99 -> "Well, can I help you with something else?"
|
||||
|
||||
# Bank System
|
||||
"balance" -> Amount=Balance, "Your account balance is %A gold."
|
||||
"balance",balance>99999 -> Amount=Balance, "You certainly have made a pretty penny. Your account balance is %A gold."
|
||||
"balance",balance>999999 -> Amount=Balance, "You certainly have made a pretty penny. Your account balance is %A gold."
|
||||
"balance",balance>9999999 -> Amount=Balance, "You have made ten millions and it still grows! Your account balance is %A gold."
|
||||
"balance",balance>99999999 -> Amount=Balance, "I think you must be one of the richest inhabitants in the world! Your account balance is %A gold."
|
||||
|
||||
"deposit" -> "You don't have any gold with you."
|
||||
"deposit",CountMoney>0 -> "Please tell me how much gold it is you would like to deposit.", Topic=81
|
||||
"deposit","all",CountMoney>0 -> Price=CountMoney, "Would you really like to deposit %P gold?", Topic=82
|
||||
"deposit",$1,0<$1,CountMoney>=$1 -> Price=$1, "Would you really like to deposit %P gold?", Topic=82
|
||||
"deposit","0" -> "You are joking, aren't you??"
|
||||
"deposit",$1,0<$1,CountMoney<$1 -> "You do not have enough gold."
|
||||
Topic=81,$1,0<$1,CountMoney>=$1 -> Price=$1, "Would you really like to deposit %P gold?", Topic=82
|
||||
Topic=81,"0" -> "You are joking, aren't you?"
|
||||
Topic=81,$1,0<$1,CountMoney<$1 -> "You do not have enough gold."
|
||||
Topic=81 -> "Please tell me how much gold it is you would like to deposit.", Topic=81
|
||||
Topic=82,"yes",CountMoney>=Price -> "Alright, we have added the amount of %P gold to your balance. You can withdraw your money anytime you want to.", DeleteMoney, Deposit(Price)
|
||||
Topic=82,"yes" -> "I am inconsolable, but it seems you have lost your gold. I hope you get it back."
|
||||
Topic=82 -> "As you wish. Is there something else I can do for you?"
|
||||
|
||||
"withdraw" -> "Please tell me how much gold you would like to withdraw.", Topic=83
|
||||
"withdraw",$1,0<$1,Balance>=$1 -> Price=$1, "Are you sure you wish to withdraw %P gold from your bank account?", Topic=84
|
||||
"withdraw","0" -> "Sure, you want nothing you get nothing!"
|
||||
"withdraw",$1,0<$1,Balance<$1 -> "There is not enough gold on your account."
|
||||
Topic=83,$1,0<$1,Balance>=$1 -> Price=$1, "Are you sure you wish to withdraw %P gold from your bank account?", Topic=84
|
||||
Topic=83,"0" -> "Sure, you want nothing you get nothing!"
|
||||
Topic=83,$1,0<$1,Balance<$1 -> "There is not enough gold on your account."
|
||||
Topic=83 -> "Please tell me how much gold you would like to withdraw.", Topic=83
|
||||
Topic=84,"yes",Balance>=Price -> "Here you are, %P gold. Please let me know if there is something else I can do for you.", CreateMoney, Withdraw(Price)
|
||||
Topic=84,"yes" -> "I am inconsolable, but it seems you don't have that many gold in your bank account."
|
||||
Topic=84 -> "The customer is king! Come back anytime you want to if you wish to withdraw your money."
|
||||
|
||||
"transfer" -> "Please tell me the amount of gold you would like to transfer.", Topic=85
|
||||
"transfer","0","to" -> "Please think about it. Okay?"
|
||||
"transfer",$1,0<$1,"to",Balance<$1 -> "There is not enough gold on your account."
|
||||
"transfer",$1,0<$1,"to",Balance>=$1,TransferToPlayerNameState=2 -> Price=$1, "Would you really like to transfer %P gold to %S?", Topic=88
|
||||
"transfer",$1,0<$1,"to",Balance>=$1,TransferToPlayerNameState=1 -> "I'm afraid this character only holds a junior account at our bank. Do not worry, though. Once he has chosen his vocation or is no longer on Rookgaard, his account will be upgraded."
|
||||
"transfer",$1,0<$1,"to",Balance>=$1,TransferToPlayerNameState=0 -> "This player does not exist."
|
||||
Topic=85,$1,0<$1,Balance>=$1 -> Price=$1, "Who would you like transfer %P gold to?", Topic=86
|
||||
Topic=85,"0" -> "Please think about it. Okay?"
|
||||
Topic=85,$1,0<$1,Balance<$1 -> "There is not enough gold on your account."
|
||||
Topic=86,Balance>=Price,TransferToPlayerNameState=2 -> "Would you really like to transfer %P gold to %S?", Topic=87
|
||||
Topic=86,Balance>=Price,TransferToPlayerNameState=1 -> "I'm afraid this character only holds a junior account at our bank. Do not worry, though. Once he has chosen his vocation or is no longer on Rookgaard, his account will be upgraded."
|
||||
Topic=86,Balance>=Price,TransferToPlayerNameState=0 -> "This player does not exist."
|
||||
Topic=87,"yes",Balance>=Price -> "You have transferred %P gold to %S.", Transfer(Price)
|
||||
Topic=87,"yes" -> "I am inconsolable, but it seems you don't have that many gold in your bank account."
|
||||
Topic=87 -> "Ok. What is next?"
|
||||
Topic=88,"yes",Balance>=Price -> "Very well. You have transferred %P gold to %S.", Transfer(Price)
|
||||
Topic=88,"yes" -> "I am inconsolable, but it seems you don't have that many gold in your bank account."
|
||||
Topic=88 -> "Alright, is there something else I can do for you?"
|
||||
|
||||
|
||||
|
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user