What's new

Skrypty & Kody C++ Brak ceny domku i wy?wietlanie czaru

Status
Not open for further replies.

DiS

Advanced User
Joined
Apr 5, 2008
Messages
274
Reaction score
12
Siema, u?ywam silnik Avesta 0.6.5 (7.6) i nie pokazuje w nim ceny domk?w. Domki dzia?aj? normlanie/poprawnie. Brakuje tylko napisu ile ten domek kosztuje. Nie mam poj?cia jak? funkcje musz? tutaj umie?ci? :/ Podpowie kto??? Wiadomo, ma to by? cena ko?cowa domku czyli 1sqm * cena w config (np.5k) * wielko?? domku

Wy?wietla si?:
Nobody owns this house.

Ma by?:
Nobody owns this house. This house cost: COST


Tutaj m?j plik house.cpp:
//////////////////////////////////////////////////////////////////////
// OpenTibia - an opensource roleplaying game
//////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////
// 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
//////////////////////////////////////////////////////////////////////
#include "otpch.h"

#include <sstream>
#include <algorithm>

#include "house.h"
#include "ioplayer.h"
#include "game.h"
#include "town.h"
#include "configmanager.h"
#include "tools.h"
//[ added for beds system
#include "beds.h"
//]

extern ConfigManager g_config;
extern Game g_game;

House::House(uint32_t _houseid) :
transfer_container(ITEM_LOCKER1)
{
isLoaded = false;
houseName = "OTServ headquarter (Flat 1, Area 42)";
houseOwner = 0;
posEntry.x = 0;
posEntry.y = 0;
posEntry.z = 0;
paidUntil = 0;
houseid = _houseid;
rentWarnings = 0;
lastWarning = 0;
rent = 0;
townid = 0;
transferItem = NULL;
}

House::~House()
{
//
}

void House::addTile(HouseTile* tile)
{
tile->setFlag(TILESTATE_PROTECTIONZONE);
houseTiles.push_back(tile);
}

void House::setHouseOwner(uint32_t guid)
{
if(isLoaded && houseOwner == guid)
return;

isLoaded = true;

if(houseOwner){
//send items to depot
transferToDepot();

PlayerVector to_kick;
for(HouseTileList::iterator it = houseTiles.begin(); it != houseTiles.end(); ++it){
for(uint32_t i = 0; i < (*it)->getThingCount(); ++i){
Creature* creature = (*it)->__getThing(i)->getCreature();
if(creature != NULL && creature->getPlayer())
to_kick.push_back(creature->getPlayer());
}
}
while(to_kick.empty() == false) {
Player* c = to_kick.back();
to_kick.pop_back();
kickPlayer(NULL, c->getName());
}

// we need to remove players from beds
HouseBedItemList::iterator bit;
for(bit = bedsList.begin(); bit != bedsList.end(); ++bit) {
if((*bit)->getSleeper() != 0) {
(*bit)->wakeUp(NULL);
}
}

//clean access lists
houseOwner = 0;
setAccessList(SUBOWNER_LIST, "");
setAccessList(GUEST_LIST, "");

for(HouseDoorList::iterator it = doorList.begin(); it != doorList.end(); ++it){
(*it)->setAccessList("");
}

//reset paid date
paidUntil = 0;
rentWarnings = 0;
}

std::string name;
if(guid != 0 && IOPlayer::instance()->getNameByGuid(guid, name)){
houseOwner = guid;
houseOwnerName = name;
}

updateDoorDescription();
setLastWarning(std::time(NULL)); //So the new owner has one day before he start the payment
}

void House::updateDoorDescription()
{
std::stringstream houseDescription;
houseDescription << "It belongs to house '" << houseName << "'. " << std::endl;

if(houseOwner != 0){
houseDescription << houseOwnerName;
}
else{
houseDescription << "Nobody";
}
houseDescription << " owns this house." << std::endl;

HouseDoorList::iterator it;
for(it = doorList.begin(); it != doorList.end(); ++it){
(*it)->setSpecialDescription(houseDescription.str());
}
}

AccessHouseLevel_t House::getHouseAccessLevel(const Player* player)
{
if(player == NULL) // By script
return HOUSE_OWNER;

if(player->hasFlag(PlayerFlag_CanEditHouses))
return HOUSE_OWNER;

if(player->getGUID() == houseOwner)
return HOUSE_OWNER;

if(subOwnerList.isInList(player))
return HOUSE_SUBOWNER;

if(guestList.isInList(player))
return HOUSE_GUEST;

return HOUSE_NO_INVITED;
}

bool House::kickPlayer(Player* player, const std::string& name)
{
Player* kickingPlayer = g_game.getPlayerByName(name);
if(kickingPlayer){
HouseTile* houseTile = kickingPlayer->getTile()->getHouseTile();

if(houseTile && houseTile->getHouse() == this){
if(getHouseAccessLevel(player) >= getHouseAccessLevel(kickingPlayer) && !kickingPlayer->hasFlag(PlayerFlag_CanEditHouses)){
if(g_game.internalTeleport(kickingPlayer, getEntryPosition()) == RET_NOERROR){
g_game.addMagicEffect(getEntryPosition(), NM_ME_ENERGY_AREA);
}
return true;
}
}
}
return false;
}

void House::setAccessList(uint32_t listId, const std::string& textlist)
{
if(listId == GUEST_LIST){
guestList.parseList(textlist);
}
else if(listId == SUBOWNER_LIST){
subOwnerList.parseList(textlist);
}
else{
Door* door = getDoorByNumber(listId);
if(door){
door->setAccessList(textlist);
}
else{
#ifdef __DEBUG_HOUSES__
std::cout << "Failure: [House::setAccessList] door == NULL, listId = " << listId <<std::endl;
#endif
}
//We dont have kick anyone
return;
}

//kick uninvited players
typedef std::list<Player*> KickPlayerList;
KickPlayerList kickList;
HouseTileList::iterator it;
for(it = houseTiles.begin(); it != houseTiles.end(); ++it){
HouseTile* hTile = *it;
if(hTile->creatures.size() > 0){
CreatureVector::iterator cit;
for(cit = hTile->creatures.begin(); cit != hTile->creatures.end(); ++cit){
Player* player = (*cit)->getPlayer();
if(player && isInvited(player) == false){
kickList.push_back(player);
}
}
}
}

KickPlayerList::iterator itkick;
for(itkick = kickList.begin(); itkick != kickList.end(); ++itkick){
if(g_game.internalTeleport(*itkick, getEntryPosition()) == RET_NOERROR){
g_game.addMagicEffect(getEntryPosition(), NM_ME_ENERGY_AREA);
}
}
}

bool House::transferToDepot()
{
if(townid == 0) {
return false;
}

Player* player = NULL;
// Empty house is just cleared.
if(houseOwner != 0) {
std::string ownerName;
if(IOPlayer::instance()->getNameByGuid(houseOwner, ownerName)){
player = g_game.getPlayerByName(ownerName);

if(!player){
player = new Player(ownerName, NULL);

if(!IOPlayer::instance()->loadPlayer(player, ownerName)){

#ifdef __DEBUG__
std::cout << "Failure: [House::transferToDepot], can not load player: " << ownerName << std::endl;
#endif

delete player;
player = NULL;
}
}
}
}

Depot* depot = player? player->getDepot(townid, true) : NULL;

std::list<Item*> moveItemList;
Container* tmpContainer = NULL;
Item* item = NULL;

for(HouseTileList::iterator it = houseTiles.begin(); it != houseTiles.end(); ++it){
for(uint32_t i = 0; i < (*it)->getThingCount(); ++i){
item = (*it)->__getThing(i)->getItem();

if(!item)
continue;

if(item->isPickupable()){
moveItemList.push_back(item);
}
else if((tmpContainer = item->getContainer())){
for(ItemList::const_iterator it = tmpContainer->getItems(); it != tmpContainer->getEnd(); ++it){
moveItemList.push_back(*it);
}
}
}
}

for(std::list<Item*>::iterator it = moveItemList.begin(); it != moveItemList.end(); ++it){
if(depot) {
g_game.internalMoveItem((*it)->getParent(), depot, INDEX_WHEREEVER,
(*it), (*it)->getItemCount(), NULL, FLAG_NOLIMIT);
}
else {
g_game.internalRemoveItem(*it);
}
}

if(player && player->isOffline()){
IOPlayer::instance()->savePlayer(player);
delete player;
}

return true;
}

void House::cleanHouse()
{
transferToDepot();

PlayerVector to_kick;
for(HouseTileList::iterator it = houseTiles.begin(); it != houseTiles.end(); ++it) {
for(uint32_t i = 0; i < (*it)->getThingCount(); ++i) {
Creature* creature = (*it)->__getThing(i)->getCreature();
if(creature != NULL && creature->getPlayer()) {
to_kick.push_back(creature->getPlayer());
}
}
}
while(to_kick.empty() == false) {
Player* c = to_kick.back();
to_kick.pop_back();
kickPlayer(NULL, c->getName());
}

// we need to remove players from beds
HouseBedItemList::iterator bit;
for(bit = bedsList.begin(); bit != bedsList.end(); ++bit) {
if((*bit)->getSleeper() != 0) {
(*bit)->wakeUp(NULL);
}
}
}

bool House::getAccessList(uint32_t listId, std::string& list) const
{
if(listId == GUEST_LIST){
guestList.getList(list);
return true;
}
else if(listId == SUBOWNER_LIST){
subOwnerList.getList(list);
return true;
}
else{
Door* door = getDoorByNumber(listId);
if(door){
return door->getAccessList(list);
}
else{
#ifdef __DEBUG_HOUSES__
std::cout << "Failure: [House::getAccessList] door == NULL, listId = " << listId <<std::endl;
#endif
return false;
}
}
return false;
}

bool House::isInvited(const Player* player)
{
if(getHouseAccessLevel(player) != HOUSE_NO_INVITED){
return true;
}
else{
return false;
}
}

void House::addDoor(Door* door)
{
door->useThing2();
doorList.push_back(door);
door->setHouse(this);
updateDoorDescription();
}

void House::removeDoor(Door* door)
{
HouseDoorList::iterator it = std::find(doorList.begin(), doorList.end(), door);
if(it != doorList.end()){
(*it)->releaseThing2();
doorList.erase(it);
}
}


//[ added for beds system
void House::addBed(BedItem* bed)
{
bedsList.push_back(bed);
bed->setHouse(this);
}
//]

Door* House::getDoorByNumber(uint32_t doorId)
{
HouseDoorList::iterator it;
for(it = doorList.begin(); it != doorList.end(); ++it){
if((*it)->getDoorId() == doorId){
return *it;
}
}
return NULL;
}

Door* House::getDoorByNumber(uint32_t doorId) const
{
HouseDoorList::const_iterator it;
for(it = doorList.begin(); it != doorList.end(); ++it){
if((*it)->getDoorId() == doorId){
return *it;
}
}
return NULL;
}

Door* House::getDoorByPosition(const Position& pos)
{
for(HouseDoorList::iterator it = doorList.begin(); it != doorList.end(); ++it){
if((*it)->getPosition() == pos){
return *it;
}
}

return NULL;
}

