Crossfire Server, Branch 1.12  R12190
exit.c
Go to the documentation of this file.
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 
00027 #include <global.h>
00028 #include <ob_methods.h>
00029 #include <ob_types.h>
00030 #include <sounds.h>
00031 #include <sproto.h>
00032 
00033 static method_ret exit_type_move_on(ob_methods *context, object *trap, object *victim, object *originator);
00034 static method_ret exit_type_apply(ob_methods *context, object *exit, object *op, int autoapply);
00035 
00039 void init_type_exit(void) {
00040     register_move_on(EXIT, exit_type_move_on);
00041     register_apply(EXIT, exit_type_apply);
00042 }
00043 
00052 static method_ret exit_type_move_on(ob_methods *context, object *trap, object *victim, object *originator) {
00053     if (common_pre_ob_move_on(trap, victim, originator) == METHOD_ERROR)
00054         return METHOD_OK;
00055     if (victim->type == PLAYER && EXIT_PATH(trap)) {
00056         /* Basically, don't show exits leading to random maps the
00057          * players output.
00058          */
00059         if (trap->msg
00060         && strncmp(EXIT_PATH(trap), "/!", 2)
00061         && strncmp(EXIT_PATH(trap), "/random/", 8))
00062             draw_ext_info(NDI_NAVY, 0, victim, MSG_TYPE_APPLY, MSG_TYPE_APPLY_TRAP, trap->msg, NULL);
00063         enter_exit(victim, trap);
00064     }
00065     common_post_ob_move_on(trap, victim, originator);
00066     return METHOD_OK;
00067 }
00068 
00090 static int is_legal_2ways_exit(object *op, object *exit) {
00091     object *tmp;
00092     object *exit_owner;
00093     player *pp;
00094     mapstruct *exitmap;
00095 
00096     if (exit->stats.exp != 1)
00097         return 1; /*This is not a 2 way, so it is legal*/
00098     if (!has_been_loaded(EXIT_PATH(exit)) && exit->race)
00099         return 0; /* This is a reset town portal */
00100     /* To know if an exit has a correspondant, we look at
00101      * all the exits in destination and try to find one with same path as
00102      * the current exit's position */
00103     if (!strncmp(EXIT_PATH(exit), settings.localdir, strlen(settings.localdir)))
00104         exitmap = ready_map_name(EXIT_PATH(exit), MAP_PLAYER_UNIQUE);
00105     else
00106         exitmap = ready_map_name(EXIT_PATH(exit), 0);
00107     if (exitmap) {
00108         tmp = GET_MAP_OB(exitmap, EXIT_X(exit), EXIT_Y(exit));
00109         if (!tmp)
00110             return 0;
00111         for ((tmp = GET_MAP_OB(exitmap, EXIT_X(exit), EXIT_Y(exit))); tmp; tmp = tmp->above) {
00112             if (tmp->type != EXIT)
00113                 continue;  /*Not an exit*/
00114             if (!EXIT_PATH(tmp))
00115                 continue; /*Not a valid exit*/
00116             if ((EXIT_X(tmp) != exit->x) || (EXIT_Y(tmp) != exit->y))
00117                 continue; /*Not in the same place*/
00118             if (strcmp(exit->map->path, EXIT_PATH(tmp)) != 0)
00119                 continue; /*Not in the same map*/
00120 
00121             /* From here we have found the exit is valid. However
00122              * we do here the check of the exit owner. It is important
00123              * for the town portals to prevent strangers from visiting
00124              * your apartments
00125              */
00126             if (!exit->race)
00127                 return 1;  /*No owner, free for all!*/
00128             exit_owner = NULL;
00129             for (pp = first_player; pp; pp = pp->next) {
00130                 if (!pp->ob)
00131                     continue;
00132                 if (pp->ob->name != exit->race)
00133                     continue;
00134                 exit_owner = pp->ob; /*We found a player which correspond to the player name*/
00135                 break;
00136             }
00137             if (!exit_owner)
00138                 return 0;    /* No more owner*/
00139             if (exit_owner->contr == op->contr)
00140                 return 1;  /*It is your exit*/
00141             if (exit_owner    /*There is a owner*/
00142             && (op->contr)    /*A player tries to pass */
00143             && ((exit_owner->contr->party == NULL) /*No pass if controller has no party*/
00144                 || (exit_owner->contr->party != op->contr->party))) /* Or not the same as op*/
00145                 return 0;
00146             return 1;
00147         }
00148     }
00149     return 0;
00150 }
00151 
00160 static method_ret exit_type_apply(ob_methods *context, object *exit, object *op, int autoapply) {
00161     if (op->type != PLAYER)
00162         return METHOD_ERROR;
00163     if (!EXIT_PATH(exit) || !is_legal_2ways_exit(op, exit)) {
00164         char name[MAX_BUF];
00165 
00166         query_name(exit, name, MAX_BUF);
00167         draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_APPLY, MSG_TYPE_APPLY_FAILURE,
00168                              "The %s is closed.", "The %s is closed.", name);
00169     } else {
00170         /* Don't display messages for random maps. */
00171         if (exit->msg
00172         && strncmp(EXIT_PATH(exit), "/!", 2)
00173         && strncmp(EXIT_PATH(exit), "/random/", 8))
00174             draw_ext_info(NDI_NAVY, 0, op, MSG_TYPE_APPLY, MSG_TYPE_APPLY_SUCCESS, exit->msg, NULL);
00175         enter_exit(op, exit);
00176     }
00177     return METHOD_OK;
00178 }