Crossfire Server, Branch 1.12
R12190
|
00001 /* 00002 CrossFire, A Multiplayer game for X-windows 00003 00004 Copyright (C) 2007 Mark Wedel & Crossfire Development Team 00005 Copyright (C) 1992 Frank Tore Johansen 00006 00007 This program is free software; you can redistribute it and/or modify 00008 it under the terms of the GNU General Public License as published by 00009 the Free Software Foundation; either version 2 of the License, or 00010 (at your option) any later version. 00011 00012 This program is distributed in the hope that it will be useful, 00013 but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00015 GNU General Public License for more details. 00016 00017 You should have received a copy of the GNU General Public License 00018 along with this program; if not, write to the Free Software 00019 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 00020 00021 The authors can be reached via e-mail at crossfire-devel@real-time.com 00022 */ 00023 00029 #include <global.h> 00030 #include <ob_methods.h> 00031 #include <ob_types.h> 00032 #include <sounds.h> 00033 #include <sproto.h> 00034 00035 static method_ret transport_type_apply(ob_methods *context, object *op, object *applier, int aflags); 00036 static method_ret transport_type_process(ob_methods *context, object *op); 00037 00041 void init_type_transport(void) { 00042 register_apply(TRANSPORT, transport_type_apply); 00043 register_process(TRANSPORT, transport_type_process); 00044 } 00045 00058 static method_ret transport_type_apply(ob_methods *context, object *op, object *applier, int aflags) { 00059 object *old_transport = applier->contr->transport; 00060 object *inv; 00061 char name_op[MAX_BUF], name_old[MAX_BUF]; 00062 00063 /* Only players can use transports right now */ 00064 if (applier->type != PLAYER) 00065 return 0; 00066 00067 query_name(op, name_op, MAX_BUF); 00068 00069 /* If player is currently on a transport but not this transport, they need 00070 * to exit first. Perhaps transport to transport transfers should be 00071 * allowed. 00072 */ 00073 if (old_transport && old_transport != op) { 00074 query_name(old_transport, name_old, MAX_BUF); 00075 draw_ext_info_format(NDI_UNIQUE, 0, applier, MSG_TYPE_APPLY, MSG_TYPE_APPLY_ERROR, 00076 "You must exit %s before you can board %s.", 00077 "You must exit %s before you can board %s.", 00078 name_old, name_op); 00079 return 1; 00080 } 00081 00082 /* player is currently on a transport. This must mean he 00083 * wants to exit. 00084 */ 00085 if (old_transport) { 00086 /* Should we print a message if the player only wants to 00087 * apply? 00088 */ 00089 if (aflags&AP_APPLY) 00090 return 1; 00091 00092 query_name(old_transport, name_old, MAX_BUF); 00093 draw_ext_info_format(NDI_UNIQUE, 0, applier, MSG_TYPE_APPLY, MSG_TYPE_APPLY_UNAPPLY, 00094 "You disembark from %s.", "You disembark from %s.", 00095 name_old); 00096 remove_ob(applier); 00097 applier->map = old_transport->map; 00098 applier->x = old_transport->x; 00099 applier->y = old_transport->y; 00100 if (applier->contr == old_transport->contr) 00101 old_transport->contr = NULL; 00102 00103 applier->contr->transport = NULL; 00104 insert_ob_in_map(applier, applier->map, applier, 0); 00105 sum_weight(old_transport); 00106 00107 /* Possible for more than one player to be using a transport. 00108 * if that is the case, we don't want to reset the face, as the 00109 * transport is still occupied. 00110 */ 00111 for (inv = old_transport->inv; inv; inv = inv->below) 00112 if (inv->type == PLAYER) 00113 break; 00114 if (!inv) { 00115 old_transport->face = old_transport->arch->clone.face; 00116 old_transport->animation_id = old_transport->arch->clone.animation_id; 00117 } else { 00118 old_transport->contr = inv->contr; 00119 draw_ext_info_format(NDI_UNIQUE, 0, inv, MSG_TYPE_APPLY, MSG_TYPE_APPLY_SUCCESS, 00120 "%s has disembarked. You are now the captain of %s", 00121 "%s has disembarked. You are now the captain of %s", 00122 applier->name, name_old); 00123 } 00124 return 1; 00125 } else { 00126 /* player is trying to board a transport */ 00127 int pc = 0, p_limit; 00128 const char *kv; 00129 sint16 ox, oy; 00130 00131 if (aflags&AP_UNAPPLY) 00132 return 1; 00133 00134 /* Can this transport hold the weight of this player? */ 00135 if (!transport_can_hold(op, applier, 1)) { 00136 draw_ext_info_format(NDI_UNIQUE, 0, applier, MSG_TYPE_APPLY, MSG_TYPE_APPLY_ERROR, 00137 "The %s is unable to hold your weight!", 00138 "The %s is unable to hold your weight!", 00139 name_op); 00140 return 1; 00141 } 00142 00143 /* If the player is holding the transport, drop it. */ 00144 if (op->env == applier) { 00145 old_transport = op; 00146 /* Don't drop transports in shops. */ 00147 if (!is_in_shop(applier)) { 00148 op = drop_object(applier, op, 1); 00149 } else { 00150 draw_ext_info_format(NDI_UNIQUE, 0, applier, MSG_TYPE_APPLY, MSG_TYPE_APPLY_ERROR, 00151 "You cannot drop the %s in a shop to use it.", 00152 "You cannot drop the %s in a shop to use it.", 00153 name_old); 00154 return 1; 00155 } 00156 /* Did it fail to drop? */ 00157 if (!op) { 00158 draw_ext_info_format(NDI_UNIQUE, 0, applier, MSG_TYPE_APPLY, MSG_TYPE_APPLY_ERROR, 00159 "You need to drop the %s to use it.", 00160 "You need to drop the %s to use it.", 00161 name_old); 00162 return 1; 00163 } 00164 } 00165 00166 /* Does this transport have space for more players? */ 00167 for (inv = op->inv; inv; inv = inv->below) 00168 if (inv->type == PLAYER) 00169 pc++; 00170 00171 kv = get_ob_key_value(op, "passenger_limit"); 00172 if (!kv) 00173 p_limit = 1; 00174 else 00175 p_limit = atoi(kv); 00176 if (pc >= p_limit) { 00177 draw_ext_info_format(NDI_UNIQUE, 0, applier, MSG_TYPE_APPLY, MSG_TYPE_APPLY_ERROR, 00178 "The %s does not have space for any more people", 00179 "The %s does not have space for any more people", 00180 name_op); 00181 return 1; 00182 } 00183 00184 /* Everything checks out OK - player can get on the transport */ 00185 applier->contr->transport = op; 00186 00187 if (op->contr) { 00188 draw_ext_info_format(NDI_UNIQUE, 0, applier, MSG_TYPE_APPLY, MSG_TYPE_APPLY_SUCCESS, 00189 "The %s's captain is currently %s", 00190 "The %s's captain is currently %s", 00191 name_op, op->contr->ob->name); 00192 } else { 00193 draw_ext_info_format(NDI_UNIQUE, 0, applier, MSG_TYPE_APPLY, MSG_TYPE_APPLY_SUCCESS, 00194 "You're the %s's captain", 00195 "You're the %s's captain", 00196 name_op); 00197 op->contr = applier->contr; 00198 } 00199 00200 remove_ob(applier); 00201 /* insert_ob_in_ob clear applier->x and applier->y, so store them away */ 00202 ox = applier->x; 00203 oy = applier->y; 00204 insert_ob_in_ob(applier, op); 00205 sum_weight(op); 00206 applier->map = op->map; 00207 if (ox != op->x || oy != op->y) { 00208 esrv_map_scroll(&applier->contr->socket, (ox-op->x), (oy-op->y)); 00209 } 00210 applier->contr->socket.update_look = 1; 00211 applier->contr->socket.look_position = 0; 00212 applier->x = op->x; 00213 applier->y = op->y; 00214 00215 /* Might need to update face, animation info */ 00216 if (!pc) { 00217 const char *str; 00218 00219 str = get_ob_key_value(op, "face_full"); 00220 if (str) 00221 op->face = &new_faces[find_face(str, op->face->number)]; 00222 str = get_ob_key_value(op, "anim_full"); 00223 if (str) 00224 op->animation_id = find_animation(str); 00225 } 00226 00227 /* Does speed of this object change based on weight? */ 00228 kv = get_ob_key_value(op, "weight_speed_ratio"); 00229 if (kv) { 00230 int wsr = atoi(kv); 00231 float base_speed; 00232 00233 kv = get_ob_key_value(op, "base_speed"); 00234 if (kv) 00235 base_speed = atof(kv); 00236 else 00237 base_speed = op->arch->clone.speed; 00238 00239 op->speed = base_speed-(base_speed*op->carrying*wsr)/(op->weight_limit*100); 00240 00241 /* Put some limits on min/max speeds */ 00242 if (op->speed < 0.10) 00243 op->speed = 0.10; 00244 if (op->speed > 1.0) 00245 op->speed = 1.0; 00246 } 00247 } /* else if player is boarding the transport */ 00248 return 1; 00249 } 00250 00258 static method_ret transport_type_process(ob_methods *context, object *op) { 00259 /* Transports are directed by players - thus, there 00260 * speed is reduced when the player moves them about. 00261 * So give them back there speed here, since process_objects() 00262 * has decremented it. 00263 */ 00264 if (op->speed_left < 0.0) { 00265 op->speed_left += 1.0; 00266 return 1; 00267 } 00268 return 0; 00269 }