Crossfire Server, Trunk  R20513
transport.c
Go to the documentation of this file.
1 /*
2  * Crossfire -- cooperative multi-player graphical RPG and adventure game
3  *
4  * Copyright (c) 1999-2014 Mark Wedel and the Crossfire Development Team
5  * Copyright (c) 1992 Frank Tore Johansen
6  *
7  * Crossfire is free software and comes with ABSOLUTELY NO WARRANTY. You are
8  * welcome to redistribute it under certain conditions. For details, please
9  * see COPYING and LICENSE.
10  *
11  * The authors can be reached via e-mail at <crossfire@metalforge.org>.
12  */
13 
21 #include "global.h"
22 
23 #include <stdlib.h>
24 
25 #include "ob_methods.h"
26 #include "ob_types.h"
27 #include "shop.h"
28 #include "sounds.h"
29 #include "sproto.h"
30 
31 static method_ret transport_type_apply(ob_methods *context, object *op, object *applier, int aflags);
32 static method_ret transport_type_process(ob_methods *context, object *op);
33 
37 void init_type_transport(void) {
40 }
41 
54 static method_ret transport_type_apply(ob_methods *context, object *op, object *applier, int aflags) {
55  object *old_transport = applier->contr->transport;
56  object *inv;
57  char name_op[MAX_BUF], name_old[MAX_BUF];
58 
59  /* Only players can use transports right now */
60  if (applier->type != PLAYER)
61  return 0;
62 
63  query_name(op, name_op, MAX_BUF);
64 
65  /* If player is currently on a transport but not this transport, they need
66  * to exit first. Perhaps transport to transport transfers should be
67  * allowed.
68  */
69  if (old_transport && old_transport != op) {
70  query_name(old_transport, name_old, MAX_BUF);
72  "You must exit %s before you can board %s.",
73  name_old, name_op);
74  return 1;
75  }
76 
77  /* player is currently on a transport. This must mean he
78  * wants to exit.
79  */
80  if (old_transport) {
81  /* Should we print a message if the player only wants to
82  * apply?
83  */
84  if (aflags&AP_APPLY)
85  return 1;
86 
87  query_name(old_transport, name_old, MAX_BUF);
89  "You disembark from %s.",
90  name_old);
91  object_remove(applier);
92  if (applier->contr == old_transport->contr)
93  old_transport->contr = NULL;
94 
95  applier->contr->transport = NULL;
96  object_insert_in_map_at(applier, old_transport->map, applier, 0, old_transport->x, old_transport->y);
97  object_sum_weight(old_transport);
98 
99  /* Possible for more than one player to be using a transport.
100  * if that is the case, we don't want to reset the face, as the
101  * transport is still occupied.
102  */
103  inv = object_find_by_type(old_transport, PLAYER);
104  if (!inv) {
105  old_transport->face = old_transport->arch->clone.face;
106  old_transport->animation_id = old_transport->arch->clone.animation_id;
107  } else {
108  old_transport->contr = inv->contr;
110  "%s has disembarked. You are now the captain of %s",
111  applier->name, name_old);
112  }
113  return 1;
114  } else {
115  /* player is trying to board a transport */
116  int pc = 0, p_limit;
117  const char *kv;
118  int16_t ox, oy;
119 
120  if (aflags&AP_UNAPPLY)
121  return 1;
122 
123  /* Can this transport hold the weight of this player? */
124  if (!transport_can_hold(op, applier, 1)) {
126  "The %s is unable to hold your weight!",
127  name_op);
128  return 1;
129  }
130 
131  /* If the player is holding the transport, drop it. */
132  if (op->env == applier) {
133  old_transport = op;
134  /* Don't drop transports in shops. */
135  if (!shop_contains(applier)) {
136  op = drop_object(applier, op, 1);
137  } else {
139  "You cannot drop the %s in a shop to use it.",
140  name_old);
141  return 1;
142  }
143  /* Did it fail to drop? */
144  if (!op) {
146  "You need to drop the %s to use it.",
147  name_old);
148  return 1;
149  }
150  }
151 
152  /* Does this transport have space for more players? */
153  FOR_INV_PREPARE(op, inv)
154  if (inv->type == PLAYER)
155  pc++;
156  FOR_INV_FINISH();
157 
158  kv = object_get_value(op, "passenger_limit");
159  if (!kv)
160  p_limit = 1;
161  else
162  p_limit = atoi(kv);
163  if (pc >= p_limit) {
165  "The %s does not have space for any more people",
166  name_op);
167  return 1;
168  }
169 
170  /* Everything checks out OK - player can get on the transport */
171  applier->contr->transport = op;
172 
173  if (op->contr) {
175  "The %s's captain is currently %s",
176  name_op, op->contr->ob->name);
177  } else {
179  "You're the %s's captain",
180  name_op);
181  op->contr = applier->contr;
182  }
183 
184  object_remove(applier);
185  /* object_insert_in_ob clear applier->x and applier->y, so store them away */
186  ox = applier->x;
187  oy = applier->y;
188  object_insert_in_ob(applier, op);
189  object_sum_weight(op);
190  applier->map = op->map;
191  if (ox != op->x || oy != op->y) {
192  esrv_map_scroll(&applier->contr->socket, (ox-op->x), (oy-op->y));
193  }
194  applier->contr->socket.update_look = 1;
195  applier->contr->socket.look_position = 0;
196  applier->x = op->x;
197  applier->y = op->y;
198 
199  /* Might need to update face, animation info */
200  if (!pc) {
201  const char *str;
202 
203  str = object_get_value(op, "face_full");
204  if (str)
205  op->face = &new_faces[find_face(str, op->face->number)];
206  str = object_get_value(op, "anim_full");
207  if (str)
208  op->animation_id = find_animation(str);
209  }
210 
211  /* Does speed of this object change based on weight? */
212  kv = object_get_value(op, "weight_speed_ratio");
213  if (kv) {
214  int wsr = atoi(kv);
215  float base_speed;
216 
217  kv = object_get_value(op, "base_speed");
218  if (kv)
219  base_speed = atof(kv);
220  else
221  base_speed = op->arch->clone.speed;
222 
223  op->speed = base_speed-(base_speed*op->carrying*wsr)/(op->weight_limit*100);
224 
225  /* Put some limits on min/max speeds */
226  if (op->speed < 0.10)
227  op->speed = 0.10;
228  if (op->speed > 1.0)
229  op->speed = 1.0;
230  }
231  } /* else if player is boarding the transport */
232  return 1;
233 }
234 
242 static method_ret transport_type_process(ob_methods *context, object *op) {
243  /* Transports are directed by players - thus, there
244  * speed is reduced when the player moves them about.
245  * So give them back there speed here, since process_objects()
246  * has decremented it.
247  */
248  if (op->speed_left < 0.0) {
249  op->speed_left += 1.0;
250  return 1;
251  }
252  return 0;
253 }
void draw_ext_info_format(int flags, int pri, const object *pl, uint8_t type, uint8_t subtype, const char *format,...)
Sends message to player(s).
Definition: main.c:315
#define AP_UNAPPLY
Item is to be remvoed.
Definition: define.h:611
Sound-related defines.
int32_t weight_limit
Weight-limit of object.
Definition: object.h:366
see doc/Developers/objects
Definition: object.h:108
bool shop_contains(object *ob)
Check if an object is in a shop.
Definition: shop.c:1239
Typedefs for ob_methods.
Definition: ob_methods.h:45
New_Face * new_faces
Contains face information, with names, numbers, magicmap color and such.
Definition: image.c:33
uint16_t animation_id
An index into the animation array.
Definition: object.h:416
object * object_find_by_type(const object *who, int type)
Find object in inventory.
Definition: object.c:3903
uint16_t look_position
Start of drawing of look window.
Definition: newserver.h:126
signed long object_sum_weight(object *op)
object_sum_weight() is a recursive function which calculates the weight an object is carrying...
Definition: object.c:311
const char * object_get_value(const object *op, const char *const key)
Get an extra value by key.
Definition: object.c:4246
object clone
An object from which to do object_copy()
Definition: object.h:470
socket_struct socket
Socket information for this player.
Definition: player.h:94
static method_ret transport_type_apply(ob_methods *context, object *op, object *applier, int aflags)
Player is trying to use a transport.
Definition: transport.c:54
Global type definitions and header inclusions.
#define AP_APPLY
Item is to be applied.
Definition: define.h:610
#define MSG_TYPE_APPLY
Applying objects.
Definition: newclient.h:384
uint16_t number
This is the image id.
Definition: face.h:15
char method_ret
Define some standard return values for callbacks which don&#39;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
object * object_insert_in_ob(object *op, object *where)
This function inserts the object op in the linked list inside the object environment.
Definition: object.c:2690
float speed_left
How much speed is left to spend this round.
Definition: object.h:329
signed short int16_t
Definition: win32.h:160
struct mapdef * map
Pointer to the map in which this object is present.
Definition: object.h:297
#define MSG_TYPE_APPLY_ERROR
Definition: newclient.h:596
object * transport
Transport the player is in.
Definition: player.h:195
#define FOR_INV_FINISH()
Finishes FOR_INV_PREPARE().
Definition: define.h:712
int32_t carrying
How much weight this object contains.
Definition: object.h:367
const char * name
The name of the object, obviously...
Definition: object.h:311
struct obj * env
Pointer to the object which is the environment.
Definition: object.h:293
int find_animation(const char *name)
Finds the animation id that matches name.
Definition: anim.c:144
void register_apply(int ob_type, apply_func method)
Registers the apply method for the given type.
Definition: ob_types.c:62
struct pl * contr
Pointer to the player which control this object.
Definition: object.h:276
float speed
The overall speed of this object.
Definition: object.h:328
#define MSG_TYPE_APPLY_UNAPPLY
Unapply an object.
Definition: newclient.h:597
#define MAX_BUF
Used for all kinds of things.
Definition: define.h:35
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.
object * ob
The object representing the player.
Definition: player.h:158
See Player.
Definition: object.h:107
struct archt * arch
Pointer to archetype.
Definition: object.h:412
uint8_t type
PLAYER, BULLET, etc.
Definition: object.h:338
int transport_can_hold(const object *transport, const object *op, int nrof)
Can transport hold object op? This is a pretty trivial function, but in the future, possible transport may have more restrictions or weight reduction like containers.
Definition: apply.c:54
#define MSG_TYPE_APPLY_SUCCESS
Was able to apply object.
Definition: newclient.h:598
void register_process(int ob_type, process_func method)
Registers the process method for the given type.
Definition: ob_types.c:71
#define NDI_UNIQUE
Print immediately, don&#39;t buffer.
Definition: newclient.h:245
void query_name(const object *op, char *buf, size_t size)
Describes an item.
Definition: item.c:625
const New_Face * face
Face with colors.
Definition: object.h:332
void init_type_transport(void)
Initializer for the TRANSPORT object type.
Definition: transport.c:37
Object type functions and variables.
object * drop_object(object *op, object *tmp, uint32_t nrof)
Try to drop an object on the floor.
Definition: c_object.c:814
unsigned find_face(const char *name, unsigned error)
This returns an the face number of face &#39;name&#39;.
Definition: image.c:303
static method_ret transport_type_process(ob_methods *context, object *op)
Processes a Transport.
Definition: transport.c:242
#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