bool House::canEditAccessList(uint32_t listId, const Player* player)
{
switch(getHouseAccessLevel(player)){
case HOUSE_OWNER:
return true;
break;
case HOUSE_SUBOWNER:
/*subowners can edit guest access list*/
if(listId == GUEST_LIST){
return true;
}
else /*subowner/door list*/{
return false;
}
break;
default:
return false;
}
}

HouseTransferItem* House::getTransferItem()
{
if(transferItem != NULL)
return NULL;

transfer_container.setParent(NULL);
transferItem = HouseTransferItem::createHouseTransferItem(this);
transfer_container.__addThing(transferItem);
return transferItem;
}

void House::resetTransferItem()
{
if(transferItem){
Item* tmpItem = transferItem;
transferItem = NULL;
transfer_container.setParent(NULL);

transfer_container.__removeThing(tmpItem, tmpItem->getItemCount());
g_game.FreeThing(tmpItem);
}
}

HouseTransferItem* HouseTransferItem::createHouseTransferItem(House* house)
{
HouseTransferItem* transferItem = new HouseTransferItem(house);
transferItem->useThing2();
transferItem->setID(ITEM_DOCUMENT_RO);
transferItem->setSubType(1);
std::stringstream stream;
stream << " It is a house transfer document for '" << house->getName() << "'.";
transferItem->setSpecialDescription(stream.str());
return transferItem;
}

bool HouseTransferItem::eek:nTradeEvent(TradeEvents_t event, Player* owner)
{
House* house;
switch(event){
case ON_TRADE_TRANSFER:
{
house = getHouse();
if(house){
house->executeTransfer(this, owner);
}

g_game.internalRemoveItem(this, 1);
break;
}

case ON_TRADE_CANCEL:
{
house = getHouse();
if(house){
house->resetTransferItem();
}

break;
}

default:
break;
}

return true;
}

bool House::executeTransfer(HouseTransferItem* item, Player* newOwner)
{
if(transferItem != item){
return false;
}

setHouseOwner(newOwner->getGUID());
transferItem = NULL;
return true;
}

AccessList::AccessList()
{
//
}

AccessList::~AccessList()
{
//
}

bool AccessList::parseList(const std::string& _list)
{
playerList.clear();
guildList.clear();
expressionList.clear();
regExList.clear();
list = _list;

if(_list == "")
return true;

std::stringstream listStream(_list);
std::string line;
while(getline(listStream, line)){
//trim left
trim_left(line, " ");
trim_left(line, "\t");

//trim right
trim_right(line, " ");
trim_right(line, "\t");

std::transform(line.begin(), line.end(), line.begin(), tolower);

if(line.substr(0,1) == "#")
continue;

if(line.length() > 100)
continue;

if(line.find("@") != std::string::npos){
std::string::size_type pos = line.find("@");
addGuild(line.substr(pos + 1), "");
}
else if(line.find("!") != std::string::npos || line.find("*") != std::string::npos || line.find("?") != std::string::npos){
addExpression(line);
}
else{
addPlayer(line);
}
}
return true;
}

bool AccessList::addPlayer(std::string& name)
{
uint32_t guid;
std::string dbName = name;
if(IOPlayer::instance()->getGuidByName(guid, dbName)){
if(playerList.find(guid) == playerList.end()){
playerList.insert(guid);
return true;
}
}
return false;
}

bool AccessList::addGuild(const std::string& guildName, const std::string& rank)
{
uint32_t guildId;
if(IOPlayer::instance()->getGuildIdByName(guildId, guildName)){
if(guildId != 0){
for(GuildList::iterator it = guildList.begin(); it != guildList.end(); ++it){
if(it->first == guildId && boost::algorithm::iequals(rank, it->second)){
return false;
}
}

guildList.push_back(std::pair<uint32_t, std::string>(guildId, rank));
return true;
}
}
return false;
}

bool AccessList::addExpression(const std::string& expression)
{
ExpressionList::iterator it;
for(it = expressionList.begin(); it != expressionList.end(); ++it){
if((*it) == expression){
return false;
}
}

std::string outExp;
std::string metachars = ".[{}()\\+|^$";

for(std::string::const_iterator it = expression.begin(); it != expression.end(); ++it){
if(metachars.find(*it) != std::string::npos){
outExp += "\\";
}

outExp += (*it);
}

replaceString(outExp, "*", ".*");
replaceString(outExp, "?", ".?");

try{
if(outExp.length() > 0){
expressionList.push_back(outExp);

if(outExp.substr(0,1) == "!"){
if(outExp.length() > 1){
//push 'NOT' expressions upfront so they are checked first
regExList.push_front(std::make_pair(boost::regex(outExp.substr(1)), false));
}
}
else{
regExList.push_back(std::make_pair(boost::regex(outExp), true));
}
}
}
catch(...){
//
}

return true;
}

bool AccessList::isInList(const Player* player)
{
RegExList::iterator it;
std::string name = player->getName();
boost::cmatch what;

std::transform(name.begin(), name.end(), name.begin(), tolower);
for(it = regExList.begin(); it != regExList.end(); ++it){
if(boost::regex_match(name.c_str(), what, it->first)){
if(it->second){
return true;
}
else{
return false;
}
}
}

PlayerList::iterator playerIt = playerList.find(player->getGUID());
if(playerIt != playerList.end())
return true;

for(GuildList::iterator it = guildList.begin(); it != guildList.end(); ++it){
if((player->getGuildId() && it->first == player->getGuildId()) && boost::algorithm::iequals(player->getGuildRank(), it->second)){
return true;
}
}

return false;
}

void AccessList::getList(std::string& _list) const
{
_list = list;
}

Door::Door(uint16_t _type):
Item(_type)
{
house = NULL;
accessList = NULL;
}

Door::~Door()
{
if(accessList)
delete accessList;
}

Attr_ReadValue Door::readAttr(AttrTypes_t attr, PropStream& propStream)
{
if(ATTR_HOUSEDOORID == attr){
unsigned char _doorId = 0;
if(!propStream.GET_UINT8(_doorId)){
return ATTR_READ_ERROR;
}

setDoorId(_doorId);
return ATTR_READ_CONTINUE;
}
else
return Item::readAttr(attr, propStream);
}

bool Door::serializeAttr(PropWriteStream& propWriteStream) const
{
//dont call Item::serializeAttr(propWriteStream);

/*
if(house){
unsigned char _doorId = getDoorId();
propWriteStream.ADD_UINT8(ATTR_HOUSEDOORID);
propWriteStream.ADD_UINT8(_doorId);
}
*/

return true;
}

void Door::setHouse(House* _house)
{
if(house != NULL){
#ifdef __DEBUG_HOUSES__
std::cout << "Warning: [Door::setHouse] house != NULL" << std::endl;
#endif
return;
}
house = _house;

if(!accessList){
accessList = new AccessList();
}
}

bool Door::canUse(const Player* player)
{
if(!house){
return true;
}
if(house->getHouseAccessLevel(player) >= HOUSE_SUBOWNER)
return true;

return accessList->isInList(player);
}

void Door::setAccessList(const std::string& textlist)
{
if(!accessList){
accessList = new AccessList();
}

accessList->parseList(textlist);
}

bool Door::getAccessList(std::string& list) const
{
if(!house){
#ifdef __DEBUG_HOUSES__
std::cout << "Failure: [Door::getAccessList] house == NULL" << std::endl;
#endif
return false;
}

accessList->getList(list);
return true;
}

void Door::copyAttributes(Item* item)
{
Item::copyAttributes(item);

if(Door* door = item->getDoor()){
std::string list;
if(door->getAccessList(list)){
setAccessList(list);
}
}
}

void Door::eek:nRemoved()
{
if(house){
house->removeDoor(this);
}
}

Houses::Houses()
{
std::string strRentPeriod = g_config.getString(ConfigManager::HOUSE_RENT_PERIOD);

rentPeriod = RENTPERIOD_MONTHLY;

if(asLowerCaseString(strRentPeriod) == "yearly"){
rentPeriod = RENTPERIOD_YEARLY;
}
else if(asLowerCaseString(strRentPeriod) == "weekly"){
rentPeriod = RENTPERIOD_WEEKLY;
}
else if(asLowerCaseString(strRentPeriod) == "daily"){
rentPeriod = RENTPERIOD_DAILY;
}
else if(asLowerCaseString(strRentPeriod) == "never"){
rentPeriod = RENTPERIOD_NEVER;
}
}

Houses::~Houses()
{
//
}

House* Houses::getHouseByPlayerId(uint32_t playerId)
{
for(HouseMap::iterator it = houseMap.begin(); it != houseMap.end(); ++it){
House* house = it->second;
if(house->getHouseOwner() == playerId){
return house;
}
}
return NULL;
}

bool Houses::loadHousesXML(std::string filename)
{
xmlDocPtr doc = xmlParseFile(filename.c_str());
if(doc){
xmlNodePtr root, houseNode;
root = xmlDocGetRootElement(doc);

if(xmlStrcmp(root->name,(const xmlChar*)"houses") != 0){
xmlFreeDoc(doc);
return false;
}

int intValue;
std::string strValue;

houseNode = root->children;
while(houseNode){
if(xmlStrcmp(houseNode->name,(const xmlChar*)"house") == 0){
int _houseid = 0;
Position entryPos(0, 0, 0);

if(!readXMLInteger(houseNode, "houseid", _houseid)){
xmlFreeDoc(doc);
return false;
}

House* house = Houses::getInstance().getHouse(_houseid);
if(!house){
std::cout << "Error: [Houses::loadHousesXML] Unknown house, id = " << _houseid << std::endl;
xmlFreeDoc(doc);
return false;
}

if(readXMLString(houseNode, "name", strValue)){
house->setName(strValue);
}

if(readXMLInteger(houseNode, "entryx", intValue)){
entryPos.x = intValue;
}

if(readXMLInteger(houseNode, "entryy", intValue)){
entryPos.y = intValue;
}

if(readXMLInteger(houseNode, "entryz", intValue)){
entryPos.z = intValue;
}

if(entryPos.x == 0 && entryPos.y == 0 && entryPos.z == 0){
std::cout << "Warning: [Houses::loadHousesXML] House entry not set"
<< " - Name: " << house->getName()
<< " - House id: " << _houseid << std::endl;
}

house->setEntryPos(entryPos);

if(readXMLInteger(houseNode, "rent", intValue)){
house->setRent(intValue);
}

if(readXMLInteger(houseNode, "townid", intValue)){
house->setTownId(intValue);
}

house->setHouseOwner(0);
}

houseNode = houseNode->next;
}

xmlFreeDoc(doc);
return true;
}

return false;
}

