Difference for server/player.c from version 1.63 to 1.64


version 1.63 version 1.64
Line 1
 
Line 1
 /*  /*
  * static char *rcsid_player_c =   * static char *rcsid_player_c =
  *   "$Id: player.c,v 1.63 2001/07/14 04:11:18 mwedel Exp $";   *   "$Id: player.c,v 1.64 2001/08/21 05:39:30 mwedel Exp $";
  */   */
   
 /*  /*
Line 235
 
Line 235
   object *op = NULL;    object *op = NULL;
   player *pl = NULL;    player *pl = NULL;
   objectlink *ol;    objectlink *ol;
   int lastdist,tmp;      int lastdist;
       rv_vector rv;
   
   for(ol=first_friendly_object,lastdist=1000;ol!=NULL;ol=ol->next) {    for(ol=first_friendly_object,lastdist=1000;ol!=NULL;ol=ol->next) {
     /* We shoult not find free objects on this friendly list, but it   /* We should not find free objects on this friendly list, but it
      * does periodically happen.  Given that, lets deal with it.       * does periodically happen.  Given that, lets deal with it.
      * While unlikely, it is possible the next object on the friendly       * While unlikely, it is possible the next object on the friendly
      * list is also free, so encapsulate this in a while loop.       * list is also free, so encapsulate this in a while loop.
Line 260
 
Line 261
      * complicated method of state checking would be needed in any case -       * complicated method of state checking would be needed in any case -
      * as it was, a clever player could type quit, and the function would         * as it was, a clever player could type quit, and the function would 
      * skip them over while waiting for confirmation.       * skip them over while waiting for confirmation.
    * put checks in for
      */       */
     if(!can_detect_enemy(mon,ol->ob)||ol->ob->map!=mon->map)   if (!on_same_map(mon,ol->ob) || !can_detect_enemy(mon,ol->ob,&rv))
       continue;        continue;
     tmp=distance(ol->ob,mon);  
     if(lastdist>tmp) {   if(lastdist>rv.distance) {
       op=ol->ob;        op=ol->ob;
       lastdist=tmp;       lastdist=rv.distance;
     }      }
   }    }
   for (pl=first_player; pl != NULL; pl=pl->next) {    for (pl=first_player; pl != NULL; pl=pl->next) {
     if (pl->ob->map == mon->map && can_detect_enemy(mon, pl->ob)) {   if (on_same_map(mon, pl->ob)&& can_detect_enemy(mon, pl->ob,&rv)) {
  tmp=distance(pl->ob,mon);  
  if(lastdist>tmp) {       if(lastdist>rv.distance) {
      op=pl->ob;       op=pl->ob;
      lastdist=tmp;   lastdist=rv.distance;
  }   }
     }      }
   }    }
Line 284
 
