SabrehavenServer/src/behaviourdatabase.h

298 lines
8.7 KiB
C++

/**
* Tibia GIMUD Server - a free and open-source MMORPG server emulator
* Copyright (C) 2019 Sabrehaven and Mark Samman <mark.samman@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef FS_BEHAVIOURDATABASE_H_4E785D4C545C455E1A0C2A9C84D5EFFF
#define FS_BEHAVIOURDATABASE_H_4E785D4C545C455E1A0C2A9C84D5EFFF
#include "script.h"
#include "enums.h"
enum BehaviourSituation_t
{
SITUATION_ADDRESS = 1,
SITUATION_BUSY,
SITUATION_VANISH,
SITUATION_NONE,
};
enum NpcBehaviourType_t
{
BEHAVIOUR_TYPE_NOP = 0, // returns true on conditions
BEHAVIOUR_TYPE_STRING, // match string, or NPC say
BEHAVIOUR_TYPE_NUMBER, // return a number
BEHAVIOUR_TYPE_OPERATION, // <, =, >, >=, <=, <>
BEHAVIOUR_TYPE_MESSAGE_COUNT, // get quantity in player message
BEHAVIOUR_TYPE_IDLE, // idle npc
BEHAVIOUR_TYPE_QUEUE, // queue talking creature
BEHAVIOUR_TYPE_TOPIC, // get/set topic
BEHAVIOUR_TYPE_PRICE, // get/set price
BEHAVIOUR_TYPE_DATA, // get/set data
BEHAVIOUR_TYPE_ITEM, // get/set item
BEHAVIOUR_TYPE_AMOUNT, // get/set amount
BEHAVIOUR_TYPE_TEXT, // get/set string
BEHAVIOUR_TYPE_HEALTH, // get/set health
BEHAVIOUR_TYPE_COUNT, // count amount of items
BEHAVIOUR_TYPE_CREATEMONEY, // create money
BEHAVIOUR_TYPE_COUNTMONEY, // get player total money
BEHAVIOUR_TYPE_DELETEMONEY, // remove money from player
BEHAVIOUR_TYPE_CREATE, // create item
BEHAVIOUR_TYPE_DELETE, // deletes an item
BEHAVIOUR_TYPE_EFFECTME, // effect on NPC
BEHAVIOUR_TYPE_EFFECTOPP, // effect on player
BEHAVIOUR_TYPE_BURNING, // get/set burning
BEHAVIOUR_TYPE_POISON, // get/set poison
BEHAVIOUR_TYPE_SPELLKNOWN, // check if spell is known
BEHAVIOUR_TYPE_SPELLLEVEL, // get spell level
BEHAVIOUR_TYPE_TEACHSPELL, // player learn spell
BEHAVIOUR_TYPE_LEVEL, // get player level
BEHAVIOUR_TYPE_RANDOM, // random value
BEHAVIOUR_TYPE_QUESTVALUE, // get/set quest value
BEHAVIOUR_TYPE_TELEPORT, // teleport player to position
BEHAVIOUR_TYPE_SORCERER, // get/set vocation
BEHAVIOUR_TYPE_DRUID, // get/set vocation
BEHAVIOUR_TYPE_KNIGHT, // get/set vocation
BEHAVIOUR_TYPE_PALADIN, // get/set vocation
BEHAVIOUR_TYPE_ISPREMIUM, // is account premium
BEHAVIOUR_TYPE_PVPENFORCED, // get world type pvpenforced
BEHAVIOUR_TYPE_MALE, // is player male
BEHAVIOUR_TYPE_FEMALE, // is player female
BEHAVIOUR_TYPE_PZLOCKED, // is player pz locked
BEHAVIOUR_TYPE_PROMOTED, // check if player promoted
BEHAVIOUR_TYPE_PROFESSION, // get/set profession
BEHAVIOUR_TYPE_PROMOTE, // promote the player
BEHAVIOUR_TYPE_SUMMON, // summons a monster
BEHAVIOUR_TYPE_EXPERIENCE, // grant experience to a player
BEHAVIOUR_TYPE_BALANCE, // return player balance
BEHAVIOUR_TYPE_WITHDRAW, // withdraw from player bank balance
BEHAVIOUR_TYPE_DEPOSIT, // deposit x amount of gold
BEHAVIOUR_TYPE_TRANSFER, // transfer x amount of gold
BEHAVIOUR_TYPE_BLESS, // add blessing to player
BEHAVIOUR_TYPE_CREATECONTAINER, // create a container of an item in particular
BEHAVIOUR_TYPE_TOWN, // change player town
BEHAVIOUR_TYPE_DRUNK, // get/set drunk (set not done)
BEHAVIOUR_TYPE_ADDOUTFITADDON, // Add Outfit Addon
BEHAVIOUR_TYPE_DELETEAMOUNT, // deletes an item according specified amount
BEHAVIOUR_TYPE_EXPIRINGQUESTVALUE, // get/set expiring quest value
};
enum NpcBehaviourOperator_t
{
BEHAVIOUR_OPERATOR_LESSER_THAN = '<',
BEHAVIOUR_OPERATOR_EQUALS = '=',
BEHAVIOUR_OPERATOR_GREATER_THAN = '>',
BEHAVIOUR_OPERATOR_GREATER_OR_EQUALS = 'G',
BEHAVIOUR_OPERATOR_LESSER_OR_EQUALS = 'L',
BEHAVIOUR_OPERATOR_NOT_EQUALS = 'N',
BEHAVIOUR_OPERATOR_MULTIPLY = '*',
BEHAVIOUR_OPERATOR_SUM = '+',
BEHAVIOUR_OPERATOR_RES = '-',
};
enum NpcBehaviourParameterSearch_t
{
BEHAVIOUR_PARAMETER_NONE,
BEHAVIOUR_PARAMETER_ASSIGN,
BEHAVIOUR_PARAMETER_ONE,
BEHAVIOUR_PARAMETER_TWO,
BEHAVIOUR_PARAMETER_THREE,
};
class Npc;
class Player;
struct NpcBehaviourNode
{
NpcBehaviourType_t type;
int32_t number;
std::string string;
NpcBehaviourNode* left;
NpcBehaviourNode* right;
NpcBehaviourNode() : type(), number(0), left(nullptr), right(nullptr) { }
~NpcBehaviourNode() {
delete left;
delete right;
}
NpcBehaviourNode* clone() {
NpcBehaviourNode* copy = new NpcBehaviourNode();
copy->type = type;
copy->number = number;
copy->string = string;
if (left) {
copy->left = left->clone();
}
if (right) {
copy->right = right->clone();
}
return copy;
}
};
struct NpcBehaviourCondition
{
NpcBehaviourType_t type;
BehaviourSituation_t situation;
std::string string;
int32_t number;
NpcBehaviourNode* expression;
NpcBehaviourCondition() : type(), situation(SITUATION_NONE), string(), number(0), expression(nullptr) {}
~NpcBehaviourCondition() {
delete expression;
}
//non-copyable
NpcBehaviourCondition(const NpcBehaviourCondition&) = delete;
NpcBehaviourCondition& operator=(const NpcBehaviourCondition&) = delete;
bool setCondition(NpcBehaviourType_t _type, int32_t _number, const std::string& _string);
};
struct NpcBehaviourAction
{
NpcBehaviourType_t type;
std::string string;
int32_t number;
NpcBehaviourNode* expression;
NpcBehaviourNode* expression2;
NpcBehaviourNode* expression3;
NpcBehaviourAction() :
type(),
string(),
number(0),
expression(nullptr),
expression2(nullptr),
expression3(nullptr) {}
~NpcBehaviourAction() {
delete expression;
delete expression2;
delete expression3;
}
NpcBehaviourAction* clone() {
NpcBehaviourAction* copy = new NpcBehaviourAction();
copy->type = type;
copy->string = string;
copy->number = number;
if (expression) {
copy->expression = expression->clone();
}
if (expression2) {
copy->expression2 = expression2->clone();
}
if (expression3) {
copy->expression3 = expression3->clone();
}
return copy;
}
};
struct NpcBehaviour
{
BehaviourSituation_t situation = SITUATION_NONE;
uint32_t priority = 0;
std::vector<NpcBehaviourCondition*> conditions;
std::vector<NpcBehaviourAction*> actions;
NpcBehaviour() = default;
~NpcBehaviour() {
for (auto condition : conditions) {
delete condition;
}
for (auto action : actions) {
delete action;
}
}
//non-copyable
NpcBehaviour(const NpcBehaviour&) = delete;
NpcBehaviour& operator=(const NpcBehaviour&) = delete;
};
struct NpcQueueEntry
{
uint32_t playerId;
std::string text;
};
class BehaviourDatabase
{
public:
BehaviourDatabase(Npc* _npc);
~BehaviourDatabase();
// non-copyable
BehaviourDatabase(const BehaviourDatabase&) = delete;
BehaviourDatabase& operator=(const BehaviourDatabase&) = delete;
bool loadDatabase(ScriptReader& script);
bool loadBehaviour(ScriptReader& script);
bool loadConditions(ScriptReader& script, NpcBehaviour* behaviour);
bool loadActions(ScriptReader& script, NpcBehaviour* behaviour);
NpcBehaviourNode* readValue(ScriptReader& script);
NpcBehaviourNode* readFactor(ScriptReader& script, NpcBehaviourNode* nextNode);
void react(BehaviourSituation_t situation, Player* player, const std::string& message);
static bool compareBehaviour(const NpcBehaviour* left, const NpcBehaviour* right) {
return left->priority >= right->priority;
}
private:
bool checkCondition(const NpcBehaviourCondition* condition, Player* player, const std::string& message);
void checkAction(const NpcBehaviourAction* action, Player* player, const std::string& message);
int32_t evaluate(NpcBehaviourNode* node, Player* player, const std::string& message = "");
int32_t checkOperation(Player* player, NpcBehaviourNode* node, const std::string& message);
int32_t searchDigit(const std::string& message);
bool searchWord(const std::string& pattern, const std::string& message);
std::string parseResponse(Player* player, const std::string& message);
void attendCustomer(uint32_t playerId);
void queueCustomer(uint32_t playerId, const std::string& message);
void idle();
void reset();
int32_t topic;
int32_t data;
int32_t type;
int32_t price;
int32_t amount;
int32_t delay;
std::string string;
Npc* npc = nullptr;
NpcBehaviour* previousBehaviour = nullptr;
NpcBehaviour* priorityBehaviour = nullptr;
std::list<NpcQueueEntry> queueList;
std::vector<uint32_t> delayedEvents;
std::list<NpcBehaviour*> behaviourEntries;
std::recursive_mutex mutex;
};
#endif