bool Houses::payHouses()
{
if(rentPeriod == RENTPERIOD_NEVER) {
return true;
}
uint32_t currentTime = std::time(NULL);

for(HouseMap::iterator it = houseMap.begin(); it != houseMap.end(); ++it){
House* house = it->second;

if(house->getHouseOwner() != 0 && house->getPaidUntil() < currentTime &&
house->getRent() != 0){
uint32_t ownerid = house->getHouseOwner();
Town* town = Towns::getInstance().getTown(house->getTownId());
if(!town){
#ifdef __DEBUG_HOUSES__
std::cout << "Warning: [Houses::payHouses] town = NULL, townid = " <<
house->getTownId() << ", houseid = " << house->getHouseId() << std::endl;
#endif
continue;
}

std::string name;
if(!IOPlayer::instance()->getNameByGuid(ownerid, name)){
//player doesnt exist, remove it as house owner?
//house->setHouseOwner(0);
continue;
}

Player* player = g_game.getPlayerByName(name);

if(!player){
player = new Player(name, NULL);

if(!IOPlayer::instance()->loadPlayer(player, name)){
#ifdef __DEBUG__
std::cout << "Failure: [Houses::payHouses], can not load player: " << name << std::endl;
#endif
delete player;
continue;
}
}

Depot* depot = player->getDepot(town->getTownID(), true);

// savePlayerHere is an ugly hack
// to avoid saving 2 times a not online player
// when items are transferred to his depot
bool savePlayerHere = true;
if(depot){
//get money from depot
bool useAccBalance = g_config.getBoolean(ConfigManager::USE_ACCBALANCE) != false;
bool hasEnoughMoney = false;

if(useAccBalance){
if(player->balance >= house->getRent()){
player->balance -= house->getRent();
hasEnoughMoney = true;
}
}
else{
hasEnoughMoney = g_game.removeMoney(depot, house->getRent(), FLAG_NOLIMIT);
}

if(hasEnoughMoney){
uint32_t paidUntil = currentTime;
switch(rentPeriod){
case RENTPERIOD_DAILY:
paidUntil += 24 * 60 * 60;
break;
case RENTPERIOD_WEEKLY:
paidUntil += 24 * 60 * 60 * 7;
break;
case RENTPERIOD_MONTHLY:
paidUntil += 24 * 60 * 60 * 30;
break;
case RENTPERIOD_YEARLY:
paidUntil += 24 * 60 * 60 * 365;
case RENTPERIOD_NEVER:
break;
}

house->setPaidUntil(paidUntil);
}
else if(currentTime >= house->getLastWarning() + 24 * 60 * 60){
if(house->getPayRentWarnings() >= 7){
house->setHouseOwner(0);
// setHouseOwner will load the player,
// transfer house items to his depot and then
// will save it, so here should not be saved
// again
savePlayerHere = false;
}
else{
int daysLeft = 7 - house->getPayRentWarnings();

Item* letter = Item::CreateItem(ITEM_LETTER_STAMPED);
std::string period = "";

switch(rentPeriod){
case RENTPERIOD_DAILY:
period = "daily";
break;

case RENTPERIOD_WEEKLY:
period = "weekly";
break;

case RENTPERIOD_MONTHLY:
period = "monthly";
break;

case RENTPERIOD_YEARLY:
period = "annual";
break;

case RENTPERIOD_NEVER:
//
break;
}

std::stringstream warningText;
warningText << "Warning! \n" <<
"The " << period << " rent of " << house->getRent() << " gold for your house \""
<< house->getName() << "\" is payable. Have it available within " << daysLeft <<
" days, or you will lose this house.";

letter->setText(warningText.str());
g_game.internalAddItem(depot, letter, INDEX_WHEREEVER, FLAG_NOLIMIT);

house->setPayRentWarnings(house->getPayRentWarnings() + 1);
house->setLastWarning(currentTime);
}
}
}

if(player->isOffline()){
if(savePlayerHere){
IOPlayer::instance()->savePlayer(player);
}
delete player;
}
}
}

return true;
}


A tutaj fragment:
std::stringstream houseDescription;
houseDescription << "It belongs to house '" << houseName << "'. " << std::endl;

if(houseOwner != 0){
houseDescription << houseOwnerName;
}
else{
houseDescription << "Nobody";
}
houseDescription << " owns this house." << std::endl;

HouseDoorList::iterator it;
for(it = doorList.begin(); it != doorList.end(); ++it){
(*it)->setSpecialDescription(houseDescription.str());
}
}


W TFS 0.3 (te? 7.6) by?o to tak zrobione

void House::updateDoorDescription()
{
char houseDescription[200];
if(houseOwner != 0)
sprintf(houseDescription, "It belongs to house '%s'. %s owns this house.", houseName.c_str(), houseOwnerName.c_str());
else
sprintf(houseDescription, "It belongs to house '%s'. Nobody owns this house. It costs %d gold coins.", houseName.c_str(), price);

HouseDoorList::iterator it;
for(it = doorList.begin(); it != doorList.end(); ++it)
(*it)->setSpecialDescription(houseDescription);
}

:/



-----------------------------------------------------------------

Drug? rzecz? kt?r? chce wykona? w tym silniku jest to zmiana wy?wietlania czar?w: aktualnie w tym silniku czar wy?wietla si? jak w starych YurOTS, na ???to, tak jak z kim? rozmawiasz. Ja chce ?eby by? to ma?y pomara?czowy napis = efekt 16 (za du?o spamu na serwerze).
To samo by?o przy fluidach, tylko tam wystarczy?o zmieni? efekt w actions.
Jak zmieni? typ wy?wietlanego napisu przy czarach?


tutaj moj plik SPELLS.CPP
//////////////////////////////////////////////////////////////////////
// OpenTibia - an opensource roleplaying game
//////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////
// 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
//////////////////////////////////////////////////////////////////////
#include "otpch.h"

#include "tools.h"
#include "house.h"
#include "housetile.h"
#include "spells.h"
#include "combat.h"
#include "commands.h"
#include "monsters.h"
#include "configmanager.h"
#include "const.h"

#include <sstream>

#include <libxml/xmlmemory.h>
#include <libxml/parser.h>
#include <boost/algorithm/string/predicate.hpp>

extern Game g_game;
extern Spells* g_spells;
extern Monsters g_monsters;
extern Vocations g_vocations;
extern ConfigManager g_config;

Spells::Spells():
m_scriptInterface("Spell Interface")
{
m_scriptInterface.initState();
}

Spells::~Spells()
{
clear();
}

TalkActionResult_t Spells::playerSaySpell(Player* player, SpeakClasses type, const std::string& words)
{
std::string str_words = words;

//strip trailing spaces
trim_left(str_words, " ");
trim_right(str_words, " ");

InstantSpell* instantSpell = getInstantSpell(str_words);
if(!instantSpell){
return TALKACTION_CONTINUE;
}

std::string param = "";

if(instantSpell->getHasParam()){
size_t spellLen = instantSpell->getWords().length();
size_t paramLen = str_words.length() - spellLen;
std::string paramText = str_words.substr(spellLen, paramLen);

if(!paramText.empty() && paramText[0] == ' '){
size_t loc1 = paramText.find('"', 0);
size_t loc2 = std::string::npos;

// if found first apostrophe
if(loc1 != std::string::npos){
// search for ending apostrophe
loc2 = paramText.find('"', loc1 + 1);
}

// if ending apostrophe not found
if(loc2 == std::string::npos){
// rest of the text is param
loc2 = paramText.length();
}

param = paramText.substr(loc1 + 1, loc2 - loc1 - 1);

trim_left(param, " ");
trim_right(param, " ");
}
}

if(instantSpell->playerCastInstant(player, param)){
return TALKACTION_BREAK;
}
else{
return TALKACTION_FAILED;
}
}

void Spells::clear()
{
RunesMap::iterator it;
for(it = runes.begin(); it != runes.end(); ++it){
delete it->second;
}
runes.clear();

InstantsMap::iterator it2;
for(it2 = instants.begin(); it2 != instants.end(); ++it2){
delete it2->second;
}
instants.clear();
}

LuaScriptInterface& Spells::getScriptInterface()
{
return m_scriptInterface;
}

std::string Spells::getScriptBaseName()
{
return "spells";
}

Event* Spells::getEvent(const std::string& nodeName)
{
if(asLowerCaseString(nodeName) == "rune"){
return new RuneSpell(&m_scriptInterface);
}
else if(asLowerCaseString(nodeName) == "instant"){
return new InstantSpell(&m_scriptInterface);
}
else if(asLowerCaseString(nodeName) == "conjure"){
return new ConjureSpell(&m_scriptInterface);
}
else{
return NULL;
}
}

bool Spells::registerEvent(Event* event, xmlNodePtr p)
{
InstantSpell* instant = dynamic_cast<InstantSpell*>(event);
RuneSpell* rune = dynamic_cast<RuneSpell*>(event);
if(!instant && !rune)
return false;

if(instant){
instants[instant->getWords()] = instant;
}
else if(rune){
runes[rune->getRuneItemId()] = rune;
}
else{
return false;
}

return true;
}

Spell* Spells::getSpellByName(const std::string& name)
{
Spell* spell;

if((spell = getRuneSpellByName(name))){
return spell;
}

if((spell = getInstantSpellByName(name))){
return spell;
}

return NULL;
}

RuneSpell* Spells::getRuneSpell(uint32_t id)
{
RunesMap::iterator it = runes.find(id);
if(it != runes.end()){
return it->second;
}

return NULL;
}

RuneSpell* Spells::getRuneSpellByName(const std::string& name)
{
for(RunesMap::iterator it = runes.begin(); it != runes.end(); ++it){
if(boost::algorithm::iequals(it->second->getName(), name)){
return it->second;
}
}

return NULL;
}

InstantSpell* Spells::getInstantSpell(const std::string words)
{
InstantSpell* result = NULL;
for(InstantsMap::iterator it = instants.begin(); it != instants.end(); ++it){
InstantSpell* instantSpell = it->second;
size_t spellLen = instantSpell->getWords().length();

if(asLowerCaseString(words).compare(0, spellLen, asLowerCaseString(instantSpell->getWords())) == 0){
if(!result || spellLen > result->getWords().length()){
result = instantSpell;
}
}
}

if(result){
if(words.length() > result->getWords().length()){
size_t spellLen = result->getWords().length();
size_t paramLen = words.length() - spellLen;
std::string paramText = words.substr(spellLen, paramLen);

if(paramText.substr(0, 1) != " " || (paramText.length() >= 2 && paramText.substr(0, 2) != " \"")){
return NULL;
}
}

return result;
}

return NULL;
}

uint32_t Spells::getInstantSpellCount(const Player* player)
{
uint32_t count = 0;
for(InstantsMap::iterator it = instants.begin(); it != instants.end(); ++it){
InstantSpell* instantSpell = it->second;

if(instantSpell->canCast(player)){
++count;
}
}

return count;
}

InstantSpell* Spells::getInstantSpellByIndex(const Player* player, uint32_t index)
{
uint32_t count = 0;
for(InstantsMap::iterator it = instants.begin(); it != instants.end(); ++it){
InstantSpell* instantSpell = it->second;

if(instantSpell->canCast(player)){
if(count == index){
return instantSpell;
}

++count;
}
}

return NULL;
}

InstantSpell* Spells::getInstantSpellByName(const std::string& name)
{
for(InstantsMap::iterator it = instants.begin(); it != instants.end(); ++it){
if(asLowerCaseString(it->second->getName()) == name){
return it->second;
}
}

return NULL;
}

