Crossfire Server, Trunk  R20513
shop_mat.c
Go to the documentation of this file.
1 /*
2  CrossFire, A Multiplayer game for X-windows
3 
4  Copyright (C) 2007 Mark Wedel & Crossfire Development Team
5  Copyright (C) 1992 Frank Tore Johansen
6 
7  This program is free software; you can redistribute it and/or modify
8  it under the terms of the GNU General Public License as published by
9  the Free Software Foundation; either version 2 of the License, or
10  (at your option) any later version.
11 
12  This program is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  GNU General Public License for more details.
16 
17  You should have received a copy of the GNU General Public License
18  along with this program; if not, write to the Free Software
19  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 
21  The authors can be reached via e-mail at crossfire-devel@real-time.com
22 */
23 
27 #include "global.h"
28 #include "ob_methods.h"
29 #include "ob_types.h"
30 #include "shop.h"
31 #include "sounds.h"
32 #include "sproto.h"
33 
34 static method_ret shop_mat_type_move_on(ob_methods *context, object *trap, object *victim, object *originator);
35 
39 void init_type_shop_mat(void) {
41 }
42 
51 static method_ret shop_mat_type_move_on(ob_methods *context, object *trap, object *victim, object *originator) {
52  int rv = 0;
53  double opinion;
54 
55  if (common_pre_ob_move_on(trap, victim, originator) == METHOD_ERROR)
56  return METHOD_OK;
57 
58  SET_FLAG(victim, FLAG_NO_APPLY); /* prevent loops */
59 
60  if (victim->type != PLAYER) {
61  /* Remove all the unpaid objects that may be carried here.
62  * This could be pets or monsters that are somehow in
63  * the shop.
64  */
65  FOR_INV_PREPARE(victim, tmp) {
66  if (QUERY_FLAG(tmp, FLAG_UNPAID)) {
67  int i = object_find_free_spot(tmp, victim->map, victim->x, victim->y, 1, 9);
68  object_remove(tmp);
69  if (i == -1)
70  i = 0;
71  object_insert_in_map_at(tmp, victim->map, victim, 0, victim->x+freearr_x[i], victim->y+freearr_y[i]);
72  }
73  } FOR_INV_FINISH();
74 
75  /* Don't teleport things like spell effects */
76  if (QUERY_FLAG(victim, FLAG_NO_PICK))
77  goto leave;
78 
79  /* unpaid objects, or non living objects, can't transfer by
80  * shop mats. Instead, put it on a nearby space.
81  */
82  if (QUERY_FLAG(victim, FLAG_UNPAID) || !QUERY_FLAG(victim, FLAG_ALIVE)) {
83  /* Somebody dropped an unpaid item, just move to an adjacent place. */
84  int i = object_find_free_spot(victim, victim->map, victim->x, victim->y, 1, 9);
85  if (i != -1) {
86  rv = transfer_ob(victim, victim->x+freearr_x[i], victim->y+freearr_y[i], 0, trap);
87  }
88  goto leave;
89  }
90  rv = teleport(trap, SHOP_MAT, victim);
91  /* immediate block below is only used for players */
92  } else if (can_pay(victim)) {
93  shop_pay_unpaid(victim, victim->inv);
94  rv = teleport(trap, SHOP_MAT, victim);
95  if (trap->msg) {
97  trap->msg);
98  }
99  /* This check below is a bit simplistic - generally it should be correct,
100  * but there is never a guarantee that the bottom space on the map is
101  * actually the shop floor.
102  */
103  else if (!rv && !shop_contains(victim)) {
104  opinion = shop_approval(victim->map, victim);
105  if (opinion > 0.9)
107  "The shopkeeper gives you a friendly wave.");
108  else if (opinion > 0.75)
110  "The shopkeeper waves to you.");
111  else if (opinion > 0.5)
113  "The shopkeeper ignores you.");
114  else
116  "The shopkeeper glares at you with contempt.");
117  }
118  } else {
119  /* if we get here, a player tried to leave a shop but was not able
120  * to afford the items he has. We try to move the player so that
121  * they are not on the mat anymore
122  */
123  int i = object_find_free_spot(victim, victim->map, victim->x, victim->y, 1, 9);
124  if (i == -1)
125  LOG(llevError, "Internal shop-mat problem.\n");
126  else {
127  object_remove(victim);
128  rv = object_insert_in_map_at(victim, victim->map, trap, 0, victim->x+freearr_x[i], victim->y+freearr_y[i]) == NULL;
129  esrv_map_scroll(&victim->contr->socket, freearr_x[i], freearr_y[i]);
130  victim->contr->socket.update_look = 1;
131  victim->contr->socket.look_position = 0;
132  }
133  }
134  CLEAR_FLAG(victim, FLAG_NO_APPLY);
135 leave:
136  common_post_ob_move_on(trap, victim, originator);
137  return METHOD_OK;
138 }
Error, serious thing.
Definition: logger.h:11
Sound-related defines.
#define FLAG_UNPAID
Object hasn't been paid for yet.
Definition: define.h:236
bool shop_contains(object *ob)
Check if an object is in a shop.
Definition: shop.c:1239
void leave(player *pl, int draw_exit)
Player logs out, or was disconnected.
Definition: server.c:1180
#define SET_FLAG(xyz, p)
Definition: define.h:223
Typedefs for ob_methods.
Definition: ob_methods.h:45
method_ret common_pre_ob_move_on(object *trap, object *victim, object *originator)
Definition: common_apply.c:51
uint16_t look_position
Start of drawing of look window.
Definition: newserver.h:126
#define METHOD_ERROR
Definition: ob_methods.h:17
socket_struct socket
Socket information for this player.
Definition: player.h:94
short freearr_x[SIZEOFFREE]
X offset when searching around a spot.
Definition: object.c:65
double shop_approval(const mapstruct *map, const object *player)
Return the approval ratio for a shop for a given player.
Definition: shop.c:1078
Global type definitions and header inclusions.
void draw_ext_info(int flags, int pri, const object *pl, uint8_t type, uint8_t subtype, const char *message)
Sends message to player(s).
Definition: main.c:310
#define MSG_TYPE_APPLY
Applying objects.
Definition: newclient.h:384
short freearr_y[SIZEOFFREE]
Y offset when searching around a spot.
Definition: object.c:71
char method_ret
Define some standard return values for callbacks which don't need to return any other results...
Definition: ob_methods.h:14
uint32_t update_look
If true, we need to send the look window.
Definition: newserver.h:115
int16_t y
Position in the map for this object.
Definition: object.h:326
object * object_insert_in_map_at(object *op, mapstruct *m, object *originator, int flag, int x, int y)
Same as object_insert_in_map() except it handle separate coordinates and do a clean job preparing mul...
Definition: object.c:1921
#define FLAG_ALIVE
Object can fight (or be fought)
Definition: define.h:230
void init_type_shop_mat(void)
Initializer for the SHOP_MAT object type.
Definition: shop_mat.c:39
void register_move_on(int ob_type, move_on_func method)
Registers the move_on method for the given type.
Definition: ob_types.c:89
#define METHOD_OK
Definition: ob_methods.h:15
struct mapdef * map
Pointer to the map in which this object is present.
Definition: object.h:297
#define FOR_INV_FINISH()
Finishes FOR_INV_PREPARE().
Definition: define.h:712
#define MSG_TYPE_SHOP_MISC
Random messages.
Definition: newclient.h:493
int teleport(object *teleporter, uint8_t tele_type, object *user)
Teleport an item around a nearby random teleporter of specified type.
Definition: move.c:188
struct pl * contr
Pointer to the player which control this object.
Definition: object.h:276
See Shop Mat.
Definition: object.h:184
#define MSG_TYPE_SHOP
Definition: newclient.h:378
#define QUERY_FLAG(xyz, p)
Definition: define.h:225
#define CLEAR_FLAG(xyz, p)
Definition: define.h:224
int16_t x
Definition: object.h:326
void esrv_map_scroll(socket_struct *ns, int dx, int dy)
Definition: request.c:1499
Object type variables.
#define FLAG_NO_APPLY
Avoids step_on/fly_on to this object.
Definition: define.h:302
void common_post_ob_move_on(object *trap, object *victim, object *originator)
Definition: common_apply.c:87
See Player.
Definition: object.h:107
uint8_t type
PLAYER, BULLET, etc.
Definition: object.h:338
#define MSG_TYPE_APPLY_SUCCESS
Was able to apply object.
Definition: newclient.h:598
const char * msg
If this is a book/sign/magic mouth/etc.
Definition: object.h:322
static method_ret shop_mat_type_move_on(ob_methods *context, object *trap, object *victim, object *originator)
Move on this Shop Mat object.
Definition: shop_mat.c:51
struct obj * inv
Pointer to the first object in the inventory.
Definition: object.h:290
#define NDI_UNIQUE
Print immediately, don't buffer.
Definition: newclient.h:245
void LOG(LogLevel logLevel, const char *format,...)
Logs a message to stderr, or to file.
Definition: logger.c:51
int shop_pay_unpaid(object *pl, object *op)
Pay for each unpaid item carried by a player, including those inside containers.
Definition: shop.c:855
int transfer_ob(object *op, int x, int y, int randomly, object *originator)
Move an object (even linked objects) to another spot on the same map.
Definition: move.c:144
int object_find_free_spot(const object *ob, mapstruct *m, int x, int y, int start, int stop)
object_find_free_spot(object, map, x, y, start, stop) will search for a spot at the given map and coo...
Definition: object.c:3415
int can_pay(object *pl)
Checks all unpaid items in op's inventory, adds up all the money they have, and checks that they can ...
Definition: shop.c:812
#define FLAG_NO_PICK
Object can't be picked up.
Definition: define.h:239
Object type functions and variables.
#define FOR_INV_PREPARE(op_, it_)
Constructs a loop iterating over the inventory of an object.
Definition: define.h:705
void object_remove(object *op)
This function removes the object op from the linked list of objects which it is currently tied to...
Definition: object.c:1654