--- deliantra/server/socket/request.C 2008/04/22 07:01:47 1.126 +++ deliantra/server/socket/request.C 2008/12/19 22:47:30 1.141 @@ -1,7 +1,7 @@ /* * This file is part of Deliantra, the Roguelike Realtime MMORPG. * - * Copyright (©) 2005,2006,2007 Marc Alexander Lehmann / Robin Redeker / the Deliantra team + * Copyright (©) 2005,2006,2007,2008 Marc Alexander Lehmann / Robin Redeker / the Deliantra team * Copyright (©) 2001,2007 Mark Wedel * Copyright (©) 1992,2007 Frank Tore Johansen * @@ -143,6 +143,32 @@ pl->ns->floorbox_reset (); } +static void +send_map_info (player *pl) +{ + client &socket = *pl->ns; + object *ob = pl->observe; + + if (socket.mapinfocmd) + { + if (ob->map && ob->map->path[0]) + { + int flags = 0; + + if (ob->map->tile_path[0]) flags |= 1; + if (ob->map->tile_path[1]) flags |= 2; + if (ob->map->tile_path[2]) flags |= 4; + if (ob->map->tile_path[3]) flags |= 8; + + socket.send_packet_printf ("mapinfo - spatial %d %d %d %d %d %s", + flags, socket.mapx / 2 - ob->x, socket.mapy / 2 - ob->y, + ob->map->width, ob->map->height, &ob->map->path); + } + else + socket.send_packet ("mapinfo current"); + } +} + /** check for map/region change and send new map data */ static void check_map_change (player *pl) @@ -150,30 +176,39 @@ client &socket = *pl->ns; object *ob = pl->observe; - if (socket.current_map != ob->map || socket.force_newmap) + region *reg = ob->region (); + if (socket.current_region != reg) { - clear_map (pl); - socket.current_map = ob->map; + INVOKE_PLAYER (REGION_CHANGE, pl, ARG_REGION (reg), ARG_REGION (socket.current_region)); + socket.current_region = reg; + } + + // first try to aovid a full newmap on tiled map scrolls + if (socket.current_map != ob->map && !socket.force_newmap) + { + rv_vector rv; - if (socket.mapinfocmd) + get_rangevector_from_mapcoord (socket.current_map, socket.current_x, socket.current_y, ob, &rv, 0); + + // manhattan distance is very handy here + if (rv.distance < 8) // 8 works nicely for speed << 70 and buggy gcfclient { - if (ob->map && ob->map->path[0]) - { - int flags = 0; + socket.current_map = ob->map; + socket.current_x = ob->x; + socket.current_y = ob->y; - if (ob->map->tile_path[0]) flags |= 1; - if (ob->map->tile_path[1]) flags |= 2; - if (ob->map->tile_path[2]) flags |= 4; - if (ob->map->tile_path[3]) flags |= 8; - - socket.send_packet_printf ("mapinfo - spatial %d %d %d %d %d %s", - flags, socket.mapx / 2 - ob->x, socket.mapy / 2 - ob->y, - ob->map->width, ob->map->height, &ob->map->path); - } - else - socket.send_packet ("mapinfo current"); + socket_map_scroll (&socket, rv.distance_x, rv.distance_y); + socket.floorbox_reset (); + send_map_info (pl); } } + + if (socket.current_map != ob->map || socket.force_newmap) + { + clear_map (pl); + socket.current_map = ob->map; + send_map_info (pl); + } else if (socket.current_x != ob->x || socket.current_y != ob->y) { int dx = ob->x - socket.current_x; @@ -190,13 +225,6 @@ socket.current_x = ob->x; socket.current_y = ob->y; - - region *reg = ob->region (); - if (socket.current_region != reg) - { - INVOKE_PLAYER (REGION_CHANGE, pl, ARG_REGION (reg), ARG_REGION (socket.current_region)); - socket.current_region = reg; - } } /** @@ -688,30 +716,15 @@ void MoveCmd (char *buf, int len, player *pl) { - int vals[3], i; + int to, tag, nrof; - /* A little funky here. We only cycle for 2 records, because - * we obviously are not going to find a space after the third - * record. Perhaps we should just replace this with a - * sscanf? - */ - for (i = 0; i < 2; i++) + if (3 != sscanf (buf, "%d %d %d", &to, &tag, &nrof)) { - vals[i] = atoi (buf); - - if (!(buf = strchr (buf, ' '))) - { - LOG (llevError, "Incomplete move command: %s\n", buf); - return; - } - - buf++; + LOG (llevError, "Incomplete move command: %s\n", buf); + return; } - vals[2] = atoi (buf); - -/* LOG(llevDebug,"Move item %d (nrof=%d) to %d.\n", vals[1], vals[2], vals[0]);*/ - esrv_move_object (pl->ob, vals[0], vals[1], vals[2]); + esrv_move_object (pl->ob, to, tag, nrof); } /****************************************************************************** @@ -822,7 +835,7 @@ AddIfShort (ns->last_stats.Cha, ob->stats.Cha, CS_STAT_CHA); for (int s = 0; s < NUM_SKILLS; s++) - if (object *skill = opl->last_skill_ob[s]) + if (object *skill = opl->last_skill_ob [s]) if (skill->stats.exp != ns->last_skill_exp [s]) { ns->last_skill_exp [s] = skill->stats.exp; @@ -899,11 +912,8 @@ << uint32 (pl->ob->face) << data8 (pl->ob->name); -#if 0 pl->ns->last_weight = weight; -#endif pl->ns->send_packet (sl); - SET_FLAG (pl->ob, FLAG_CLIENT_SENT); } /****************************************************************************** @@ -1031,16 +1041,14 @@ if (!ob->active) return; - maptile *plmap = ob->map; - /* If player is just joining the game, he isn't here yet, so the map * can get swapped out. If so, don't try to send them a map. All will * be OK once they really log in. */ - if (!plmap || plmap->in_memory != MAP_ACTIVE) + if (!ob->map || ob->map->in_memory != MAP_ACTIVE) return; - int x, y, ax, ay, startlen, max_x, max_y, oldlen; + int startlen, oldlen; int estartlen, eoldlen; uint8 eentrysize; uint16 ewhatstart, ewhatflag; @@ -1107,33 +1115,27 @@ estartlen = esl.length (); } - /* x,y are the real map locations. ax, ay are viewport relative - * locations. - */ - ay = 0; - /* We could do this logic as conditionals in the if statement, * but that started to get a bit messy to look at. */ - max_x = ob->x + (socket.mapx + 1) / 2; - max_y = ob->y + (socket.mapy + 1) / 2; + int hx = socket.mapx / 2; + int hy = socket.mapy / 2; - for (y = ob->y - socket.mapy / 2; y < max_y; y++, ay++) + for (int dx = -hx; dx <= hx; dx++) { sint16 nx, ny; maptile *m = 0; - ax = 0; - for (x = ob->x - socket.mapx / 2; x < max_x; x++, ax++) + for (int dy = -hy; dy <= hy; dy++) { - // check to see if we can simply go one right quickly - ++nx; - if (m && nx >= m->width) + // check to see if we can simply go one down quickly + if (m && ++ny >= m->height) m = 0; + // no, so do it the slow way if (!m) { - nx = x; ny = y; m = plmap; + nx = ob->x + dx; ny = ob->y + dy; m = ob->map; if (xy_normalise (m, nx, ny)) m->touch (); @@ -1141,6 +1143,9 @@ m = 0; } + int ax = dx + hx; + int ay = dy + hy; + int emask, mask; emask = mask = (ax & 0x3f) << 10 | (ay & 0x3f) << 4; @@ -1151,9 +1156,9 @@ */ if (!m) { - /* space is out of map. Update space and clear values - * if this hasn't already been done. If the space is out - * of the map, it shouldn't have a head + /* space is out of map. Update space and clear values + * if this hasn't already been done. If the space is out + * of the map, it shouldn't have a head. */ if (lastcell.count != -1) { @@ -1164,11 +1169,10 @@ continue; } - int d = pl->blocked_los[ax][ay]; + int d = pl->blocked_los_uc (dx, dy); if (d > 3) { - int need_send = 0, count; /* This block deals with spaces that are not visible for whatever @@ -1184,11 +1188,11 @@ count = -1; - /* properly clear a previously sent big face */ if (lastcell.faces[0] || lastcell.faces[1] || lastcell.faces[2] || lastcell.stat_hp || lastcell.flags || lastcell.player) need_send = 1; + /* properly clear a previously sent big face */ map_clearcell (&lastcell, count); if ((mask & 0xf) || need_send) @@ -1254,17 +1258,21 @@ && op->stats.maxhp > 0 && (op->type == PLAYER || op->type == DOOR // does not work, have maxhp 0 - || QUERY_FLAG (op, FLAG_MONSTER) || QUERY_FLAG (op, FLAG_ALIVE) || QUERY_FLAG (op, FLAG_GENERATOR))) + || QUERY_FLAG (op, FLAG_MONSTER) + || QUERY_FLAG (op, FLAG_ALIVE) + || QUERY_FLAG (op, FLAG_GENERATOR))) { stat_hp = 255 - (op->stats.hp * 255 + 254) / op->stats.maxhp; stat_width = op->arch->max_x - op->arch->x; //TODO: should be upper-left edge } - if (op->msg && op->msg[0] == '@') + if (op->has_dialogue ()) flags |= 1; - if (op->type == PLAYER && op != ob) - player = op->count; + if (op->type == PLAYER) + player = op == ob ? pl->ob->count + : op == pl->ob ? ob->count + : op->count; } if (lastcell.stat_hp != stat_hp) @@ -1317,8 +1325,9 @@ if (update_space (sl, socket, ms, lastcell, 1)) mask |= 0x2; - if (ms.player () == ob - && (ob->invisible & (ob->invisible < 50 ? 1 : 7))) + if (ob->invisible + && ob->invisible & (ob->invisible < 50 ? 1 : 7) + && ms.player () == ob) { // force player to be visible to himself if invisible if (lastcell.faces[0] != ob->face) @@ -1424,7 +1433,7 @@ sl << "replyinfo skill_info\n"; for (int i = 1; i < NUM_SKILLS; i++) - sl.printf ("%d:%s\n", i + CS_STAT_SKILLINFO, &skill_names[i]); + sl.printf ("%d:%s\n", i + CS_STAT_SKILLINFO, &skill_names [i]); if (sl.length () > MAXSOCKBUF) { @@ -1478,21 +1487,21 @@ int flags = 0; /* check if we need to update it */ - if (spell->last_sp != SP_level_spellpoint_cost (pl->ob, spell, SPELL_MANA)) + if (spell->cached_sp != SP_level_spellpoint_cost (pl->ob, spell, SPELL_MANA)) { - spell->last_sp = SP_level_spellpoint_cost (pl->ob, spell, SPELL_MANA); + spell->cached_sp = SP_level_spellpoint_cost (pl->ob, spell, SPELL_MANA); flags |= UPD_SP_MANA; } - if (spell->last_grace != SP_level_spellpoint_cost (pl->ob, spell, SPELL_GRACE)) + if (spell->cached_grace != SP_level_spellpoint_cost (pl->ob, spell, SPELL_GRACE)) { - spell->last_grace = SP_level_spellpoint_cost (pl->ob, spell, SPELL_GRACE); + spell->cached_grace = SP_level_spellpoint_cost (pl->ob, spell, SPELL_GRACE); flags |= UPD_SP_GRACE; } - if (spell->last_eat != spell->stats.dam + SP_level_dam_adjust (pl->ob, spell)) + if (spell->cached_eat != spell->stats.dam + SP_level_dam_adjust (pl->ob, spell)) { - spell->last_eat = spell->stats.dam + SP_level_dam_adjust (pl->ob, spell); + spell->cached_eat = spell->stats.dam + SP_level_dam_adjust (pl->ob, spell); flags |= UPD_SP_DAMAGE; } @@ -1504,9 +1513,9 @@ << uint8 (flags) << uint32 (spell->count); - if (flags & UPD_SP_MANA ) sl << uint16 (spell->last_sp); - if (flags & UPD_SP_GRACE ) sl << uint16 (spell->last_grace); - if (flags & UPD_SP_DAMAGE) sl << uint16 (spell->last_eat); + if (flags & UPD_SP_MANA ) sl << uint16 (spell->cached_sp); + if (flags & UPD_SP_GRACE ) sl << uint16 (spell->cached_grace); + if (flags & UPD_SP_DAMAGE) sl << uint16 (spell->cached_eat); pl->ns->send_packet (sl); } @@ -1546,20 +1555,14 @@ } /* store costs and damage in the object struct, to compare to later */ - spell->last_sp = SP_level_spellpoint_cost (pl->ob, spell, SPELL_MANA); - spell->last_grace = SP_level_spellpoint_cost (pl->ob, spell, SPELL_GRACE); - spell->last_eat = spell->stats.dam + SP_level_dam_adjust (pl->ob, spell); + spell->cached_sp = SP_level_spellpoint_cost (pl->ob, spell, SPELL_MANA); + spell->cached_grace = SP_level_spellpoint_cost (pl->ob, spell, SPELL_GRACE); + spell->cached_eat = spell->stats.dam + SP_level_dam_adjust (pl->ob, spell); /* figure out which skill it uses, if it uses one */ if (spell->skill) - { - for (i = 1; i < NUM_SKILLS; i++) - if (!strcmp (spell->skill, skill_names[i])) - { - skill = i + CS_STAT_SKILLINFO; - break; - } - } + if (object *tmp = pl->find_skill (spell->skill)) + skill = tmp->subtype + CS_STAT_SKILLINFO; // spells better have a face if (!spell->face) @@ -1574,9 +1577,9 @@ sl << uint32 (spell->count) << uint16 (spell->level) << uint16 (spell->casting_time) - << uint16 (spell->last_sp) - << uint16 (spell->last_grace) - << uint16 (spell->last_eat) + << uint16 (spell->cached_sp) + << uint16 (spell->cached_grace) + << uint16 (spell->cached_eat) << uint8 (skill) << uint32 (spell->path_attuned) << uint32 (spell->face)