Position Spells::getCasterPosition(Creature* creature, Direction dir)
{
Position pos = creature->getPosition();

switch(dir){
case NORTH:
pos.y -= 1;
break;

case SOUTH:
pos.y += 1;
break;

case EAST:
pos.x += 1;
break;

case WEST:
pos.x -= 1;
break;

case SOUTHWEST:
pos.x -= 1;
pos.y += 1;
break;

case NORTHWEST:
pos.x -= 1;
pos.y -= 1;
break;

case NORTHEAST:
pos.x += 1;
pos.y -= 1;
break;

case SOUTHEAST:
pos.x += 1;
pos.y += 1;
break;

default:
break;
}

return pos;
}


CombatSpell::CombatSpell(Combat* _combat, bool _needTarget, bool _needDirection) :
Event(&g_spells->getScriptInterface())
{
combat =_combat;
needTarget = _needTarget;
needDirection = _needDirection;
}

CombatSpell::~CombatSpell()
{
if(combat){
delete combat;
}
}

bool CombatSpell::loadScriptCombat()
{
if(m_scriptInterface->reserveScriptEnv()){
ScriptEnviroment* env = m_scriptInterface->getScriptEnv();
combat = env->getCombatObject(env->getLastCombatId());

env->resetCallback();
m_scriptInterface->releaseScriptEnv();
}

return (combat != NULL);
}

bool CombatSpell::castSpell(Creature* creature)
{
if(m_scripted){
LuaVariant var;
var.type = VARIANT_POSITION;

if(needDirection){
var.pos = Spells::getCasterPosition(creature, creature->getDirection());
}
else{
var.pos = creature->getPosition();
}

return executeCastSpell(creature, var);
}

Position pos;

if(needDirection){
pos = Spells::getCasterPosition(creature, creature->getDirection());
}
else{
pos = creature->getPosition();
}

combat->doCombat(creature, pos);
return true;
}

bool CombatSpell::castSpell(Creature* creature, Creature* target)
{
if(m_scripted){
LuaVariant var;

if(combat->hasArea()){
var.type = VARIANT_POSITION;

if(needTarget){
var.pos = target->getPosition();
}
else if(needDirection){
var.pos = Spells::getCasterPosition(creature, creature->getDirection());
}
else{
var.pos = creature->getPosition();
}
}
else{
var.type = VARIANT_NUMBER;
var.number = target->getID();
}

return executeCastSpell(creature, var);
}

if(combat->hasArea()){
if(needTarget){
combat->doCombat(creature, target->getPosition());
}
else{
return castSpell(creature);
}
}
else{
combat->doCombat(creature, target);
}

return true;
}

bool CombatSpell::executeCastSpell(Creature* creature, const LuaVariant& var)
{
//onCastSpell(cid, var)
if(m_scriptInterface->reserveScriptEnv()){
ScriptEnviroment* env = m_scriptInterface->getScriptEnv();

#ifdef __DEBUG_LUASCRIPTS__
std::stringstream desc;
desc << "onCastSpell - " << creature->getName();
env->setEventDesc(desc.str());
#endif

env->setScriptId(m_scriptId, m_scriptInterface);
env->setRealPos(creature->getPosition());

lua_State* L = m_scriptInterface->getLuaState();

uint32_t cid = env->addThing(creature);

m_scriptInterface->pushFunction(m_scriptId);
lua_pushnumber(L, cid);
m_scriptInterface->pushVariant(L, var);

int32_t result = m_scriptInterface->callFunction(2);
m_scriptInterface->releaseScriptEnv();

return (result != LUA_ERROR);
}
else{
std::cout << "[Error] Call stack overflow. CombatSpell::executeCastSpell" << std::endl;
return false;
}
}

Spell::Spell()
{
level = 0;
magLevel = -1;
mana = 0;
manaPercent = 0;
lvPercent = 0;
#ifdef __PROTOCOL_76__
soul = 0;
#endif // __PROTOCOL_76__
range = -1;
customExhaust = 0;
exhaustion = true;
needTarget = false;
needWeapon = false;
selfTarget = false;
blockingSolid = false;
blockingCreature = false;
premium = false;
enabled = true;
isAggressive = true;
learnable = false;
}

bool Spell::configureSpell(xmlNodePtr p)
{
int intValue;
std::string strValue;
if(readXMLString(p, "name", strValue)){
name = strValue;

const char* reservedList[] =
{
"melee",
"physical",
"poison",
"fire",
"energy",
"drown",
"lifedrain",
"manadrain",
"healing",
"speed",
"outfit",
"invisible",
"drunk",
"firefield",
"poisonfield",
"energyfield",
"firecondition",
"poisoncondition",
"energycondition"
};

for(unsigned int i = 0; i < sizeof(reservedList)/sizeof(const char*); ++i){
if(boost::algorithm::iequals(reservedList, name.c_str())){
std::cout << "Error: [Spell::configureSpell] Spell is using a reserved name: " << reservedList << std::endl;
return false;
}
}
}
else{
std::cout << "Error: [Spell::configureSpell] Spell without name." << std::endl;
return false;
}

if(readXMLInteger(p, "lvl", intValue)){
level = intValue;
}

if(readXMLInteger(p, "maglv", intValue)){
magLevel = intValue;
}

if(readXMLInteger(p, "mana", intValue)){
mana = intValue;
}

if(readXMLInteger(p, "manapercent", intValue)){
manaPercent = intValue;
}

if(readXMLInteger(p, "lvpercent", intValue)){
lvPercent = intValue;
}

#ifdef __PROTOCOL_76__
if(readXMLInteger(p, "soul", intValue)){
soul = intValue;
}
#endif // __PROTOCOL_76__

if(readXMLInteger(p, "customexhaust", intValue)){
customExhaust = intValue;
}

if(readXMLInteger(p, "exhaustion", intValue)){
exhaustion = (intValue == 1);
}

if(readXMLInteger(p, "prem", intValue)){
premium = (intValue == 1);
}

if(readXMLInteger(p, "enabled", intValue)){
enabled = (intValue == 1);
}

if(readXMLInteger(p, "needtarget", intValue)){
needTarget = (intValue == 1);
}

if(readXMLInteger(p, "needweapon", intValue)){
needWeapon = (intValue == 1);
}

if(readXMLInteger(p, "selftarget", intValue)){
selfTarget = (intValue == 1);
}

if(readXMLInteger(p, "needlearn", intValue)){
learnable = (intValue == 1);
}

if(readXMLInteger(p, "range", intValue)){
range = intValue;
}

if(readXMLInteger(p, "blocking", intValue)){
blockingSolid = (intValue == 1);
blockingCreature = (intValue == 1);
}

if(readXMLString(p, "blocktype", strValue)){
if(asLowerCaseString(strValue) == "all"){
blockingSolid = true;
blockingCreature = true;
}
else if(asLowerCaseString(strValue) == "solid"){
blockingSolid = true;
}
else if(asLowerCaseString(strValue) == "creature"){
blockingCreature = true;
}
}

if(readXMLInteger(p, "aggressive", intValue)){
isAggressive = (intValue == 1);
}

xmlNodePtr vocationNode = p->children;
while(vocationNode){
if(xmlStrcmp(vocationNode->name,(const xmlChar*)"vocation") == 0){
if(readXMLString(vocationNode, "name", strValue)){
int32_t vocationId = g_vocations.getVocationId(strValue);

if(vocationId != -1){
vocSpellMap[vocationId] = true;
}
else{
std::cout << "Warning: [Spell::configureSpell] Wrong vocation name: " << strValue << std::endl;
}
}
}

vocationNode = vocationNode->next;
}

return true;
}

bool Spell::playerSpellCheck(Player* player) const
{
if(player->hasFlag(PlayerFlag_CannotUseSpells)){
return false;
}

if(!player->hasFlag(PlayerFlag_IgnoreSpellCheck)){
if(!enabled){
return false;
}

if(isAggressive){
if(!player->hasFlag(PlayerFlag_IgnoreProtectionZone) && player->getZone() == ZONE_PROTECTION){
player->sendCancelMessage(RET_ACTIONNOTPERMITTEDINPROTECTIONZONE);
return false;
}
}

if (player->hasCondition(CONDITION_EXHAUST_COMBAT) ||
player->hasCondition(CONDITION_EXHAUST_HEAL))
{
player->sendCancelMessage(RET_YOUAREEXHAUSTED);

if(isInstant()){
g_game.addMagicEffect(player->getPosition(), NM_ME_PUFF);
}

return false;
}

if(player->getLevel() < level){
player->sendCancelMessage(RET_NOTENOUGHLEVEL);
g_game.addMagicEffect(player->getPosition(), NM_ME_PUFF);
return false;
}

if(((int32_t)player->getMagicLevel()) < magLevel){
player->sendCancelMessage(RET_NOTENOUGHMAGICLEVEL);
g_game.addMagicEffect(player->getPosition(), NM_ME_PUFF);
return false;
}

if(player->getMana() < getManaCost(player) && !player->hasFlag(PlayerFlag_HasInfiniteMana)){
player->sendCancelMessage(RET_NOTENOUGHMANA);
g_game.addMagicEffect(player->getPosition(), NM_ME_PUFF);
return false;
}

#ifdef __PROTOCOL_76__
if(player->getPlayerInfo(PLAYERINFO_SOUL) < soul &&
!player->hasFlag(PlayerFlag_HasInfiniteSoul))
{
player->sendCancelMessage(RET_NOTENOUGHSOUL);
g_game.addMagicEffect(player->getPosition(), NM_ME_PUFF);
return false;
}
#endif // __PROTOCOL_76__

if(isInstant() && isLearnable()){
if(!player->hasLearnedInstantSpell(getName())){
player->sendCancelMessage(RET_YOUNEEDTOLEARNTHISSPELL);
g_game.addMagicEffect(player->getPosition(), NM_ME_PUFF);
return false;
}
}
else{
if(!vocSpellMap.empty()){
if(vocSpellMap.find(player->getVocationId()) == vocSpellMap.end()){
player->sendCancelMessage(RET_YOURVOCATIONCANNOTUSETHISSPELL);
g_game.addMagicEffect(player->getPosition(), NM_ME_PUFF);
return false;
}
}
}

if(needWeapon){
switch(player->getWeaponType()){
case WEAPON_SWORD:
case WEAPON_CLUB:
case WEAPON_AXE:
break;

default:
{
player->sendCancelMessage(RET_YOUNEEDAWEAPONTOUSETHISSPELL);
g_game.addMagicEffect(player->getPosition(), NM_ME_PUFF);
return false;
}
}
}

if(isPremium() && !player->isPremium()){
player->sendCancelMessage(RET_YOUNEEDPREMIUMACCOUNT);
return false;
}
}

return true;
}

