Crossfire Server, Branches 1.12  R18729
transport.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 
29 #include <global.h>
30 #include <ob_methods.h>
31 #include <ob_types.h>
32 #include <sounds.h>
33 #include <sproto.h>
34 
35 static method_ret transport_type_apply(ob_methods *context, object *op, object *applier, int aflags);
36 static method_ret transport_type_process(ob_methods *context, object *op);
37 
41 void init_type_transport(void) {
44 }
45 
58 static method_ret transport_type_apply(ob_methods *context, object *op, object *applier, int aflags) {
59  object *old_transport = applier->contr->transport;
60  object *inv;
61  char name_op[MAX_BUF], name_old[MAX_BUF];
62 
63  /* Only players can use transports right now */
64  if (applier->type != PLAYER)
65  return 0;
66 
67  query_name(op, name_op, MAX_BUF);
68 
69  /* If player is currently on a transport but not this transport, they need
70  * to exit first. Perhaps transport to transport transfers should be
71  * allowed.
72  */
73  if (old_transport && old_transport != op) {
74  query_name(old_transport, name_old, MAX_BUF);
76  "You must exit %s before you can board %s.",
77  "You must exit %s before you can board %s.",
78  name_old, name_op);
79  return 1;
80  }
81 
82  /* player is currently on a transport. This must mean he
83  * wants to exit.
84  */
85  if (old_transport) {
86  /* Should we print a message if the player only wants to
87  * apply?
88  */
89  if (aflags&AP_APPLY)
90  return 1;
91 
92  query_name(old_transport, name_old, MAX_BUF);
94  "You disembark from %s.", "You disembark from %s.",
95  name_old);
96  remove_ob(applier);
97  applier->map = old_transport->map;
98  applier->x = old_transport->x;
99  applier->y = old_transport->y;
100  if (applier->contr == old_transport->contr)
101  old_transport->contr = NULL;
102 
103  applier->contr->transport = NULL;
104  insert_ob_in_map(applier, applier->map, applier, 0);
105  sum_weight(old_transport);
106 
107  /* Possible for more than one player to be using a transport.
108  * if that is the case, we don't want to reset the face, as the
109  * transport is still occupied.
110  */
111  for (inv = old_transport->inv; inv; inv = inv->below)
112  if (inv->type == PLAYER)
113  break;
114  if (!inv) {
115  old_transport->face = old_transport->arch->clone.face;
116  old_transport->animation_id = old_transport->arch->clone.animation_id;
117  } else {
118  old_transport->contr = inv->contr;
120  "%s has disembarked. You are now the captain of %s",
121  "%s has disembarked. You are now the captain of %s",
122  applier->name, name_old);
123  }
124  return 1;
125  } else {
126  /* player is trying to board a transport */
127  int pc = 0, p_limit;
128  const char *kv;
129  sint16 ox, oy;
130 
131  if (aflags&AP_UNAPPLY)
132  return 1;
133 
134  /* Can this transport hold the weight of this player? */
135  if (!transport_can_hold(op, applier, 1)) {
137  "The %s is unable to hold your weight!",
138  "The %s is unable to hold your weight!",
139  name_op);
140  return 1;
141  }
142 
143  /* If the player is holding the transport, drop it. */
144  if (op->env == applier) {
145  old_transport = op;
146  /* Don't drop transports in shops. */
147  if (!is_in_shop(applier)) {
148  op = drop_object(applier, op, 1);
149  } else {
151  "You cannot drop the %s in a shop to use it.",
152  "You cannot drop the %s in a shop to use it.",
153  name_old);
154  return 1;
155  }
156  /* Did it fail to drop? */
157  if (!op) {
159  "You need to drop the %s to use it.",
160  "You need to drop the %s to use it.",
161  name_old);
162  return 1;
163  }
164  }
165 
166  /* Does this transport have space for more players? */
167  for (inv = op->inv; inv; inv = inv->below)
168  if (inv->type == PLAYER)
169  pc++;
170 
171  kv = get_ob_key_value(op, "passenger_limit");
172  if (!kv)
173  p_limit = 1;
174  else
175  p_limit = atoi(kv);
176  if (pc >= p_limit) {
178  "The %s does not have space for any more people",
179  "The %s does not have space for any more people",
180  name_op);
181  return 1;
182  }
183 
184  /* Everything checks out OK - player can get on the transport */
185  applier->contr->transport = op;
186 
187  if (op->contr) {
189  "The %s's captain is currently %s",
190  "The %s's captain is currently %s",
191  name_op, op->contr->ob->name);
192  } else {
194  "You're the %s's captain",
195  "You're the %s's captain",
196  name_op);
197  op->contr = applier->contr;
198  }
199 
200  remove_ob(applier);
201  /* insert_ob_in_ob clear applier->x and applier->y, so store them away */
202  ox = applier->x;
203  oy = applier->y;
204  insert_ob_in_ob(applier, op);
205  sum_weight(op);
206  applier->map = op->map;
207  if (ox != op->x || oy != op->y) {
208  esrv_map_scroll(&applier->contr->socket, (ox-op->x), (oy-op->y));
209  }
210  applier->contr->socket.update_look = 1;
211  applier->contr->socket.look_position = 0;
212  applier->x = op->x;
213  applier->y = op->y;
214 
215  /* Might need to update face, animation info */
216  if (!pc) {
217  const char *str;
218 
219  str = get_ob_key_value(op, "face_full");
220  if (str)
221  op->face = &new_faces[find_face(str, op->face->number)];
222  str = get_ob_key_value(op, "anim_full");
223  if (str)
224  op->animation_id = find_animation(str);
225  }
226 
227  /* Does speed of this object change based on weight? */
228  kv = get_ob_key_value(op, "weight_speed_ratio");
229  if (kv) {
230  int wsr = atoi(kv);
231  float base_speed;
232 
233  kv = get_ob_key_value(op, "base_speed");
234  if (kv)
235  base_speed = atof(kv);
236  else
237  base_speed = op->arch->clone.speed;
238 
239  op->speed = base_speed-(base_speed*op->carrying*wsr)/(op->weight_limit*100);
240 
241  /* Put some limits on min/max speeds */
242  if (op->speed < 0.10)
243  op->speed = 0.10;
244  if (op->speed > 1.0)
245  op->speed = 1.0;
246  }
247  } /* else if player is boarding the transport */
248  return 1;
249 }
250 
258 static method_ret transport_type_process(ob_methods *context, object *op) {
259  /* Transports are directed by players - thus, there
260  * speed is reduced when the player moves them about.
261  * So give them back there speed here, since process_objects()
262  * has decremented it.
263  */
264  if (op->speed_left < 0.0) {
265  op->speed_left += 1.0;
266  return 1;
267  }
268  return 0;
269 }
#define AP_UNAPPLY
Definition: define.h:1010
int is_in_shop(object *ob)
Definition: shop.c:1414
const char * get_ob_key_value(const object *op, const char *const key)
Definition: object.c:3701
signed short sint16
Definition: global.h:72
New_Face * new_faces
Definition: image.c:38
object clone
Definition: object.h:326
socket_struct socket
Definition: player.h:148
static method_ret transport_type_apply(ob_methods *context, object *op, object *applier, int aflags)
Definition: transport.c:58
sint16 x
Definition: object.h:179
signed long sum_weight(object *op)
Definition: object.c:317
#define AP_APPLY
Definition: define.h:1009
void draw_ext_info_format(int flags, int pri, const object *pl, uint8 type, uint8 subtype, const char *new_format, const char *old_format,...)
Definition: standalone.c:175
#define MSG_TYPE_APPLY_UNAPPLY
Definition: newclient.h:517
#define PLAYER
Definition: define.h:113
char method_ret
Definition: ob_methods.h:41
uint16 number
Definition: face.h:43
void remove_ob(object *op)
Definition: object.c:1515
sint32 weight_limit
Definition: object.h:217
#define TRANSPORT
Definition: define.h:114
float speed_left
Definition: object.h:182
struct mapdef * map
Definition: object.h:155
object * transport
Definition: player.h:249
sint32 carrying
Definition: object.h:218
const char * name
Definition: object.h:167
struct obj * env
Definition: object.h:151
struct obj * below
Definition: object.h:145
object * drop_object(object *op, object *tmp, uint32 nrof)
Definition: c_object.c:847
int find_animation(const char *name)
Definition: anim.c:146
sint16 y
Definition: object.h:179
void register_apply(int ob_type, apply_func method)
Definition: ob_types.c:79
struct pl * contr
Definition: object.h:134
float speed
Definition: object.h:181
#define MSG_TYPE_APPLY
Definition: newclient.h:330
object * insert_ob_in_ob(object *op, object *where)
Definition: object.c:2510
#define MAX_BUF
Definition: define.h:81
object * insert_ob_in_map(object *op, mapstruct *m, object *originator, int flag)
Definition: object.c:1992
void esrv_map_scroll(socket_struct *ns, int dx, int dy)
Definition: request.c:1432
uint16 look_position
Definition: newserver.h:142
object * ob
Definition: player.h:207
#define MSG_TYPE_APPLY_SUCCESS
Definition: newclient.h:518
uint32 update_look
Definition: newserver.h:131
struct archt * arch
Definition: object.h:263
int transport_can_hold(const object *transport, const object *op, int nrof)
Definition: apply.c:64
#define MSG_TYPE_APPLY_ERROR
Definition: newclient.h:516
void register_process(int ob_type, process_func method)
Definition: ob_types.c:88
uint16 animation_id
Definition: object.h:267
struct obj * inv
Definition: object.h:148
#define NDI_UNIQUE
Definition: newclient.h:219
void query_name(const object *op, char *buf, size_t size)
Definition: item.c:628
New_Face * face
Definition: object.h:183
void init_type_transport(void)
Definition: transport.c:41
unsigned find_face(const char *name, unsigned error)
Definition: image.c:324
static method_ret transport_type_process(ob_methods *context, object *op)
Definition: transport.c:258
uint8 type
Definition: object.h:189