Line 286
   return op;    return op;
 }  }
   
   /* I believe this can safely go to 2, 3 is questionable, 4 will likely
    * result in a monster paths backtracking.  It basically determines how large a
    * detour a monster will take from the direction path when looking
    * for a path to the player.  The values are in the amount of direction
    * the deviation is
    */
   #define DETOUR_AMOUNT 2
   
   /* This is used to prevent infinite loops.  Consider a case where the
    * player is in a chamber (with gate closed), and monsters are outside.
    * with DETOUR_AMOUNT==2, the function will turn each corner, trying to
    * find a path into the chamber.  This is a good thing, but since there
    * is no real path, it will just keep circling the chamber for
    * ever (this could be a nice effect for monsters, but not for the function
    * to get stuck in.  I think for the monsters, if max is reached and
    * we return the first direction the creature could move would result in the
    * circling behaviour.  Unfortunately, this function is also used to determined
    * if the creature should cast a spell, so returning a direction in that case
    * is probably not a good thing.
    */
   #define MAX_SPACES 50
   
   
 /*  /*
  * Returns the direction to the player, if valid.  Returns 0 otherwise.   * Returns the direction to the player, if valid.  Returns 0 otherwise.
  * modified to verify there is a path to the player.  Does this by stepping towards   * modified to verify there is a path to the player.  Does this by stepping towards
Line 292
 
Line 317
  * reach player or path is blocked.  Thus, will only return true if there is a free   * reach player or path is blocked.  Thus, will only return true if there is a free
  * path to player.  Though path may not be a straight line.  Note that it will find   * path to player.  Though path may not be a straight line.  Note that it will find
  * player hiding along a corridor at right angles to the corridor with the monster.   * player hiding along a corridor at right angles to the corridor with the monster.
    *
    * Modified by MSW 2001-08-06 to handle tiled maps. Various notes:
    * 1) With DETOUR_AMOUNT being 2, it should still go and find players hiding
    * down corriders. 
    * 2) I think the old code was broken if the first direction the monster
    * should move was blocked - the code would store the first direction without
    * verifying that the player can actually move in that direction.  The new
    * code does not store anything in firstdir until we have verified that the
    * monster can in fact move one space in that direction.
    * 3) I'm not sure how good this code will be for moving multipart monsters,
    * since only simple checks to blocked are being called, which could mean the monster
    * is blocking itself.
  */   */
 int path_to_player(object *mon, object *pl,int mindiff) {  int path_to_player(object *mon, object *pl,int mindiff) {
   int dir,x,y,diff;      rv_vector rv;
   int oldx,oldy,olddir,newdir;      int x,y,lastx,lasty,dir,i,diff, firstdir=0,lastdir, max=MAX_SPACES;
       mapstruct *m ,*lastmap;
   x=mon->x, y=mon->y;  
   dir=find_dir_2(x-pl->x,y-pl->y);      get_rangevector(mon, pl, &rv, 0);
       if (rv.distance<mindiff) return 0;
   /* diff is how many steps from monster to player */  
   diff= abs(x-pl->x) > abs(y-pl->y) ? abs(x-pl->x) : abs(y-pl->y);      x=mon->x;
   if(diff<mindiff) return 0;      y=mon->y;
       m=mon->map;
   newdir = olddir = dir;      dir = rv.direction;
   oldx = x, oldy=y;      lastdir = rv.direction;
       diff = FABS(rv.distance_x)>FABS(rv.distance_y)?FABS(rv.distance_x):FABS(rv.distance_y);
   while( diff>1 ) {      /* If we can't solve it within the search distance, return now. */
     for( ; diff>1; diff--) {      if (diff>max) return 0;
       oldx=x, oldy=y;      while (diff >1 && max>0) {
       x+=freearr_x[newdir],y+=freearr_y[newdir];   lastx = x;
       if(blocked(mon->map,x,y)){   lasty = y;
         if (olddir == (newdir=find_dir_2(oldx-pl->x, oldy-pl->y))){   lastmap = m;
           if ( (newdir%2) == 0)   x = lastx + freearr_x[dir];
             return 0;   y = lasty + freearr_y[dir];
             /* if heading straight then try diag step towards player.  needed to find  
              * player in a L position compared to monster along corridors.  the 2* and   m = get_map_from_coord(m, &x, &y);
  * RANDOM are to go around a block and find the player behind. */   /* Space is blocked - try changing direction a little */
           if ((newdir==1) || (newdir==5)) {   if (blocked(m, x, y) && (m == mon->map && blocked_link(mon, x, y))) {
             ( (2*x) > (2*(pl->x+RANDOM()%2)-1) ) ? x-- : x++;       /* recalculate direction from last good location.  Possible
           } else if((newdir==3) || (newdir==7)) {        * we were not traversing ideal location before.
             ( (2*y) > (2*(pl->y+RANDOM()%2)-1) ) ? y-- : y++;        */
           }       get_rangevector_from_mapcoord(lastmap, lastx, lasty, pl, &rv, 0);
           if(blocked(mon->map,x,y))         if (rv.direction != dir) {
             return 0;        /* path blocked to player */   /* OK - says direction should be different - lets reset the
           diff = abs(x-pl->x) > abs(y-pl->y) ? abs(x-pl->x) : abs(y-pl->y);   * the values so it will try again.
         } else {        /*have a new direction to try */   */
           olddir = newdir, x=oldx, y=oldy;   x = lastx;
           diff = abs(oldx-pl->x) > abs(oldy-pl->y) ? abs(oldx-pl->x) : abs(oldy-pl->y);   y = lasty;
         }   m = lastmap;
       }   dir = rv.direction;
     }       } else {
     /* diff may have headed us all the way down that direction, but not next to the player   /* direct path is blocked - try taking a side step to
      * so head towards player.  If next to player then will exit while loop */   * either the left or right.
     newdir=find_dir_2(x-pl->x, y-pl->y);   * Note increase the values in the loop below to be
     diff = abs(x-pl->x) > abs(y-pl->y) ? abs(x-pl->x) : abs(y-pl->y);   * more than -1/1 respectively will mean the monster takes
   }   * bigger detour.  Have to be careful about these values getting
   return dir;   * too big (3 or maybe 4 or higher) as the monster may just try
    * stepping back and forth
    */
    for (i=-DETOUR_AMOUNT; i<=DETOUR_AMOUNT; i++) {
        if (i==0) continue; /* already did this, so skip it */
        /* Use lastdir here - otherwise,
         * since the direction that the creature should move in
         * may change, you could get infinite loops.
         * ie, player is northwest, but monster can only
         * move west, so it does that.  It goes some distance,
         * gets blocked, finds that it should move north,
         * can't do that, but now finds it can move east, and
         * gets back to its original point.  lastdir contains
         * the last direction the creature has successfully
         * moved.
         */
       
        x = lastx + freearr_x[absdir(lastdir+i)];
        y = lasty + freearr_y[absdir(lastdir+i)];
        m = lastmap;
        if (!out_of_map(m, x, y)) {
    m = get_map_from_coord(m, &x, &y);
    if (!blocked(m, x, y) && (m == mon->map && blocked_link(mon, x, y))) break;
        }
    }
    /* go through entire loop without finding a valid
    * sidestep to take - thus, no valid path.
    */
    if (i==(DETOUR_AMOUNT+1))
        return 0;
    diff--;
    lastdir=dir;
    max--;
    if (!firstdir) firstdir = dir+i;
        } /* else check alternate directions */
    } /* if blocked */
    else {
        /* we moved towards creature, so diff is less */
        diff--;
        max--;
        lastdir=dir;
        if (!firstdir) firstdir = dir;
    }
    if (diff<=1) {
        /* Recalculate diff (distance) because we may not have actually
         * headed toward player for entire distance.
         */
        get_rangevector_from_mapcoord(m, x, y, pl, &rv, 0);
        diff = FABS(rv.distance_x)>FABS(rv.distance_y)?FABS(rv.distance_x):FABS(rv.distance_y);
    }
    if (diff>max) return 0;
       }
       /* If we reached the max, didn't find a direction in time */
       if (!max) return 0;
       return firstdir;
 }  }
   
 void give_initial_items(object *pl,treasurelist *items) {  void give_initial_items(object *pl,treasurelist *items) {
Line 1211
 
Line 1302
     return tmp;      return tmp;
 }  }
   
   /* moved door processing out of move_player_attack.
    * returns 1 if player has opened the door with a key
    * such that the caller should not do anything more,
    * 0 otherwise
    */
   static int player_attack_door(object *op, object *door)
   {
   
       /* If its a door, try to find a use a key.  If we do destroy the door,
        * might as well return immediately as there is nothing more to do -
        * otherwise, we fall through to the rest of the code.
        */
       object *key=find_key(op, op, door);
   
       /* IF we found a key, do some extra work */
       if (key) {
    object *container=key->env;
   
    play_sound_map(op->map, op->x, op->y, SOUND_OPEN_DOOR);
    if(action_makes_visible(op)) make_visible(op);
    if(door->inv && door->inv->type ==RUNE) spring_trap(door->inv,op);
    if (door->type == DOOR) {
        hit_player(door,9999,op,AT_PHYSICAL); /* Break through the door */
    }
    else if(door->type==LOCKED_DOOR) {
        new_draw_info_format(NDI_UNIQUE, NDI_BROWN, op,
         "You open the door with the %s", query_short_name(key));
        remove_door2(door); /* remove door without violence ;-) */
    }
    /* Do this after we print the message */
    decrease_ob(key); /* Use up one of the keys */
    /* Need to update the weight the container the key was in */
    if (container != op)
        esrv_update_item(UPD_WEIGHT, op, container);
    return 1; /* Nothing more to do below */
       } else if (door->type==LOCKED_DOOR) {
    /* Might as well return now - no other way to open this */
    new_draw_info(NDI_UNIQUE | NDI_NAVY, 0, op, door->msg);
    return 1;
       }
       return 0;
   }
   
 /* This function is just part of a breakup from move_player.  /* This function is just part of a breakup from move_player.
  * It should keep the code cleaner.   * It should keep the code cleaner.
  * When this is called, the players direction has been updated   * When this is called, the players direction has been updated
Line 1222
 
Line 1356
 {  {
   object *tmp;    object *tmp;
   int nx=freearr_x[dir]+op->x,ny=freearr_y[dir]+op->y;    int nx=freearr_x[dir]+op->x,ny=freearr_y[dir]+op->y;
       mapstruct *m;
   
   /* If braced, or can't move to the square, and it is not out of the    /* If braced, or can't move to the square, and it is not out of the
    * map, attack it.  Note order of if statement is important - don't     * map, attack it.  Note order of if statement is important - don't
Line 1233
 
Line 1367
    * quite a bit of processing.  However, it probably is less than what     * quite a bit of processing.  However, it probably is less than what
    * move_ob uses.     * move_ob uses.
    */     */
   if ((op->contr->braced || !move_ob(op,dir,op)) &&      if ((op->contr->braced || !move_ob(op,dir,op)) && !out_of_map(op->map,nx,ny)) {
     !out_of_map(op->map,nx,ny)) {   if (OUT_OF_REAL_MAP(op->map, nx, ny))
        m = get_map_from_coord(op->map, &nx, &ny);
    else m =op->map;
          
    if ((tmp=get_map_ob(m,nx,ny))==NULL) {
     if ((tmp=get_map_ob(op->map,nx,ny))==NULL) {  
 /* LOG(llevError,"player_move_attack: get_map_ob returns NULL, but player can not more there.\n");*/  /* LOG(llevError,"player_move_attack: get_map_ob returns NULL, but player can not more there.\n");*/
  return;   return;
     }      }
Line 1256
 
Line 1391
     if(tmp->head != NULL)      if(tmp->head != NULL)
       tmp = tmp->head;        tmp = tmp->head;
   
     /* If its a door, try to find a use a key.  If we do destroy the door,   if ((tmp->type==DOOR && tmp->stats.hp>=0) || (tmp->type==LOCKED_DOOR))
      * might as well return immediately as there is nothing more to do -       if (player_attack_door(op, tmp)) return;
      * otherwise, we fall through to the rest of the code.  
      */  
     if ((tmp->type==DOOR && tmp->stats.hp>=0) || (tmp->type==LOCKED_DOOR)) {  
  object *key=find_key(op, op, tmp);  
   
  /* IF we found a key, do some extra work */  
  if (key) {  
      object *container=key->env;  
   
      play_sound_map(op->map, op->x, op->y, SOUND_OPEN_DOOR);  
      if(action_makes_visible(op)) make_visible(op);  
      if(tmp->inv && tmp->inv->type ==RUNE) spring_trap(tmp->inv,op);  
      if (tmp->type == DOOR) {  
  hit_player(tmp,9999,op,AT_PHYSICAL); /* Break through the door */  
      }  
      else if(tmp->type==LOCKED_DOOR) {  
  new_draw_info_format(NDI_UNIQUE, NDI_BROWN, op,   
       "You open the door with the %s", query_short_name(key));  
  remove_door2(tmp); /* remove door without violence ;-) */  
      }  
      /* Do this after we print the message */  
      decrease_ob(key); /* Use up one of the keys */  
      /* Need to update the weight the container the key was in */  
      if (container != op)   
  esrv_update_item(UPD_WEIGHT, op, container);  
      return; /* Nothing more to do below */  
  } else if (tmp->type==LOCKED_DOOR) {  
      /* Might as well return now - no other way to open this */  
      new_draw_info(NDI_UNIQUE | NDI_NAVY, 0, op, tmp->msg);  
      return;  
  }  
     }  
   
     /* The following deals with possibly attacking peaceful      /* The following deals with possibly attacking peaceful
      * or frienddly creatures.  Basically, all players are considered       * or frienddly creatures.  Basically, all players are considered
Line 1329
 
Line 1432
       else if(QUERY_FLAG(tmp,FLAG_CAN_ROLL)&&(!op->contr->braced)) {        else if(QUERY_FLAG(tmp,FLAG_CAN_ROLL)&&(!op->contr->braced)) {
    recursive_roll(tmp,dir,op);     recursive_roll(tmp,dir,op);
           if(action_makes_visible(op)) make_visible(op);            if(action_makes_visible(op)) make_visible(op);
   
       }        }
   
       /* Any generic living creature.  Including things like doors.        /* Any generic living creature.  Including things like doors.
Line 1339
 
Line 1441
        * that party_number -1 is no party, so attacks can still happen.         * that party_number -1 is no party, so attacks can still happen.
        */         */
   
       else   else if ((tmp->stats.hp>=0) && QUERY_FLAG(tmp, FLAG_ALIVE) &&
  if ((tmp->stats.hp>=0) && QUERY_FLAG(tmp, FLAG_ALIVE) &&  
  ((tmp->type!=PLAYER || op->contr->party_number==-1 ||   ((tmp->type!=PLAYER || op->contr->party_number==-1 ||
  op->contr->party_number!=tmp->contr->party_number))) {   op->contr->party_number!=tmp->contr->party_number))) {
   
Line 1350
 
Line 1451
    /* If attacking another player, that player gets automatic     /* If attacking another player, that player gets automatic
     * hitback, and doesn't loose luck either.      * hitback, and doesn't loose luck either.
     */      */
    if (tmp->type == PLAYER && tmp->stats.hp >= 0 &&       if (tmp->type == PLAYER && tmp->stats.hp >= 0 && !tmp->contr->has_hit) {
       !tmp->contr->has_hit)  
    {  
      short luck = tmp->stats.luck;       short luck = tmp->stats.luck;
      tmp->contr->has_hit = 1;       tmp->contr->has_hit = 1;
      skill_attack(op, tmp, 0, NULL);       skill_attack(op, tmp, 0, NULL);
Line 1360
 
Line 1459
    }     }
    if(action_makes_visible(op)) make_visible(op);     if(action_makes_visible(op)) make_visible(op);
  }   }
     }      } /* if player should attack something */
 }  }
   
 int move_player(object *op,int dir) {  int move_player(object *op,int dir) {
Line 2200
 
Line 2299
  * our backs...on the other hand, does the "facing" direction   * our backs...on the other hand, does the "facing" direction
  * imply the way your head, or body is facing? Its possible   * imply the way your head, or body is facing? Its possible
  * for them to differ. Sigh, this fctn could get a bit more complex.   * for them to differ. Sigh, this fctn could get a bit more complex.
  * -b.t. */   * -b.t.
    * This function is now map tiling safe.
    */
   
 int player_can_view (object *pl,object *op) {  int player_can_view (object *pl,object *op) {
       rv_vector rv;
       int dx,dy;
   
   if(pl->type!=PLAYER) {    if(pl->type!=PLAYER) {
     LOG(llevError,"player_can_view() called for non-player object\n");      LOG(llevError,"player_can_view() called for non-player object\n");
     return -1;      return -1;
   }    }
       if (!pl || !op) return 0;
   
       if(op->head) { op = op->head; }
       get_rangevector(pl, op, &rv, 0x1);
   
   if(pl&&op&&pl->map==op->map) {   
     /* starting with the 'head' part, lets loop      /* starting with the 'head' part, lets loop
      * through the object and find if it has any       * through the object and find if it has any
      * part that is in the los array but isnt on        * part that is in the los array but isnt on
      * a blocked los square. */       * a blocked los square.
     if(op->head) { op = op->head; }       * we use the archetype to figure out offsets.
        */
     while(op) {      while(op) {
       if(pl->y - MAP_CLIENT_Y/2 <= op->y &&    dx = rv.distance_x + op->arch->clone.x;
  pl->y + MAP_CLIENT_Y/2 >= op->y &&   dy = rv.distance_y + op->arch->clone.y;
          pl->x - MAP_CLIENT_X/2 <= op->x &&   
  pl->x + MAP_CLIENT_X/2 >= op->x &&   /* only the viewable area the player sees is updated by LOS
  !pl->contr->blocked_los[op->x-pl->x+MAP_CLIENT_X/2][op->y-pl->y+MAP_CLIENT_Y/2] )    * code, so we need to restrict ourselves to that range of values
    * for any meaningful values.
    */
    if (FABS(dx) <= (pl->contr->socket.mapx/2) &&
        FABS(dy) <= (pl->contr->socket.mapy/2) &&
        !pl->contr->blocked_los[dx + (pl->contr->socket.mapx/2)][dy+(pl->contr->socket.mapy/2)] )
         return 1;          return 1;
       op = op->more;        op = op->more;
     }      }
   }  
   return 0;    return 0;
 }  }
   


Legend:
line(s) removed in v.1.63 
line(s) changed
 line(s) added in v.1.64

File made using version 1.98 of cvs2html by leaf at 2011-07-21 17:41