bool Spell::playerInstantSpellCheck(Player* player, const Position& toPos)
{
if(!playerSpellCheck(player)){
return false;
}

if(toPos.x != 0xFFFF){
const Position& playerPos = player->getPosition();
if(playerPos.z > toPos.z){
player->sendCancelMessage(RET_FIRSTGOUPSTAIRS);
g_game.addMagicEffect(player->getPosition(), NM_ME_PUFF);
return false;
}
else if(playerPos.z < toPos.z){
player->sendCancelMessage(RET_FIRSTGODOWNSTAIRS);
g_game.addMagicEffect(player->getPosition(), NM_ME_PUFF);
return false;
}
else{
Tile* tile = g_game.getTile(toPos.x, toPos.y, toPos.z);

if(!tile){
tile = new Tile(toPos.x, toPos.y, toPos.z);
g_game.setTile(tile);
}

ReturnValue ret;
if((ret = Combat::canDoCombat(player, tile, isAggressive)) != RET_NOERROR){
player->sendCancelMessage(ret);
g_game.addMagicEffect(player->getPosition(), NM_ME_PUFF);
return false;
}

if(blockingCreature && !tile->creatures.empty()){
player->sendCancelMessage(RET_NOTENOUGHROOM);
g_game.addMagicEffect(player->getPosition(), NM_ME_PUFF);
return false;
}

if(blockingSolid && tile->hasProperty(BLOCKSOLID)){
player->sendCancelMessage(RET_NOTENOUGHROOM);
g_game.addMagicEffect(player->getPosition(), NM_ME_PUFF);
return false;
}
}
}

return true;
}

bool Spell::playerRuneSpellCheck(Player* player, const Position& toPos)
{
if(!playerSpellCheck(player)){
return false;
}

if(toPos.x != 0xFFFF){
const Position& playerPos = player->getPosition();
if(playerPos.z > toPos.z){
player->sendCancelMessage(RET_FIRSTGOUPSTAIRS);
g_game.addMagicEffect(player->getPosition(), NM_ME_PUFF);
return false;
}
else if(playerPos.z < toPos.z){
player->sendCancelMessage(RET_FIRSTGODOWNSTAIRS);
g_game.addMagicEffect(player->getPosition(), NM_ME_PUFF);
return false;
}
else{
Tile* tile = g_game.getTile(toPos.x, toPos.y, toPos.z);

if(!tile){
player->sendCancelMessage(RET_NOTPOSSIBLE);
g_game.addMagicEffect(player->getPosition(), NM_ME_PUFF);
return false;
}

if(range != -1){
if(!g_game.canThrowObjectTo(playerPos, toPos, true, range, range)){
player->sendCancelMessage(RET_DESTINATIONOUTOFREACH);
g_game.addMagicEffect(player->getPosition(), NM_ME_PUFF);
return false;
}
}

ReturnValue ret;
if((ret = Combat::canDoCombat(player, tile, isAggressive)) != RET_NOERROR){
player->sendCancelMessage(ret);
g_game.addMagicEffect(player->getPosition(), NM_ME_PUFF);
return false;
}

if(blockingCreature && !tile->creatures.empty()){
player->sendCancelMessage(RET_NOTENOUGHROOM);
g_game.addMagicEffect(player->getPosition(), NM_ME_PUFF);
return false;
}
else if(blockingSolid && tile->hasProperty(BLOCKSOLID)){
player->sendCancelMessage(RET_NOTENOUGHROOM);
g_game.addMagicEffect(player->getPosition(), NM_ME_PUFF);
return false;
}

if(needTarget && tile->creatures.empty()){
player->sendCancelMessage(RET_CANONLYUSETHISRUNEONCREATURES);
g_game.addMagicEffect(player->getPosition(), NM_ME_PUFF);
return false;
}
#ifdef __SKULLSYSTEM__
if(isAggressive && needTarget && player->hasSafeMode() && !tile->creatures.empty()){
Player* targetPlayer = tile->getTopCreature()->getPlayer();
if(targetPlayer && targetPlayer != player && targetPlayer->getSkull() == SKULL_NONE){
player->sendCancelMessage(RET_TURNSECUREMODETOATTACKUNMARKEDPLAYERS);
g_game.addMagicEffect(player->getPosition(), NM_ME_PUFF);
return false;
}
}
#endif
}
}

return true;
}

void Spell::postCastSpell(Player* player, bool finishedCast /*= true*/, bool payCost /*= true*/) const
{
if(finishedCast){
if(!player->hasFlag(PlayerFlag_HasNoExhaustion)){
if(exhaustion){
if(isAggressive){
if (customExhaust != 0 && customExhaust != g_game.getFightExhaustionTicks()) {
player->addCombatExhaust(customExhaust);
}
else {
player->addCombatExhaust(g_game.getFightExhaustionTicks());
}
}
else{
if (customExhaust != 0 && customExhaust != g_game.getHealExhaustionTicks()) {
player->addHealExhaust(customExhaust);
}
else {
player->addHealExhaust(g_game.getHealExhaustionTicks());
}
}
}
}

if(!player->hasFlag(PlayerFlag_NotGainInFight)){
if(isAggressive){
player->addInFightTicks();
}
}
}

if(payCost){
int32_t manaCost = getManaCost(player);

#ifdef __PROTOCOL_76__
int32_t soulCost = getSoulCost(player);
postCastSpell(player, (uint32_t)manaCost, (uint32_t)soulCost);
#else
postCastSpell(player, (uint32_t)manaCost);
#endif // __PROTOCOL_76__
}
}

#ifdef __PROTOCOL_76__
void Spell::postCastSpell(Player* player, uint32_t manaCost, uint32_t soulCost) const
{

if(manaCost > 0){
player->addManaSpent(manaCost);
if(!player->hasFlag(PlayerFlag_HasInfiniteMana)){
player->changeMana(-(int32_t)manaCost);
}
}

if(!player->hasFlag(PlayerFlag_HasInfiniteSoul)){
if(soulCost > 0){
player->changeSoul(-(int32_t)soulCost);
}
}
}
#else
void Spell::postCastSpell(Player* player, uint32_t manaCost) const
{
if(manaCost > 0){
player->addManaSpent(manaCost);
if(!player->hasFlag(PlayerFlag_HasInfiniteMana)){
player->changeMana(-(int32_t)manaCost);
}
}
}
#endif // __PROTOCOL_76__

int32_t Spell::getManaCost(const Player* player) const
{
if(mana != 0){
return mana;
}

if(manaPercent != 0){
int32_t maxMana = player->getMaxMana();
int32_t manaCost = (maxMana * manaPercent)/100;
return manaCost;
}

if(lvPercent != 0){
int32_t level = player->getLevel();
int32_t manaCost = (level * lvPercent)/100;
return manaCost;
}

return 0;
}

#ifdef __PROTOCOL_76__
int32_t Spell::getSoulCost(const Player* player) const
{
if(soul != 0){
return soul;
}

return 0;
}
#endif // __PROTOCOL_76__

ReturnValue Spell::CreateIllusion(Creature* creature, const Outfit_t outfit, int32_t time)
{
ConditionOutfit* outfitCondition = new ConditionOutfit(CONDITIONID_COMBAT, CONDITION_OUTFIT, time);

if(!outfitCondition){
return RET_NOTPOSSIBLE;
}

outfitCondition->addOutfit(outfit);
creature->addCondition(outfitCondition);

return RET_NOERROR;
}

ReturnValue Spell::CreateIllusion(Creature* creature, const std::string& name, int32_t time)
{
uint32_t mId = g_monsters.getIdByName(name);

if(mId == 0){
return RET_CREATUREDOESNOTEXIST;
}

const MonsterType* mType = g_monsters.getMonsterType(mId);

if(mType == NULL){
return RET_CREATUREDOESNOTEXIST;
}

Player* player = creature->getPlayer();
if(player && !player->hasFlag(PlayerFlag_CanIllusionAll)){
if(!mType->isIllusionable){
return RET_NOTPOSSIBLE;
}
}

return CreateIllusion(creature, mType->outfit, time);
}

ReturnValue Spell::CreateIllusion(Creature* creature, uint32_t itemId, int32_t time)
{
const ItemType& it = Item::items[itemId];
if(it.id == 0){
return RET_NOTPOSSIBLE;
}

Outfit_t outfit;
outfit.lookTypeEx = itemId;

return CreateIllusion(creature, outfit, time);
}

InstantSpell::InstantSpell(LuaScriptInterface* _interface) :
TalkAction(_interface)
{
casterTargetOrDirection = false;
needDirection = false;
hasParam = false;
checkLineOfSight = true;
function = NULL;
}

InstantSpell::~InstantSpell()
{
//
}

std::string InstantSpell::getScriptEventName()
{
return "onCastSpell";
}

bool InstantSpell::configureEvent(xmlNodePtr p)
{
if(!Spell::configureSpell(p)){
return false;
}

if(!TalkAction::configureEvent(p)){
return false;
}

int intValue;
std::string strValue;

if(readXMLInteger(p, "params", intValue)){
if(intValue == 1)
hasParam = true;
}

if(readXMLInteger(p, "direction", intValue)){
needDirection = (intValue == 1);
}
else if(readXMLInteger(p, "casterTargetOrDirection", intValue)){
casterTargetOrDirection = (intValue == 1);
}

if(readXMLInteger(p, "blockwalls", intValue)){
checkLineOfSight = (intValue == 1);
}

return true;
}

bool InstantSpell::loadFunction(const std::string& functionName)
{
if(asLowerCaseString(functionName) == "edithouseguest"){
isAggressive = false;
function = HouseGuestList;
}
else if(asLowerCaseString(functionName) == "edithousesubowner"){
isAggressive = false;
function = HouseSubOwnerList;
}
else if(asLowerCaseString(functionName) == "edithousedoor"){
isAggressive = false;
function = HouseDoorList;
}
else if(asLowerCaseString(functionName) == "housekick"){
isAggressive = false;
function = HouseKick;
}
else if(asLowerCaseString(functionName) == "searchplayer"){
isAggressive = false;
function = SearchPlayer;
}
else if(asLowerCaseString(functionName) == "summonmonster"){
function = SummonMonster;
}
else if(asLowerCaseString(functionName) == "levitate"){
isAggressive = false;
function = Levitate;
}
else if(asLowerCaseString(functionName) == "illusion"){
isAggressive = false;
function = Illusion;
}
else{
return false;
}

m_scripted = false;
return true;
}

bool InstantSpell::playerCastInstant(Player* player, const std::string& param)
{
if(!playerSpellCheck(player)){
return false;
}

LuaVariant var;

if(selfTarget){
var.type = VARIANT_NUMBER;
var.number = player->getID();
}
else if(needTarget || casterTargetOrDirection){
Creature* target = NULL;
bool useDirection = false;

if(hasParam){
Player* playerTarget = NULL;
ReturnValue ret = g_game.getPlayerByNameWildcard(param, playerTarget);
target = playerTarget;

if(!target || target->getHealth() <= 0){
if(!casterTargetOrDirection){
player->sendCancelMessage(ret);//RET_PLAYERWITHTHISNAMEISNOTONLINE);
g_game.addMagicEffect(player->getPosition(), NM_ME_PUFF);
return false;
}
useDirection = true;
}
}
else{
target = player->getAttackedCreature();

if(!target || target->getHealth() <= 0){
if(!casterTargetOrDirection){
player->sendCancelMessage(RET_YOUCANONLYUSEITONCREATURES);
g_game.addMagicEffect(player->getPosition(), NM_ME_PUFF);
return false;
}
useDirection = true;
}
}

if(!useDirection){
if(!canThrowSpell(player, target)){
player->sendCancelMessage(RET_CREATUREISNOTREACHABLE);
g_game.addMagicEffect(player->getPosition(), NM_ME_PUFF);
return false;
}

var.type = VARIANT_NUMBER;
var.number = target->getID();
}
else{
var.type = VARIANT_POSITION;
var.pos = Spells::getCasterPosition(player, player->getDirection());

if(!playerInstantSpellCheck(player, var.pos)){
return false;
}
}
}
else if(hasParam){
var.type = VARIANT_STRING;
var.text = param;
}
else{
var.type = VARIANT_POSITION;
if(needDirection){
var.pos = Spells::getCasterPosition(player, player->getDirection());
}
else{
var.pos = player->getPosition();
}

if(!playerInstantSpellCheck(player, var.pos)){
return false;
}
}

bool result = internalCastSpell(player, var);

if(result){
Spell::postCastSpell(player);
}

return result;
}

