/**************************************************************************/
// shop.cpp - shop functionality written by Slortar
/***************************************************************************
* The Dawn of Time v1.69r (c)1997-2004 Michael Garratt *
* >> A number of people have contributed to the Dawn codebase, with the *
* majority of code written by Michael Garratt - www.dawnoftime.org *
* >> To use this source code, you must fully comply with the dawn license *
* in licenses.txt... In particular, you may not remove this copyright *
* notice. *
***************************************************************************/
#include "shop.h"
/**************************************************************************/
/*
* The default constructor. Don't forget to initliase new member variables
* here.
* \return Nothing.
* \param None.
*/
cShopData::cShopData()
{
close_hour = 23;
open_hour = 0;
profit_buy = 100;
profit_sell = 100;
vnKeeper = 0;
}
/**************************************************************************/
/*
* The default destructor.
* \return Nothing.
* \param None.
*/
cShopData::~cShopData()
{
}
/**************************************************************************/
/*
* The default constructor. Don't forget to initliase new member variables
* here.
* \return Nothing.
* \param None.
*/
cInnData::cInnData()
{
pNextInn = NULL;
for(int i=0; i<MAX_INN; i++){
vnRoom[i]=0;
shRate[i]=0;
}
}
/**************************************************************************/
/*
* The default destructor.
* \return Nothing.
* \param None.
*/
cInnData::~cInnData()
{
}
/**************************************************************************/
/* Returns the first NPC in the same room as *ch that is an innkeeper. If there
* is an innkeeper in the room, but he's unavailable for action. Closing hours,
* unable to see *ch, then NULL is returned.
* \return The pointer to the char_data structure of a NPC innkeeper.
* \param ch Pointer to the char_data structure of a player.
*/
char_data* find_innkeeper(char_data *ch)
{
cInnData* pInn = NULL;
char_data* pKeeper = NULL;
for ( pKeeper=ch->in_room->people; pKeeper; pKeeper=pKeeper->next_in_room ) {
if ( IS_NPC(pKeeper) && (pInn=pKeeper->pIndexData->pInnData) != NULL ) {
break;
}
}
// No innkeeper in the room.
if ( pInn == NULL ) {
ch->println("You can't do that here.");
return NULL;
}
// Shop hours.
if ( time_info.hour < pInn->open_hour )
{
do_say( pKeeper, "Sorry, I am closed. Come back later." );
return NULL;
}
if ( time_info.hour > pInn->close_hour )
{
do_say( pKeeper, "Sorry, I am closed. Come back tomorrow." );
return NULL;
}
// Invisible or hidden people.
if ( !can_see( pKeeper, ch ) && INVIS_LEVEL(ch)<1)
{
do_say( pKeeper, "I don't rent to folks I can't see." );
return NULL;
}
return pKeeper;
}
/**************************************************************************/
/*
* Allows players to rent a room. The function makes the necesary checks on
* the room and the player etc. Then the function parses the argument which
* should represent the number of hours the player wishes to rent the room.
* Renting a room will set the player's first point of recall to this room,
* for a certain amount of hours.
* \return Nothing.
* \param ch The pointer to the player's char_data structure.
* \param aArg The string containing the input the player supplied.
*/
void do_rent( char_data *ch, char *aArg)
{
char_data* pInnKeeper = NULL;
cInnData* pInn = NULL;
ROOM_INDEX_DATA* pRoom = NULL;
const double uiTicksPerGameHour = 11.4;
unsigned int uiNumHours = 0;
vn_int roomVnum = 0;
long roomRate = 0;
int roomCost = 0;
int roomHaggle = 0;
sh_int roomIdx = 0;
char arg1[MIL];
char arg2[MIL];
aArg = one_argument(aArg, arg1);
aArg = one_argument(aArg, arg2);
// Check the room is an inn.
if ( (ch->in_room != NULL) && (!IS_SET(ch->in_room->room_flags, ROOM_INN)) ) {
ch->println("Perhaps try renting a room at an inn.");
if(IS_IMMORTAL(ch) || HAS_SECURITY(ch,1)){
ch->wrapln("[imm/builder only message] A room must have the INN flag set.");
}
return;
}
// Find the innkeeper.
if ( (pInnKeeper=find_innkeeper(ch)) == NULL ) {
ch->println("The innkeeper seems to have run off.");
if(IS_IMMORTAL(ch) || HAS_SECURITY(ch,1)){
ch->wrapln("[imm/builder only message] This room is marked as an inn, but a mob with an inn assigned "
"was not found (or outside the hours for their inn).");
}
return;
}
// Check arguments.
if ( !is_number(arg1) || !is_number(arg2) ) {
ch->println("Syntax: rent <room number> <number of hours>");
return;
}
roomIdx = (sh_int)atoi(arg1);
if(roomIdx<1 || roomIdx>MAX_INN){
ch->println("Syntax: rent <room number> <number of hours>");
ch->printlnf("The room number must be between 1 and %d", MAX_INN);
return;
}
uiNumHours = (sh_int)atoi(arg2);
pInn = pInnKeeper->pIndexData->pInnData;
// Get the relevant room details.
roomVnum = pInn->vnRoom[roomIdx-1];
roomRate = pInn->shRate[roomIdx-1];
// Check the room is a valid room.
if ( (pRoom=get_room_index(roomVnum))==NULL ) {
ch->println("That room is not available.");
return;
}
// Calculate the cost and check the cost will be positive.
if ( (roomCost=(roomRate*uiNumHours)) <= 0 ) {
ch->println("You can't rent a room for that amount of hours.");
return;
}
// haggle ( code taken from do_buy the petshop bit, made a few alterations. )
roomHaggle = number_percent();
if (roomHaggle < get_skill(ch,gsn_haggle)) {
// Haggle succeeded.
roomCost -= roomCost / 2 * roomHaggle / 100;
if ( (ch->silver + 100 * ch->gold) < roomCost)
{
ch->printlnf( "You haggle the price down to %d coin%s, but "
"still can't afford it.", roomCost, roomCost==1?"":"s");
if ( (ch->silver + 100 * ch->gold) > (roomCost * 96/100) )
{
roomCost=(ch->silver + 100 * ch->gold);
ch->printlnf( "You explain this to the innkeeper and manage to "
"haggle the price down to the money that you do have!");
} else { // didn't get it
WAIT_STATE(ch, 20); // 5 seconds lag to reduce potential abuse
return;
}
} else {
ch->printlnf( "You haggle the price down to %d coin%s.",
roomCost, roomCost==1?"":"s");
check_improve(ch, gsn_haggle, true, 4);
}
}else{
// Haggle failed.
if ( (ch->silver + 100 * ch->gold) < roomCost ) {
ch->println("You can't afford it.");
check_improve(ch, gsn_haggle, false, 2);
return;
} else {
ch->printlnf( "You succesfully rented a room for %d coin%s.",
roomCost, roomCost==1?"":"s");
}
}
deduct_cost(ch, roomCost);
// If you're renting the same room, then just add the extra days to the end of your
// current period. Rounded downwards.
if ( ch->recall_inn_room == roomVnum && ch->expire_recall_inn>0 ) {
uiNumHours+=(ch->expire_recall_inn / (int)uiTicksPerGameHour);
} else {
ch->recall_inn_room = roomVnum;
}
ch->expire_recall_inn=(int)(uiNumHours*uiTicksPerGameHour);
ch->printlnf("You will recall to `#%s`^ for the following %d hour%s.", pRoom->name, uiNumHours, uiNumHours==1 ? "" : "s");
ch->println("Type `#`=Crecall reset`^ to cancel this and recall to your default location.");
return;
}
/**************************************************************************/
/**************************************************************************/