Crossfire Server, Branch 1.12  R12190
shop_mat.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 shop_mat_type_move_on(ob_methods *context, object *trap, object *victim, object *originator);
00034 
00038 void init_type_shop_mat(void) {
00039     register_move_on(SHOP_MAT, shop_mat_type_move_on);
00040 }
00041 
00050 static method_ret shop_mat_type_move_on(ob_methods *context, object *trap, object *victim, object *originator) {
00051     int rv = 0;
00052     double opinion;
00053     object *tmp, *next;
00054 
00055     if (common_pre_ob_move_on(trap, victim, originator) == METHOD_ERROR)
00056         return METHOD_OK;
00057 
00058     SET_FLAG(victim, FLAG_NO_APPLY);   /* prevent loops */
00059 
00060     if (victim->type != PLAYER) {
00061         /* Remove all the unpaid objects that may be carried here.
00062          * This could be pets or monsters that are somehow in
00063          * the shop.
00064          */
00065         for (tmp = victim->inv; tmp; tmp = next) {
00066             next = tmp->below;
00067             if (QUERY_FLAG(tmp, FLAG_UNPAID)) {
00068                 int i = find_free_spot(tmp, victim->map, victim->x, victim->y, 1, 9);
00069                 remove_ob(tmp);
00070                 if (i == -1)
00071                     i = 0;
00072                 tmp->map = victim->map;
00073                 tmp->x = victim->x+freearr_x[i];
00074                 tmp->y = victim->y+freearr_y[i];
00075                 insert_ob_in_map(tmp, victim->map, victim, 0);
00076             }
00077         }
00078 
00079         /* Don't teleport things like spell effects */
00080         if (QUERY_FLAG(victim, FLAG_NO_PICK))
00081             goto leave;
00082 
00083         /* unpaid objects, or non living objects, can't transfer by
00084          * shop mats.  Instead, put it on a nearby space.
00085          */
00086         if (QUERY_FLAG(victim, FLAG_UNPAID) || !QUERY_FLAG(victim, FLAG_ALIVE)) {
00087             /* Somebody dropped an unpaid item, just move to an adjacent place. */
00088             int i = find_free_spot(victim, victim->map, victim->x, victim->y, 1, 9);
00089             if (i != -1) {
00090                 rv = transfer_ob(victim, victim->x+freearr_x[i], victim->y+freearr_y[i], 0, trap);
00091             }
00092             goto leave;
00093         }
00094         rv = teleport(trap, SHOP_MAT, victim);
00095     /* immediate block below is only used for players */
00096     } else if (can_pay(victim)) {
00097         get_payment(victim, victim->inv);
00098         rv = teleport(trap, SHOP_MAT, victim);
00099         if (trap->msg) {
00100             draw_ext_info(NDI_UNIQUE, 0, victim, MSG_TYPE_APPLY, MSG_TYPE_APPLY_SUCCESS,
00101                 trap->msg, NULL);
00102         }
00103         /* This check below is a bit simplistic - generally it should be correct,
00104          * but there is never a guarantee that the bottom space on the map is
00105          * actually the shop floor.
00106          */
00107         else if (!rv && !is_in_shop(victim)) {
00108             opinion = shopkeeper_approval(victim->map, victim);
00109             if (opinion > 0.9)
00110                 draw_ext_info(NDI_UNIQUE, 0, victim, MSG_TYPE_SHOP, MSG_TYPE_SHOP_MISC,
00111                     "The shopkeeper gives you a friendly wave.", NULL);
00112             else if (opinion > 0.75)
00113                 draw_ext_info(NDI_UNIQUE, 0, victim, MSG_TYPE_SHOP, MSG_TYPE_SHOP_MISC,
00114                     "The shopkeeper waves to you.", NULL);
00115             else if (opinion > 0.5)
00116                 draw_ext_info(NDI_UNIQUE, 0, victim, MSG_TYPE_SHOP, MSG_TYPE_SHOP_MISC,
00117                     "The shopkeeper ignores you.", NULL);
00118             else
00119                 draw_ext_info(NDI_UNIQUE, 0, victim, MSG_TYPE_SHOP, MSG_TYPE_SHOP_MISC,
00120                     "The shopkeeper glares at you with contempt.", NULL);
00121         }
00122     } else {
00123         /* if we get here, a player tried to leave a shop but was not able
00124          * to afford the items he has.  We try to move the player so that
00125          * they are not on the mat anymore
00126          */
00127         int i = find_free_spot(victim, victim->map, victim->x, victim->y, 1, 9);
00128         if (i == -1)
00129             LOG(llevError, "Internal shop-mat problem.\n");
00130         else {
00131             remove_ob(victim);
00132             victim->x += freearr_x[i];
00133             victim->y += freearr_y[i];
00134             rv = insert_ob_in_map(victim, victim->map, trap, 0) == NULL;
00135             esrv_map_scroll(&victim->contr->socket, freearr_x[i], freearr_y[i]);
00136             victim->contr->socket.update_look = 1;
00137             victim->contr->socket.look_position = 0;
00138         }
00139     }
00140     CLEAR_FLAG(victim, FLAG_NO_APPLY);
00141 leave:
00142     common_post_ob_move_on(trap, victim, originator);
00143     return METHOD_OK;
00144 }