bool InstantSpell::canThrowSpell(const Creature* creature, const Creature* target) const
{
const Position& fromPos = creature->getPosition();
const Position& toPos = target->getPosition();

if(fromPos.z != toPos.z ||
(range == -1 && !g_game.canThrowObjectTo(fromPos, toPos, checkLineOfSight)) ||
(range != -1 && !g_game.canThrowObjectTo(fromPos, toPos, checkLineOfSight, range, range)) ){
return false;
}

return true;
}

bool InstantSpell::castSpell(Creature* creature)
{
LuaVariant var;
if(casterTargetOrDirection){
Creature* target = creature->getAttackedCreature();

if(target && target->getHealth() > 0){
if(!canThrowSpell(creature, target)){
return false;
}

var.type = VARIANT_NUMBER;
var.number = target->getID();
return internalCastSpell(creature, var);
}
return false;
}
else if(needDirection){
var.type = VARIANT_POSITION;
var.pos = Spells::getCasterPosition(creature, creature->getDirection());
}
else{
var.type = VARIANT_POSITION;
var.pos = creature->getPosition();
}

return internalCastSpell(creature, var);
}

bool InstantSpell::castSpell(Creature* creature, Creature* target)
{
if(needTarget){
LuaVariant var;
var.type = VARIANT_NUMBER;
var.number = target->getID();

return internalCastSpell(creature, var);
}
else{
return castSpell(creature);
}
}

bool InstantSpell::internalCastSpell(Creature* creature, const LuaVariant& var)
{
bool result = false;

if(m_scripted){
result = executeCastSpell(creature, var);
}
else{
if(function){
result = function(this, creature, var.text);
}
}

return result;
}

bool InstantSpell::executeCastSpell(Creature* creature, const LuaVariant& var)
{
//onCastSpell(cid, var)
if(m_scriptInterface->reserveScriptEnv()){
ScriptEnviroment* env = m_scriptInterface->getScriptEnv();

#ifdef __DEBUG_LUASCRIPTS__
std::stringstream desc;
desc << "onCastSpell - " << creature->getName();
env->setEventDesc(desc.str());
#endif

env->setScriptId(m_scriptId, m_scriptInterface);
env->setRealPos(creature->getPosition());

lua_State* L = m_scriptInterface->getLuaState();

uint32_t cid = env->addThing(creature);

m_scriptInterface->pushFunction(m_scriptId);
lua_pushnumber(L, cid);
m_scriptInterface->pushVariant(L, var);

int32_t result = m_scriptInterface->callFunction(2);
m_scriptInterface->releaseScriptEnv();

return (result != LUA_ERROR);
}
else{
std::cout << "[Error] Call stack overflow. InstantSpell::executeCastSpell" << std::endl;
return false;
}
}

House* InstantSpell::getHouseFromPos(Creature* creature)
{
if(creature){
Player* player = creature->getPlayer();
if(player){
HouseTile* houseTile = dynamic_cast<HouseTile*>(player->getTile());
if(houseTile){
House* house = houseTile->getHouse();
if(house){
return house;
}
}
}
}
return NULL;
}

bool InstantSpell::HouseGuestList(const InstantSpell* spell, Creature* creature, const std::string& param)
{
House* house = getHouseFromPos(creature);
if(!house){
return false;
}

Player* player = creature->getPlayer();

if(house->canEditAccessList(GUEST_LIST, player)){
player->setEditHouse(house, GUEST_LIST);
player->sendHouseWindow(house, GUEST_LIST);
return true;
}
else{
player->sendCancelMessage(RET_NOTPOSSIBLE);
g_game.addMagicEffect(player->getPosition(), NM_ME_PUFF);
}

return true;
}

bool InstantSpell::HouseSubOwnerList(const InstantSpell* spell, Creature* creature, const std::string& param)
{
House* house = getHouseFromPos(creature);
if(!house)
return false;

Player* player = creature->getPlayer();

if(house->canEditAccessList(SUBOWNER_LIST, player)){
player->setEditHouse(house, SUBOWNER_LIST);
player->sendHouseWindow(house, SUBOWNER_LIST);
return true;
}
else{
player->sendCancelMessage(RET_NOTPOSSIBLE);
g_game.addMagicEffect(player->getPosition(), NM_ME_PUFF);
}

return true;
}

bool InstantSpell::HouseDoorList(const InstantSpell* spell, Creature* creature, const std::string& param)
{
House* house = getHouseFromPos(creature);
if(!house)
return false;

Player* player = creature->getPlayer();
Position pos = Spells::getCasterPosition(player, player->getDirection());
Door* door = house->getDoorByPosition(pos);

if(door && house->canEditAccessList(door->getDoorId(), player)){
player->setEditHouse(house, door->getDoorId());
player->sendHouseWindow(house, door->getDoorId());
return true;
}
else{
player->sendCancelMessage(RET_NOTPOSSIBLE);
g_game.addMagicEffect(player->getPosition(), NM_ME_PUFF);
}

return true;
}

bool InstantSpell::HouseKick(const InstantSpell* spell, Creature* creature, const std::string& param)
{
House* house = getHouseFromPos(creature);
if(!house)
return false;

Player* player = creature->getPlayer();
house->kickPlayer(player, param);

return true;
}

bool InstantSpell::SearchPlayer(const InstantSpell* spell, Creature* creature, const std::string& param)
{
//a. From 1 to 4 sq's [Person] is standing next to you.
//b. From 5 to 100 sq's [Person] is to the south, north, east, west.
//c. From 101 to 274 sq's [Person] is far to the south, north, east, west.
//d. From 275 to infinite sq's [Person] is very far to the south, north, east, west.
//e. South-west, s-e, n-w, n-e (corner coordinates): this phrase appears if the player you're looking for has moved five squares in any direction from the south, north, east or west.
//f. Lower level to the (direction): this phrase applies if the person you're looking for is from 1-25 squares up/down the actual floor you're in.
//g. Higher level to the (direction): this phrase applies if the person you're looking for is from 1-25 squares up/down the actual floor you're in.

Player* player = creature->getPlayer();
if(!player){
return false;
}

enum distance_t{
DISTANCE_BESIDE,
DISTANCE_CLOSE_1,
DISTANCE_CLOSE_2,
DISTANCE_FAR,
DISTANCE_VERYFAR,
};

enum direction_t{
DIR_N, DIR_S, DIR_E, DIR_W,
DIR_NE, DIR_NW, DIR_SE, DIR_SW,
};

enum level_t{
LEVEL_HIGHER,
LEVEL_LOWER,
LEVEL_SAME,
};

Player* playerExiva = NULL;
ReturnValue ret = g_game.getPlayerByNameWildcard(param, playerExiva);

if(playerExiva && ret == RET_NOERROR){
if(playerExiva->getAccessLevel() > player->getAccessLevel()){
player->sendCancelMessage(RET_PLAYERWITHTHISNAMEISNOTONLINE);
g_game.addMagicEffect(player->getPosition(), NM_ME_PUFF);
return false;
}

const Position lookPos = player->getPosition();
const Position searchPos = playerExiva->getPosition();

int32_t dx = lookPos.x - searchPos.x;
int32_t dy = lookPos.y - searchPos.y;
int32_t dz = lookPos.z - searchPos.z;

distance_t distance;
direction_t direction;
level_t level;
//getting floor
if(dz > 0){
level = LEVEL_HIGHER;
}
else if(dz < 0){
level = LEVEL_LOWER;
}
else{
level = LEVEL_SAME;
}
//getting distance
if(std::abs(dx) < 4 && std::abs(dy) <4){
distance = DISTANCE_BESIDE;
}
else{
int32_t distance2 = dx*dx + dy*dy;
if(distance2 < 625){
distance = DISTANCE_CLOSE_1;
}
else if(distance2 < 10000){
distance = DISTANCE_CLOSE_2;
}
else if(distance2 < 75076){
distance = DISTANCE_FAR;
}
else{
distance = DISTANCE_VERYFAR;
}
}
//getting direction
float tan;
if(dx != 0){
tan = (float)dy/(float)dx;
}
else{
tan = 10.;
}
if(std::abs(tan) < 0.4142){
if(dx > 0){
direction = DIR_W;
}
else{
direction = DIR_E;
}
}
else if(std::abs(tan) < 2.4142){
if(tan > 0){
if(dy > 0){
direction = DIR_NW;
}
else{
direction = DIR_SE;
}
}
else{ //tan < 0
if(dx > 0){
direction = DIR_SW;
}
else{
direction = DIR_NE;
}
}
}
else{
if(dy > 0){
direction = DIR_N;
}
else{
direction = DIR_S;
}
}

std::stringstream ss;
ss << playerExiva->getName() << " ";

if(distance == DISTANCE_BESIDE){
if(level == LEVEL_SAME)
ss << "is standing next to you";
else if(level == LEVEL_HIGHER)
ss << "is above you";
else if(level == LEVEL_LOWER)
ss << "is below you";
}
else{
switch(distance){
case DISTANCE_CLOSE_1:
if(level == LEVEL_SAME){
ss << "is to the";
}
else if(level == LEVEL_HIGHER){
ss << "is on a higher level to the";
}
else if(level == LEVEL_LOWER){
ss << "is on a lower level to the";
}
break;

case DISTANCE_CLOSE_2:
ss << "is to the";
break;

case DISTANCE_FAR:
ss << "is far to the";
break;

case DISTANCE_VERYFAR:
ss << "is very far to the";
break;

default:
break;
}

ss << " ";
switch(direction){
case DIR_N:
ss << "north";
break;

case DIR_S:
ss << "south";
break;
case DIR_E:

ss << "east";
break;

case DIR_W:
ss << "west";
break;

case DIR_NE:
ss << "north-east";
break;

case DIR_NW:
ss << "north-west";
break;

case DIR_SE:
ss << "south-east";
break;

case DIR_SW:
ss << "south-west";
break;
}
}

ss << ".";
player->sendTextMessage(MSG_INFO_DESCR, ss.str().c_str());
g_game.addMagicEffect(player->getPosition(), NM_ME_MAGIC_ENERGY);
return true;
}
else{
player->sendCancelMessage(ret);
g_game.addMagicEffect(player->getPosition(), NM_ME_PUFF);
}

return false;
}

