Atrinik Server 2.5
types/player_mover.c
Go to the documentation of this file.
00001 /************************************************************************
00002 *            Atrinik, a Multiplayer Online Role Playing Game            *
00003 *                                                                       *
00004 *    Copyright (C) 2009-2011 Alex Tokar and Atrinik Development Team    *
00005 *                                                                       *
00006 * Fork from Daimonin (Massive Multiplayer Online Role Playing Game)     *
00007 * and Crossfire (Multiplayer game for X-windows).                       *
00008 *                                                                       *
00009 * This program is free software; you can redistribute it and/or modify  *
00010 * it under the terms of the GNU General Public License as published by  *
00011 * the Free Software Foundation; either version 2 of the License, or     *
00012 * (at your option) any later version.                                   *
00013 *                                                                       *
00014 * This program is distributed in the hope that it will be useful,       *
00015 * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00016 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
00017 * GNU General Public License for more details.                          *
00018 *                                                                       *
00019 * You should have received a copy of the GNU General Public License     *
00020 * along with this program; if not, write to the Free Software           *
00021 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.             *
00022 *                                                                       *
00023 * The author can be reached at admin@atrinik.org                        *
00024 ************************************************************************/
00025 
00030 #include <global.h>
00031 
00036 void move_player_mover(object *op)
00037 {
00038     object *victim, *victim_next;
00039     mapstruct *mt;
00040     int xt, yt, dir = op->direction;
00041 
00042     op->value = pticks;
00043 
00044     if (!(blocked(NULL, op->map, op->x, op->y, TERRAIN_NOTHING) & (P_IS_ALIVE | P_IS_PLAYER)))
00045     {
00046         return;
00047     }
00048 
00049     /* Determine direction now for random movers so we do the right thing. */
00050     if (!dir)
00051     {
00052         dir = get_random_dir();
00053     }
00054 
00055     for (victim = GET_BOTTOM_MAP_OB(op); victim; victim = victim_next)
00056     {
00057         victim_next = victim->above;
00058 
00059         if (IS_LIVE(victim) && (!(QUERY_FLAG(victim, FLAG_FLYING)) || op->stats.maxhp))
00060         {
00061             if (QUERY_FLAG(op, FLAG_LIFESAVE) && op->stats.hp-- < 0)
00062             {
00063                 destruct_ob(op);
00064                 return;
00065             }
00066 
00067             /* No direction, this means 'xrays 1' was set; so use the
00068              * victim's direction instead. */
00069             if (!op->direction && QUERY_FLAG(op, FLAG_XRAYS))
00070             {
00071                 dir = victim->direction;
00072             }
00073 
00074             xt = op->x + freearr_x[dir];
00075             yt = op->y + freearr_y[dir];
00076 
00077             if (!(mt = get_map_from_coord(op->map, &xt, &yt)))
00078             {
00079                 return;
00080             }
00081 
00082             /* Flag to stop moving if there's a wall. */
00083             if (QUERY_FLAG(op, FLAG_STAND_STILL) && blocked(victim, mt, xt, yt, victim->terrain_flag))
00084             {
00085                 continue;
00086             }
00087 
00088             /* Unless there is an alive object or a player on the square
00089              * this object is being moved onto, disable the mover on that
00090              * square, if any. This is done so the object doesn't rocket
00091              * across a bunch of movers. */
00092             if (!(blocked(NULL, mt, xt, yt, TERRAIN_NOTHING) & (P_IS_ALIVE | P_IS_PLAYER)))
00093             {
00094                 object *nextmover;
00095 
00096                 for (nextmover = GET_MAP_OB(mt, xt, yt); nextmover; nextmover = nextmover->above)
00097                 {
00098                     /* Only disable movers that didn't go this tick yet;
00099                      * otherwise they wouldn't trigger on the next tick to
00100                      * move objects they may have on top of them. */
00101                     if (nextmover->type == PLAYERMOVER && nextmover->value != op->value)
00102                     {
00103                         nextmover->speed_left--;
00104                     }
00105                 }
00106             }
00107 
00108             if (victim->type == PLAYER)
00109             {
00110                 /* only level >=1 movers move people */
00111                 if (op->level)
00112                 {
00113                     /* Following is a bit of hack.  We need to make sure it
00114                      * is cleared, otherwise the player will get stuck in
00115                      * place. This can happen if the player used a spell to
00116                      * get to this space. */
00117                     CONTR(victim)->fire_on = 0;
00118                     victim->speed_left = -FABS(victim->speed);
00119                     move_player(victim, dir);
00120                     /* Clear player's path; they probably can't move there
00121                      * any more after being pushed, or might not want to. */
00122                     player_path_clear(CONTR(victim));
00123                 }
00124                 else
00125                 {
00126                     continue;
00127                 }
00128             }
00129             else if (op->stats.grace)
00130             {
00131                 move_object(victim, dir);
00132             }
00133             else
00134             {
00135                 continue;
00136             }
00137 
00138             if (!op->stats.maxsp && op->stats.sp)
00139             {
00140                 op->stats.maxsp = 2;
00141             }
00142 
00143             /* flag to paralyze the player */
00144             if (op->stats.sp)
00145             {
00146                 victim->speed_left = -(op->stats.maxsp * FABS(victim->speed));
00147             }
00148         }
00149     }
00150 }