bool InstantSpell::SummonMonster(const InstantSpell* spell, Creature* creature, const std::string& param)
{
Player* player = creature->getPlayer();
if(!player){
return false;
}

MonsterType* mType = g_monsters.getMonsterType(param);
if(!mType){
player->sendCancelMessage(RET_NOTPOSSIBLE);
g_game.addMagicEffect(player->getPosition(), NM_ME_PUFF);
return false;
}

int32_t manaCost = mType->manaCost;
if(!player->hasFlag(PlayerFlag_CanSummonAll)){
if(!mType->isSummonable){
player->sendCancelMessage(RET_NOTPOSSIBLE);
g_game.addMagicEffect(player->getPosition(), NM_ME_PUFF);
return false;
}

if(player->getMana() < manaCost){
player->sendCancelMessage(RET_NOTENOUGHMANA);
g_game.addMagicEffect(player->getPosition(), NM_ME_PUFF);
return false;
}

if(player->getSummonCount() >= 2){
player->sendCancel("You cannot summon more creatures.");
g_game.addMagicEffect(player->getPosition(), NM_ME_PUFF);
return false;
}
}

ReturnValue ret = RET_NOERROR;
Monster* monster = Monster::createMonster(param);
if(!monster){
ret = RET_NOTPOSSIBLE;
}
else{
// Place the monster
creature->addSummon(monster);
if(!g_game.placeCreature(monster, creature->getPosition(), true)){
creature->removeSummon(monster);
ret = RET_NOTENOUGHROOM;
}
}

if(ret == RET_NOERROR){
#ifdef __PROTOCOL_76__
spell->postCastSpell(player, (uint32_t)manaCost, (uint32_t)spell->getSoulCost(player));
#else
spell->postCastSpell(player, (uint32_t)manaCost);
#endif // __PROTOCOL_76__
g_game.addMagicEffect(player->getPosition(), NM_ME_MAGIC_POISON);
}
else{
player->sendCancelMessage(ret);
g_game.addMagicEffect(player->getPosition(), NM_ME_PUFF);
}

return (ret == RET_NOERROR);
}

bool InstantSpell::Levitate(const InstantSpell* spell, Creature* creature, const std::string& param)
{
Player* player = creature->getPlayer();
if(!player){
return false;
}

const Position& currentPos = creature->getPosition();
const Position& destPos = Spells::getCasterPosition(creature, creature->getDirection());

ReturnValue ret = RET_NOTPOSSIBLE;
if(asLowerCaseString(param) == "up"){
if(currentPos.z != 8){
Tile* tmpTile = g_game.getTile(currentPos.x, currentPos.y, currentPos.z - 1);
if(tmpTile == NULL || (tmpTile->ground == NULL && !tmpTile->hasProperty(IMMOVABLEBLOCKSOLID))){
tmpTile = g_game.getTile(destPos.x, destPos.y, destPos.z - 1);
if(tmpTile && tmpTile->ground && !tmpTile->hasProperty(IMMOVABLEBLOCKSOLID) && !tmpTile->floorChange()){
ret = g_game.internalMoveCreature(player, player->getTile(),
tmpTile, FLAG_IGNOREBLOCKITEM | FLAG_IGNOREBLOCKCREATURE);
}
}
}
}
else if(asLowerCaseString(param) == "down"){
if(currentPos.z != 7){
Tile* tmpTile = g_game.getTile(destPos.x, destPos.y, destPos.z);
if(tmpTile == NULL || (tmpTile->ground == NULL && !tmpTile->hasProperty(BLOCKSOLID))){
tmpTile = g_game.getTile(destPos.x, destPos.y, destPos.z + 1);
if(tmpTile && tmpTile->ground && !tmpTile->hasProperty(IMMOVABLEBLOCKSOLID) && !tmpTile->floorChange()){
ret = g_game.internalMoveCreature(player, player->getTile(),
tmpTile, FLAG_IGNOREBLOCKITEM | FLAG_IGNOREBLOCKCREATURE);
}
}
}
}

if(ret == RET_NOERROR){
g_game.addMagicEffect(currentPos, NM_ME_ENERGY_AREA);
}
else{
player->sendCancelMessage(ret);
g_game.addMagicEffect(player->getPosition(), NM_ME_PUFF);
}

return (ret == RET_NOERROR);
}

bool InstantSpell::Illusion(const InstantSpell* spell, Creature* creature, const std::string& param)
{
Player* player = creature->getPlayer();
if(!player){
return false;
}

ReturnValue ret = CreateIllusion(creature, param, 60000);

if(ret == RET_NOERROR){
g_game.addMagicEffect(player->getPosition(), NM_ME_MAGIC_BLOOD);
}
else{
player->sendCancelMessage(ret);
g_game.addMagicEffect(player->getPosition(), NM_ME_PUFF);
}

return (ret == RET_NOERROR);
}

bool InstantSpell::canCast(const Player* player) const
{
if(player->hasFlag(PlayerFlag_CannotUseSpells)){
return false;
}

if(player->hasFlag(PlayerFlag_IgnoreSpellCheck)){
return true;
}

if(isLearnable()){
if(player->hasLearnedInstantSpell(getName())){
return true;
}
}
else{
if(vocSpellMap.empty() || vocSpellMap.find(player->getVocationId()) != vocSpellMap.end()){
return true;
}
}

return false;
}


ConjureSpell::ConjureSpell(LuaScriptInterface* _interface) :
InstantSpell(_interface)
{
isAggressive = false;
conjureId = 0;
conjureCount = 1;
conjureReagentId = 0;
}

ConjureSpell::~ConjureSpell()
{
//
}

std::string ConjureSpell::getScriptEventName()
{
return "onCastSpell";
}

bool ConjureSpell::configureEvent(xmlNodePtr p)
{
if(!InstantSpell::configureEvent(p)){
return false;
}

/*
if(!Spell::configureSpell(p)){
return false;
}

if(!TalkAction::configureEvent(p)){
return false;
}
*/

int intValue;

if(readXMLInteger(p, "conjureId", intValue)){
conjureId = intValue;
}

if(readXMLInteger(p, "conjureCount", intValue)){
conjureCount = intValue;
}
else if(conjureId != 0){
//load the default charge from items.xml
const ItemType& it = Item::items[conjureId];
if(it.charges != 0){
conjureCount = it.charges;
}
}

if(readXMLInteger(p, "reagentId", intValue)){
conjureReagentId = intValue;
}

return true;
}

bool ConjureSpell::loadFunction(const std::string& functionName)
{
if(asLowerCaseString(functionName) == "conjureitem"){
function = ConjureItem;
}
else if(asLowerCaseString(functionName) == "conjurerune"){
function = ConjureItem;
}
else if(asLowerCaseString(functionName) == "conjurefood"){
function = ConjureFood;
}
else{
return false;
}

m_scripted = false;
return true;
}

ReturnValue ConjureSpell::internalConjureItem(Player* player, uint32_t conjureId, uint32_t conjureCount)
{
Item* newItem = Item::CreateItem(conjureId, conjureCount);
if(!newItem){
return RET_NOTPOSSIBLE;
}

ReturnValue result = g_game.internalPlayerAddItem(player, newItem);
if(result != RET_NOERROR){
delete newItem;
}

return result;
}

ReturnValue ConjureSpell::internalConjureItem(Player* player, uint32_t conjureId,
uint32_t conjureCount, uint32_t reagentId, slots_t slot, bool test /*= false*/)
{
if(reagentId != 0){
Item* item = player->getInventoryItem(slot);
if(item && item->getID() == reagentId){
if(item->isStackable() && item->getItemCount() != 1){ //TODO? reagentCount
return RET_YOUNEEDTOSPLITYOURSPEARS;
}

if(test){
return RET_NOERROR;
}

Item* newItem = g_game.transformItem(item, conjureId, conjureCount);
if(newItem){
g_game.startDecay(newItem);
}

return RET_NOERROR;
}
}

return RET_YOUNEEDAMAGICITEMTOCASTSPELL;
}

bool ConjureSpell::ConjureItem(const ConjureSpell* spell, Creature* creature, const std::string& param)
{
Player* player = creature->getPlayer();

if(!player){
return false;
}

if(!player->hasFlag(PlayerFlag_IgnoreSpellCheck) && player->getZone() == ZONE_PVP){
player->sendCancelMessage(RET_CANNOTCONJUREITEMHERE);
g_game.addMagicEffect(player->getPosition(), NM_ME_PUFF);
return false;
}

ReturnValue result = RET_NOERROR;
if(spell->getReagentId() != 0){
//Test if we can cast the conjure spell on left hand
ReturnValue result1 = internalConjureItem(player, spell->getConjureId(), spell->getConjureCount(),
spell->getReagentId(), SLOT_LEFT, true);

if(result1 == RET_NOERROR){
//Check level/mana etc.
if(!spell->playerSpellCheck(player)){
return false;
}

result1 = internalConjureItem(player, spell->getConjureId(), spell->getConjureCount(),
spell->getReagentId(), SLOT_LEFT);

if(result1 == RET_NOERROR){
spell->postCastSpell(player, false);
}
}

//Check if we can cast the conjure spell on the right hand
ReturnValue result2 = internalConjureItem(player, spell->getConjureId(), spell->getConjureCount(),
spell->getReagentId(), SLOT_RIGHT, true);

if(result2 == RET_NOERROR){
//Check level/mana etc.
if(!spell->playerSpellCheck(player)){
//Finished the cast, add exhaustion and stuff
spell->postCastSpell(player, true, false);
return false;
}

result2 = internalConjureItem(player, spell->getConjureId(), spell->getConjureCount(),
spell->getReagentId(), SLOT_RIGHT);

if(result2 == RET_NOERROR){
spell->postCastSpell(player, false);
}
}

if(result1 == RET_NOERROR || result2 == RET_NOERROR){
//Finished the cast, add exhaustion and stuff
spell->postCastSpell(player, true, false);
g_game.addMagicEffect(player->getPosition(), NM_ME_MAGIC_BLOOD);
return true;
}

result = result1;
if((result == RET_NOERROR && result2 != RET_NOERROR) ||
(result == RET_YOUNEEDAMAGICITEMTOCASTSPELL && result2 == RET_YOUNEEDTOSPLITYOURSPEARS) ) {
result = result2;
}
}
else{
if(internalConjureItem(player, spell->getConjureId(), spell->getConjureCount()) == RET_NOERROR){
spell->postCastSpell(player);
g_game.addMagicEffect(player->getPosition(), NM_ME_MAGIC_BLOOD);
return true;
}
}

player->sendCancelMessage(result);
g_game.addMagicEffect(player->getPosition(), NM_ME_PUFF);
return false;
}

bool ConjureSpell::ConjureFood(const ConjureSpell* spell, Creature* creature, const std::string& param)
{
Player* player = creature->getPlayer();

if(!player){
return false;
}

uint32_t foodType[8] = {
ITEM_MEAT,
ITEM_HAM,
ITEM_GRAPE,
ITEM_APPLE,
ITEM_BREAD,
ITEM_CHEESE,
ITEM_ROLL,
ITEM_BREAD
};

bool result = (internalConjureItem(player, foodType[random_range(0, 7)], 1) == RET_NOERROR);

if(result){
spell->postCastSpell(player);
g_game.addMagicEffect(player->getPosition(), NM_ME_MAGIC_POISON);
}

return result;
}

bool ConjureSpell::playerCastInstant(Player* player, const std::string& param)
{
if(!playerSpellCheck(player)){
return false;
}

bool result = false;

if(m_scripted){
LuaVariant var;
var.type = VARIANT_STRING;
var.text = param;
result = executeCastSpell(player, var);
}
else{
if(function){
result = function(this, player, param);
}
}

return result;
}

RuneSpell::RuneSpell(LuaScriptInterface* _interface) :
Action(_interface)
{
hasCharges = true;
runeId = 0;
function = NULL;

allowFarUse = true;
}

RuneSpell::~RuneSpell()
{
//
}

std::string RuneSpell::getScriptEventName()
{
return "onCastSpell";
}

bool RuneSpell::configureEvent(xmlNodePtr p)
{
if(!Spell::configureSpell(p)){
return false;
}

if(!Action::configureEvent(p)){
return false;
}

int intValue;
if(readXMLInteger(p, "id", intValue)){
runeId = intValue;
}
else{
std::cout << "Error: [RuneSpell::configureSpell] Rune spell without id." << std::endl;
return false;
}

uint32_t charges = 0;
if(readXMLInteger(p, "charges", intValue)){
charges = intValue;
}

hasCharges = (charges > 0);

if(magLevel != 0 || level != 0){
//Change information in the ItemType to get accurate description
ItemType& iType = Item::items.getItemType(runeId);
iType.runeSpellName = getName();
iType.runeMagLevel = magLevel;
iType.runeLevel = level;
iType.charges = charges;
}

return true;
}

bool RuneSpell::loadFunction(const std::string& functionName)
{
if(functionName == "chameleon"){
function = Illusion;
}
else if(functionName == "convince"){
function = Convince;
}
else{
return false;
}

m_scripted = false;
return true;
}

bool RuneSpell::Illusion(const RuneSpell* spell, Creature* creature, Item* item,
const Position& posFrom, const Position& posTo)
{
Player* player = creature->getPlayer();
if(!player){
return false;
}

Thing* thing = g_game.internalGetThing(player, posTo, 0, 0, STACKPOS_MOVE);
if(!thing){
player->sendCancelMessage(RET_NOTPOSSIBLE);
g_game.addMagicEffect(player->getPosition(), NM_ME_PUFF);
return false;
}

Item* illusionItem = thing->getItem();
if(!illusionItem || illusionItem->isNotMoveable()){
player->sendCancelMessage(RET_NOTPOSSIBLE);
g_game.addMagicEffect(player->getPosition(), NM_ME_PUFF);
return false;
}

ReturnValue ret = CreateIllusion(creature, illusionItem->getID(), 60000);

if(ret == RET_NOERROR){
g_game.addMagicEffect(player->getPosition(), NM_ME_MAGIC_BLOOD);
}
else{
player->sendCancelMessage(ret);
g_game.addMagicEffect(player->getPosition(), NM_ME_PUFF);
}

return (ret == RET_NOERROR);
}

bool RuneSpell::Convince(const RuneSpell* spell, Creature* creature, Item* item, const Position& posFrom, const Position& posTo)
{
Player* player = creature->getPlayer();
if(!player){
return false;
}

if(!player->hasFlag(PlayerFlag_CanConvinceAll)){
if(player->getSummonCount() >= 2){
player->sendCancelMessage(RET_NOTPOSSIBLE);
g_game.addMagicEffect(player->getPosition(), NM_ME_PUFF);
return false;
}
}

Thing* thing = g_game.internalGetThing(player, posTo, 0, 0, STACKPOS_LOOK);
if(!thing){
player->sendCancelMessage(RET_NOTPOSSIBLE);
g_game.addMagicEffect(player->getPosition(), NM_ME_PUFF);
return false;
}

Creature* convinceCreature = thing->getCreature();
if(!convinceCreature){
player->sendCancelMessage(RET_NOTPOSSIBLE);
g_game.addMagicEffect(player->getPosition(), NM_ME_PUFF);
return false;
}

int32_t manaCost = 0;

if(convinceCreature->getMonster()){
manaCost = convinceCreature->getMonster()->getManaCost();
}

if(!player->hasFlag(PlayerFlag_HasInfiniteMana) && player->getMana() < manaCost){
player->sendCancelMessage(RET_NOTENOUGHMANA);
g_game.addMagicEffect(player->getPosition(), NM_ME_PUFF);
return false;
}

if(!convinceCreature->convinceCreature(creature)){
player->sendCancelMessage(RET_NOTPOSSIBLE);
g_game.addMagicEffect(player->getPosition(), NM_ME_PUFF);
return false;
}

#ifdef __PROTOCOL_76__
spell->postCastSpell(player, (uint32_t)manaCost, (uint32_t)spell->getSoulCost(player));
#else
spell->postCastSpell(player, (uint32_t)manaCost);
#endif // __PROTOCOL_76__

g_game.addMagicEffect(player->getPosition(), NM_ME_MAGIC_BLOOD);
return true;
}

ReturnValue RuneSpell::canExecuteAction(const Player* player, const Position& toPos)
{
if(player->hasFlag(PlayerFlag_CannotUseSpells)){
return RET_CANNOTUSETHISOBJECT;
}

ReturnValue ret = Action::canExecuteAction(player, toPos);
if(ret != RET_NOERROR){
return ret;
}

if(toPos.x == 0xFFFF){
if(needTarget){
return RET_CANONLYUSETHISRUNEONCREATURES;
}
else if(!selfTarget){
return RET_NOTENOUGHROOM;
}
}

return RET_NOERROR;
}

bool RuneSpell::executeUse(Player* player, Item* item, const PositionEx& posFrom,
const PositionEx& posTo, bool extendedUse, uint32_t creatureId)
{
if(!playerRuneSpellCheck(player, posTo)){
return false;
}

bool result = false;

if(m_scripted){
LuaVariant var;

if(creatureId != 0){
var.type = VARIANT_NUMBER;
var.number = creatureId;
}
else{
var.type = VARIANT_POSITION;
var.pos = posTo;
}

result = internalCastSpell(player, var);
}
else{
if(function){
result = function(this, player, item, posFrom, posTo);
}
}

if(result){
Spell::postCastSpell(player);

if(hasCharges && item && g_config.getBoolean(ConfigManager::REMOVE_RUNE_CHARGES)){
int32_t newCharge = std::max((int32_t)0, ((int32_t)item->getCharges()) - 1);
g_game.transformItem(item, item->getID(), newCharge);
}
}

return result;
}

bool RuneSpell::castSpell(Creature* creature)
{
LuaVariant var;
var.type = VARIANT_NUMBER;
var.number = creature->getID();

return internalCastSpell(creature, var);
}

bool RuneSpell::castSpell(Creature* creature, Creature* target)
{
LuaVariant var;
var.type = VARIANT_NUMBER;
var.number = target->getID();

return internalCastSpell(creature, var);
}

bool RuneSpell::internalCastSpell(Creature* creature, const LuaVariant& var)
{
bool result = false;

if(m_scripted){
result = executeCastSpell(creature, var);
}
else{
//call hardcodedAction
result = false;
}

return result;
}

bool RuneSpell::executeCastSpell(Creature* creature, const LuaVariant& var)
{
//onCastSpell(cid, var)
if(m_scriptInterface->reserveScriptEnv()){
ScriptEnviroment* env = m_scriptInterface->getScriptEnv();

#ifdef __DEBUG_LUASCRIPTS__
std::stringstream desc;
desc << "onCastSpell - " << creature->getName();
env->setEventDesc(desc.str());
#endif

env->setScriptId(m_scriptId, m_scriptInterface);
env->setRealPos(creature->getPosition());

lua_State* L = m_scriptInterface->getLuaState();

uint32_t cid = env->addThing(creature);

m_scriptInterface->pushFunction(m_scriptId);
lua_pushnumber(L, cid);
m_scriptInterface->pushVariant(L, var);

int32_t result = m_scriptInterface->callFunction(2);
m_scriptInterface->releaseScriptEnv();

return (result != LUA_ERROR);
}
else{
std::cout << "[Error] Call stack overflow. RuneSpell::executeCastSpell" << std::endl;
return false;
}
}
 

Jastro

Senior User
Joined
Aug 18, 2009
Messages
727
Reaction score
101
Odp: C++ Brak ceny domku i wy?wietlanie czaru

Tw?j fragment kodu zamie? na:
[CPP]std::stringstream houseDescription;
houseDescription << "It belongs to house '" << houseName << "'. " << std::endl;

if(houseOwner != 0){
houseDescription << houseOwnerName << " owns this house." << std::endl;
}
else{
houseDescription << "Nobody owns this house. This house cost: " << price << std::endl;
}

HouseDoorList::iterator it;
for(it = doorList.begin(); it != doorList.end(); ++it){
(*it)->setSpecialDescription(houseDescription.str());
}
}[/CPP]
znajd?:
[cpp]rent = 0;[/cpp]
po tym dodaj:
[cpp]price = 0;[/cpp]
znajd?:
[cpp]void House::setAccessList(uint32_t listId, const std::string& textlist)[/cpp]
przed tym dodaj:
[cpp]void House::setPrice(uint32_t _price, bool update /*= false*/)
{
price = _price;
if(update && !getHouseOwner())
updateDoorDescription();
}[/cpp]
znajd?:
[cpp]Position entryPos(0, 0, 0);[/cpp]
po tym dodaj:
[cpp]uint32_t _price = 0;[/cpp]
znajd?:
[cpp]house->setTownId(intValue);[/cpp]
po tym dodaj:
[cpp] if(g_config.getBool(ConfigManager::HOUSE_RENTASPRICE) && house->getRent())
house->setPrice(house->getRent());
else
{
for(HouseTileList::iterator it = house->getHouseTileBegin(); it != house->getHouseTileEnd(); it++)
_price += g_config.getNumber(ConfigManager::HOUSE_PRICE);

if(g_config.getBool(ConfigManager::HOUSE_PRICEASRENT))
house->setRent(_price);

house->setPrice(_price);
}[/cpp]
znajd?:
[cpp]bool Houses::payHouses()[/cpp]
przed tym dodaj:
[cpp]bool Houses::reloadPrices()
{
for(HouseMap::iterator it = houseMap.begin(); it != houseMap.end(); ++it)
{
if(g_config.getBool(ConfigManager::HOUSE_RENTASPRICE) && it->second->getRent())
continue;

uint32_t _price = 0;
for(HouseTileList::iterator tit = it->second->getHouseTileBegin(); tit != it->second->getHouseTileEnd(); tit++)
_price += g_config.getNumber(ConfigManager::HOUSE_PRICE);

it->second->setPrice(_price, true);
}

return true;
}[/cpp]
 
Last edited:
Status
Not open for further replies.
Top