std::vector<Position> SearchLevel::getAdjacentNodes(int posX, int posY) { std::vector<Position> result; if (isWalkable(posX + 1, posY)) result.push_back(Position(posX + 1, posY)); if (isWalkable(posX - 1, posY)) result.push_back(Position(posX - 1, posY)); if (isWalkable(posX, posY + 1)) result.push_back(Position(posX, posY + 1)); if (isWalkable(posX, posY - 1)) result.push_back(Position(posX, posY - 1)); return result; }
void PlayerPawnMap::fixedGridMovement() { if( isNearTile(m_nextTile) ) { if( !m_wantToMove ) { m_speed.set(0, 0); } else { // compute next tile depending on facing if( m_facing == 'u' && isWalkable(tile().x(), tile().y() - 1) ) { m_nextTile.set( tile().x(), tile().y() - 1 ); m_speed.set(0, -1); setAnim(Assets::instance->playerWalkU); } else if( m_facing == 'd' && isWalkable(tile().x(), tile().y() + 1) ) { m_nextTile.set( tile().x(), tile().y() + 1 ); m_speed.set(0, 1); setAnim(Assets::instance->playerWalkD); } else if( m_facing == 'l' && isWalkable(tile().x() - 1, tile().y() ) ) { m_nextTile.set( tile().x() - 1, tile().y() ); m_speed.set(-1, 0); setAnim(Assets::instance->playerWalkL); } else if( m_facing == 'r' && isWalkable(tile().x() + 1, tile().y() ) ) { m_nextTile.set( tile().x() + 1, tile().y() ); m_speed.set(1, 0); setAnim(Assets::instance->playerWalkR); } else { m_speed.set(0,0); } } } if( m_speed.x() == 0 && m_speed.y() == 0 ) { switch( m_facing ) { case 'u': setAnim(Assets::instance->playerStandU); break; case 'd': setAnim(Assets::instance->playerStandD); break; case 'l': setAnim(Assets::instance->playerStandL); break; case 'r': setAnim(Assets::instance->playerStandR); break; } } }
/*! \author Luxor */ void cChar::walkNextStep() { if ( isFrozen() ) return; if ( !hasPath() ) return; if ( !path->pathFound() ) path->exec(); sLocation pos = path->getNextPos(); if ( pos == getPosition() ) return; if ( isWalkable( pos, WALKFLAG_DYNAMIC|WALKFLAG_CHARS, this ) == illegal_z ) { safedelete( path ); return; } pCreatureInfo creature = creatures.getCreature( getId() ); if( creature!=NULL ) { if( creature->canFly() && ( fly_steps>0 ) ) if ( chance( 20 ) ) playAction( 0x13 ); // Flying animation } uint8_t dirXY = getDirFromXY(pos); dir = dirXY & 0x07; MoveTo( pos ); sendToPlayers( this, dirXY ); setNpcMoveTime(); }
void Tile::explode() { if (m_type == Tile::Stone) { setType(Tile::Debris); emit exploded(); } else if (isWalkable()) { emit exploded(); } }
Road::RoadType Way::getRoadType() { Road::RoadType type = Road::ROAD_TYPE_UNKNOWN; if(!isWalkable()) return type; try { if(isOfType(TAG_BRIDGE)) type = Road::ROAD_TYPE_BRIDGE; else if(isOfType(TAG_TUNNEL)) type = Road::ROAD_TYPE_TUNNEL; else { std::string highway = getTag(TAG_HIGHWAY); std::map<std::string,Road::RoadType>::iterator it = highwayTypes.find(highway); if(it != highwayTypes.end()) type = it->second; } } catch(Exception e) {} return type; }
int PathFinding::createPath(const iPoint& origin, const iPoint& destination) { // Origin and destination are walkable? if (!isWalkable(origin) || !isWalkable(destination)) return -1; path_found.clear(); // Open and close list pathList open_list, close_list; open_list.list.add(pathNode(0, 0, origin, NULL)); while (open_list.list.count() > 0) { doubleNode<pathNode> *pnode = open_list.getNodeLowestScore(); close_list.list.add(pnode->data); iPoint pos = pnode->data.pos; open_list.list.del(pnode); pnode = close_list.find(pos); if (pnode->data.pos == destination) { close_list.list.add(pnode->data); break; } pathList candidate_nodes; int items_added = pnode->data.findWalkableAdjacents(candidate_nodes); doubleNode<pathNode> *item = candidate_nodes.list.getLast(); for (int i = 0; i < items_added; i++) { if (close_list.find(item->data.pos)) { item = item->previous; continue; } else if (open_list.find(item->data.pos)) { doubleNode<pathNode> *to_compare = open_list.find(item->data.pos); if (item->data.calculateF(destination) < to_compare->data.score()) { to_compare->data.parent = item->data.parent; to_compare->data.calculateF(destination); } } else { item->data.calculateF(destination); open_list.list.add(item->data); } item = item->previous; } } const pathNode *item = &(close_list.list.getLast()->data); while (item != NULL) { path_found.pushBack(item->pos); item = item->parent; } path_found.flip(); return path_found.getNumElements(); }
/*! \author Luxor */ void cPath::exec() { P_CHAR pc = pointers::findCharBySerial( pc_serial ); UI32 min_cost, curr_cost, heuristic, loops = 0; NODE_LIST::iterator it; while( loops < MAX_PATH_INTERNAL_LOOPS ) { if ( currNode->pos == m_finalPos ) { m_pathFound = true; break; } // Look for tiles reachable by currNode, add them to the open list addReachableNodes( currNode ); // Drop the current node in the closed list dropToClosedList( currNode ); if ( open_list.empty() ) { m_pathFound = true; break; } for ( it = open_list.begin(); it != open_list.end(); it++ ) { loops++; if ( it == open_list.begin() ) { min_cost = (*it)->cost + ( UI32( dist( (*it)->pos, m_finalPos ) ) * OBLIQUE_COST ); if ( (*it)->pos.z != m_finalPos.z ) min_cost += Z_COST * (abs( SI16((*it)->pos.z - m_finalPos.z )) / 2); nextNode = (*it); continue; } curr_cost = (*it)->cost + UI32( dist( (*it)->pos, m_finalPos ) ) * OBLIQUE_COST; if ( (*it)->pos.z != m_finalPos.z ) curr_cost += Z_COST * (abs( SI16((*it)->pos.z - m_finalPos.z) ) / 2); if ( curr_cost < min_cost ) { min_cost = curr_cost; nextNode = (*it); } } // // Heuristic and possible path improvement // heuristic = UI32( dist( currNode->parentNode->pos, nextNode->pos, false ) ); if ( heuristic == 1 ) { // The nodes are adjacent heuristic = 0; Location parent = currNode->parentNode->pos; Location next = nextNode->pos; LOGICAL bOk = false; if ( abs( SI16(parent.x - next.x) ) + abs( SI16(parent.y - next.y) ) == 1 ) heuristic = STRAIGHT_COST; else heuristic = OBLIQUE_COST; if ( heuristic < abs( SI16(nextNode->cost - currNode->parentNode->cost) ) ) bOk = true; if ( parent.z != next.z ) { next.z = parent.z; if ( isWalkable( next, WALKFLAG_ALL, pc ) == illegal_z ) // nextNode is not walkable by parentNode bOk = false; } if ( bOk ) nextNode->parentNode = currNode->parentNode; } currNode = nextNode; loops++; } m_loops += loops; if ( m_loops > MAX_PATH_TOTAL_LOOPS ) m_pathFound = true; if ( m_pathFound ) { if ( path_list.empty() ) { while( currNode->pos != m_startPos && currNode->cost != 0 && m_loops >= 0 ) { path_list.push_front( currNode->pos ); currNode = currNode->parentNode; m_loops--; } path_list.push_front( currNode->pos ); } else return; } }
/*! \author Luxor \brief Looks for every tile reachable walking by pos, and adds them to the open list */ UI08 cPath::addReachableNodes( path_node* node ) { P_CHAR pc = pointers::findCharBySerial( pc_serial ); LOGICAL bWalkable[ 4 ]; UI08 num = 0; SI08 zAdd = 0; Location loc; Location pos = node->pos; // North - 0 loc = Loc( pos.x, pos.y - 1, pos.z ); if ( (zAdd = isWalkable( loc, WALKFLAG_ALL, pc )) != illegal_z ) { bWalkable[ 0 ] = true; loc.z = zAdd; addToOpenList( loc, node, STRAIGHT_COST ); num++; } else bWalkable[ 0 ] = false; // South - 1 loc = Loc( pos.x, pos.y + 1, pos.z ); if ( (zAdd = isWalkable( loc, WALKFLAG_ALL, pc )) != illegal_z ) { bWalkable[ 1 ] = true; loc.z = zAdd; addToOpenList( loc, node, STRAIGHT_COST ); num++; } else bWalkable[ 1 ] = false; // East - 2 loc = Loc( pos.x + 1, pos.y, pos.z ); if ( (zAdd = isWalkable( loc, WALKFLAG_ALL, pc )) != illegal_z ) { bWalkable[ 2 ] = true; loc.z = zAdd; addToOpenList( loc, node, STRAIGHT_COST ); num++; } else bWalkable[ 2 ] = false; // West - 3 loc = Loc( pos.x - 1, pos.y, pos.z ); if ( (zAdd = isWalkable( loc, WALKFLAG_ALL, pc )) != illegal_z ) { bWalkable[ 3 ] = true; loc.z = zAdd; addToOpenList( loc, node, STRAIGHT_COST ); num++; } else bWalkable[ 3 ] = false; // North-East loc = Loc( pos.x + 1, pos.y - 1, pos.z ); if ( bWalkable[0] && bWalkable[2] ) { // Avoid to go near a tile angle if ( (zAdd = isWalkable( loc, WALKFLAG_ALL, pc )) != illegal_z ) { loc.z = zAdd; addToOpenList( loc, node, OBLIQUE_COST ); num++; } } // North-West loc = Loc( pos.x - 1, pos.y - 1, pos.z ); if ( bWalkable[0] && bWalkable[3] ) { // Avoid to go near a tile angle if ( (zAdd = isWalkable( loc, WALKFLAG_ALL, pc )) != illegal_z ) { loc.z = zAdd; addToOpenList( loc, node, OBLIQUE_COST ); num++; } } // South-East loc = Loc( pos.x + 1, pos.y + 1, pos.z ); if ( bWalkable[1] && bWalkable[2] ) { // Avoid to go near a tile angle if ( (zAdd = isWalkable( loc, WALKFLAG_ALL, pc )) != illegal_z ) { loc.z = zAdd; addToOpenList( loc, node, OBLIQUE_COST ); num++; } } // South-West loc = Loc( pos.x - 1, pos.y + 1, pos.z ); if ( bWalkable[1] && bWalkable[3] ) { // Avoid to go near a tile angle if ( (zAdd = isWalkable( loc, WALKFLAG_ALL, pc )) != illegal_z ) { loc.z = zAdd; addToOpenList( loc, node, OBLIQUE_COST ); num++; } } return num; }
/*! \author Zippy \brief Build an house Triggered by double clicking a deed-> the deed's morex is read for the house section in house.cpp. Extra items can be added using HOUSE ITEM, (this includes all doors!) and locked "LOCK" Space around the house with SPACEX/Y and CHAR offset CHARX/Y/Z \todo Remove temp variable */ void buildhouse( pClient client, pTarget t ) { int i = t->buffer[2]; char temp[TEMP_STR_SIZE]; //xan -> this overrides the global temp var int loopexit=0;//where they click, and the house/key items uint32_t k, sx = 0, sy = 0, icount=0; uint16_t x, y, id_tile; int16_t z; int hitem[100];//extra "house items" (up to 100) char sect[512]; //file reading char itemsdecay = 0; // set to 1 to make stuff decay in houses static int looptimes=0; //for targeting int cx=0,cy=0,cz=8; //where the char is moved to when they place the house (Inside, on the steps.. etc...)(Offset) int boat=0;//Boats int hdeed=0;//deed id # int norealmulti=0,nokey=0,othername=0; char name[512]; pChar pc = client->currChar(); if ( ! pc ) return; sLocation charpos= pc->getPosition(); int16_t id = INVALID; //house ID hitem[0]=0;//avoid problems if there are no HOUSE_ITEMs by initializing the first one as 0 if (i) { cScpIterator* iter = NULL; char script1[1024]; char script2[1024]; sprintf(sect, "SECTION HOUSE %d", i);//and BTW, .find() adds SECTION on there for you.... iter = Scripts::House->getNewIterator(sect); if (iter==NULL) return; do { iter->parseLine(script1, script2); if ((script1[0]!='}')&&(script1[0]!='{')) { if (!(strcmp(script1,"ID"))) { id = hex2num(script2); } else if (!(strcmp(script1,"SPACEX"))) { sx=str2num(script2)+1; } else if (!(strcmp(script1,"SPACEY"))) { sy=str2num(script2)+1; } else if (!(strcmp(script1,"CHARX"))) { cx=str2num(script2); } else if (!(strcmp(script1,"CHARY"))) { cy=str2num(script2); } else if (!(strcmp(script1,"CHARZ"))) { cz=str2num(script2); } else if( !(strcmp(script1, "ITEMSDECAY" ))) { itemsdecay = str2num( script2 ); } else if (!(strcmp(script1,"HOUSE_ITEM"))) { hitem[icount]=str2num(script2); icount++; } else if (!(strcmp(script1, "HOUSE_DEED"))) { hdeed=str2num(script2); } else if (!(strcmp(script1, "BOAT"))) boat=1;//Boats else if (!(strcmp(script1, "NOREALMULTI"))) norealmulti=1; // LB bugfix for pentas crashing client else if (!(strcmp(script1, "NOKEY"))) nokey=1; else if (!(strcmp(script1, "NAME"))) { strcpy(name,script2); othername=1; } } } while ( (strcmp(script1,"}")) && (++loopexit < MAXLOOPS) ); safedelete(iter); if (!id) { ErrOut("Bad house script # %i!\n",i); return; } } if(!looptimes) { if (i) { if (norealmulti) { pTarget targ = clientInfo[s]->newTarget( new cLocationTarget() ); targ->code_callback=buildhouse; ShortToCharPtr(0x4064, t->buffer); targ->send( ps ); ps->sysmsg( "Select a place for your structure: "); } else client->sysmessage("Select location for building."); nPackets::Sent::TargetMulti pk(0x00010000/*serial*/, id -0x4000/*model*/); client->sendPacket(&pk); } else { client->sysmessage("Select location for building."); nPackets::Sent::TargetMulti pk(0x00010000/*serial*/, ShortFromCharPtr(t->buffer) -0x4000/*model*/); client->sendPacket(&pk); } looptimes++;//for when we come back after they target something return; } if(looptimes) { looptimes=0; if(!pc->IsGM() && SrvParms->houseintown==0) { if ((region[pc->region].priv & rgnFlagGuarded) && itemById::IsHouse(id) ) // popy { client->sysmessage(" You cannot build houses in town!"); return; } } x = ShortFromCharPtr(buffer[s] +11); //where they targeted y = ShortFromCharPtr(buffer[s] +13); z = ShortFromCharPtr(buffer[s] +15); id_tile = ShortFromCharPtr(buffer[s] +17); z += tileHeight(id_tile); //XAN : House placing fix :) if ( (( x<XBORDER || y <YBORDER ) || ( x>(uint32_t)((map_width*8)-XBORDER) || y >(uint32_t)((map_height*8)-YBORDER) )) ) { client->sysmessage("You cannot build your structure there!"); return; } /* if (ishouse(id1, id2)) // strict checking only for houses ! LB { if(!(CheckBuildSite(x,y,z,sx,sy))) { client->sysmessage("Can not build a house at that location (CBS)!"); return; } }*/ for (k=0;k<sx;k++)//check the SPACEX and SPACEY to make sure they are valid locations.... { for (uint32_t l=0;l<sy;l++) { sLocation loc; loc.x=x+k; loc.y=y+l; loc.z=z; sLocation newpos = sLocation( x+k, y+l, z ); if ( (isWalkable( newpos ) == illegal_z ) && ((charpos.x != x+k)&&(charpos.y != y+l)) ) /*This will take the char making the house out of the space check, be careful you don't build a house on top of your self..... this had to be done So you could extra space around houses, (12+) and they would still be buildable.*/ { client->sysmessage("You cannot build your stucture there."); return; //ConOut("Invalid %i,%i [%i,%i]\n",k,l,x+k,y+l); } //else ConOut("DEBUG: Valid at %i,%i [%i,%i]\n",k,l,x+k,y+l); if ( !norealmulti && cMulti::getAt(loc) ) { client->sysmessage("You cant build structures inside structures"); return; } } } if((id % 256)>=18) sprintf(temp,"%s's house",pc->getCurrentName().c_str());//This will make the little deed item you see when you have showhs on say the person's name, thought it might be helpful for GMs. else strcpy(temp, "a mast"); if(norealmulti) strcpy(temp, name); //--^ if (othername) strcpy(temp,name); if (id == INVALID) return; pItem pHouse = item::CreateFromScript( "$item_hardcoded" ); if ( !pHouse ) return; pHouse->setId( id ); pHouse->setCurrentName( temp ); pc->making=0; pHouse->setPosition(x, y, z); pHouse->setDecay( false ); pHouse->setNewbie( false ); pHouse->setDispellable( false ); pHouse->more4 = itemsdecay; // set to 1 to make items in houses decay pHouse->morex=hdeed; // crackerjack 8/9/99 - for converting back *into* deeds pHouse->setOwner(pc); if (pHouse->isInWorld()) { mapRegions->add(pHouse); } if (!hitem[0] && !boat) { pc->teleport(); return;//If there's no extra items, we don't really need a key, or anything else do we? ;-) } if(boat) { if(!Build(s,pHouse, id%256/*id2*/)) { pHouse->Delete(); return; } } if (i) { pItem pFx1 = MAKE_ITEM_REF( pc->fx1 ); if ( pFx1 != 0 ) pFx1->Delete(); // this will del the deed no matter where it is } pc->fx1=-1; //reset fx1 so it does not interfere // bugfix LB ... was too early reseted pItem pKey=NULL; pItem pKey2=NULL; pItem pBackPack = pc->getBackpack(); //Key... //Altered key naming to include pc's name. Integrated backpack and bankbox handling (Sparhawk) if ((id%256 >=0x70) && (id%256 <=0x73)) { sprintf(temp,"%s's tent key",pc->getCurrentName().c_str()); pKey = item::CreateFromScript( "$item_iron_key", pBackPack ); //iron key for tents pKey2= item::CreateFromScript( "$item_iron_key", pBackPack ); } else if(id%256 <=0x18) { sprintf(temp,"%s's ship key",pc->getCurrentName().c_str()); pKey= item::CreateFromScript( "$item_bronze_key", pBackPack ); //Boats -Rusty Iron Key pKey2= item::CreateFromScript( "$item_bronze_key", pBackPack ); } else { sprintf(temp,"%s's house key",pc->getCurrentName().c_str()); pKey= item::CreateFromScript( "$item_gold_key", pBackPack ); //gold key for everything else; pKey2= item::CreateFromScript( "$item_gold_key", pBackPack ); } if ( ! pKey || ! pKey2 ) return; pKey->Refresh(); pKey2->Refresh(); pHouse->st = pKey->getSerial(); // Create link from house to housekeys to allow easy renaming of pHouse->st2= pKey2->getSerial(); // house, housesign and housekeys without having to loop trough // all world items (Sparhawk) pKey->more = pHouse->getSerial(); //use the house's serial for the more on the key to keep it unique pKey->type=ITYPE_KEY; pKey->setNewbie(); pKey2->more = pHouse->getSerial(); //use the house's serial for the more on the key to keep it unique pKey2->type=ITYPE_KEY; pKey2->setNewbie(); pItem bankbox = pc->GetBankBox(); if(bankbox!=NULL) // we sould add a key in bankbox only if the player has a bankbox =) { pItem p_key3=item::CreateFromScript( "$item_gold_key" ); if ( ! p_key3 ) return; p_key3->setCurrentName( "a house key" ); p_key3->more = pHouse->getSerial(); p_key3->type=ITYPE_KEY; p_key3->setNewbie(); bankbox->AddItem(p_key3); } if(nokey) { pKey->Delete(); // No key for .. nokey items pKey2->Delete(); // No key for .. nokey items } for (k=0;k<icount;k++)//Loop through the HOUSE_ITEMs { cScpIterator* iter = NULL; char script1[1024]; char script2[1024]; sprintf(sect,"SECTION HOUSE ITEM %i",hitem[k]); iter = Scripts::House->getNewIterator(sect); if (iter!=NULL) { pItem pi_l=NULL; loopexit=0; do { iter->parseLine(script1, script2); if (script1[0]!='}') { if (!(strcmp(script1,"ITEM"))) { pi_l=item::CreateScriptItem(s,str2num(script2),0);//This opens the item script... so we gotta keep track of where we are with the other script. if(pi_l) { pi_l->magic=2;//Non-Movebale by default pi_l->setDecay( false ); //since even things in houses decay, no-decay by default pi_l->setNewbie( false ); pi_l->setDispellable( false ); pi_l->setPosition(x, y, z); pi_l->setOwner(pc); // SPARHAWK 2001-01-28 Added House sign naming if (pi_l->IsSign()) if ((id%256 >=0x70) && (id%256<=0x73)) pi_l->setCurrentName("%s's tent",pc->getCurrentName().c_str()); else if (id%256<=0x18) pi_l->setCurrentName("%s's ship",pc->getCurrentName().c_str()); else pi_l->setCurrentName("%s's house",pc->getCurrentName().c_str()); } } if (!(strcmp(script1,"DECAY"))) { if (pi_l) pi_l->setDecay(); } if (!(strcmp(script1,"NODECAY"))) { if (pi_l) pi_l->setDecay( false ); } if (!(strcmp(script1,"PACK")))//put the item in the Builder's Backpack { if (pi_l) pi_l->setContainer(pc->getBackpack()); if (pi_l) pi_l->setPosition("x", rand()%90+31); if (pi_l) pi_l->setPosition("y", rand()%90+31); if (pi_l) pi_l->setPosition("z", 9); } if (!(strcmp(script1,"MOVEABLE"))) { if (pi_l) pi_l->magic=1; } if (!(strcmp(script1,"LOCK")))//lock it with the house key { if (pi_l) pi_l->more = pHouse->getSerial(); } if (!(strcmp(script1,"X")))//offset + or - from the center of the house: { if (pi_l) pi_l->setPosition("x", x+str2num(script2)); } if (!(strcmp(script1,"Y"))) { if (pi_l) pi_l->setPosition("y", y+str2num(script2)); } if (!(strcmp(script1,"Z"))) { if (pi_l) pi_l->setPosition("z", z+str2num(script2)); } } } while ( (strcmp(script1,"}")) && (++loopexit < MAXLOOPS) ); if (pi_l) if (pi_l->isInWorld()) { mapRegions->add(pi_l); } safedelete(iter); } } NxwSocketWrapper sw; sw.fillOnline( pc, false ); for( sw.rewind(); !sw.isEmpty(); sw++ ) { pClient ps_i = sw.getClient(); if(ps_i==NULL) continue; pChar pc_i=ps_i->currChar(); if(pc_i) pc_i->teleport(); } //</Luxor> if (!(norealmulti)) { charpos.x= x+cx; //move char inside house charpos.y= y+cy; charpos.dispz= charpos.z= z+cz; pc->setPosition( charpos ); //ConOut("Z: %i Offset: %i Char: %i Total: %i\n",z,cz,chars[currchar[s]].z,z+cz); pc->teleport(); } } }
/*! \author Luxor \brief Calls the pathfinding algorithm and creates a new path */ void cChar::pathFind( sLocation pos, bool bOverrideCurrentPath ) { if ( hasPath() ) { if ( bOverrideCurrentPath ) safedelete( path ); else return; } bool bOk = true; sLocation loc = pos; if ( isWalkable( pos, WALKFLAG_ALL, this ) == illegal_z ) { // If it isn't walkable, we can only reach the nearest tile bOk = false; for ( uint32_t i = 1; i < 4; i++ ) { // East loc = sLocation( pos.x + i, pos.y, pos.z ); if ( isWalkable( loc, WALKFLAG_ALL, this ) != illegal_z ) { bOk = true; break; } // West loc = sLocation( pos.x - i, pos.y, pos.z ); if ( isWalkable( loc, WALKFLAG_ALL, this ) != illegal_z ) { bOk = true; break; } // South loc = sLocation( pos.x, pos.y + i, pos.z ); if ( isWalkable( loc, WALKFLAG_ALL, this ) != illegal_z ) { bOk = true; break; } // North loc = sLocation( pos.x, pos.y - i, pos.z ); if ( isWalkable( loc, WALKFLAG_ALL, this ) != illegal_z ) { bOk = true; break; } // North-East loc = sLocation( pos.x + i, pos.y - i, pos.z ); if ( isWalkable( loc, WALKFLAG_ALL, this ) != illegal_z ) { bOk = true; break; } // North-West loc = sLocation( pos.x - i, pos.y - i, pos.z ); if ( isWalkable( loc, WALKFLAG_ALL, this ) != illegal_z ) { bOk = true; break; } // South-East loc = sLocation( pos.x + i, pos.y + i, pos.z ); if ( isWalkable( loc, WALKFLAG_ALL, this ) != illegal_z ) { bOk = true; break; } // South-West loc = sLocation( pos.x - i, pos.y + i, pos.z ); if ( isWalkable( loc, WALKFLAG_ALL, this ) != illegal_z ) { bOk = true; break; } } } if ( bOk ) path = new cPath( getPosition(), loc, this ); }
/*! \brief Handles a 'real move' if the char is not only changing direction \param pc Walking character \param dir Direction in which the character is moving to \param oldp Previous position of the char (in the same map) */ static bool WalkHandleBlocking(pChar pc, int sequence, uint8_t dir, sPoint oldp) { if(!pc) return false; if (pc->npc) pc->setNpcMoveTime(); //reset move timer sLocation pcpos= pc->getPosition(); pcpos.move(dir&0x07, 1); // This calculate the new position int8_t z; if ( pc->npc ) z = isWalkable( pc->getPosition(), WALKFLAG_MAP + WALKFLAG_STATIC + WALKFLAG_DYNAMIC, pc ); else z = getHeight( pc->getPosition() ); //WalkEvaluateBlockers(pc, &z, &dispz, blockers); //!\todo Should this actually be used only for npcs? Sure the owner and banned stuff, but the rest? if (pc->npc==0) // this is also called for npcs .. LB ?????? Sparhawk Not if you're excluding npc's { pMulti pi_multi = cMulti::getAt( pc->getPosition() ); if ( ! pi_multi ) pc->setMulti(NULL); else { pBoat pb = dynamic_cast<pBoat>(pi_multi); pHouse ph = dynamic_cast<pHouse>(pi_multi); if ( pb ) { //xan : probably the plr has entered the boat walking! //!\todo Change this when new owner-system is up and running NxwCharWrapper pets; pets.fillOwnedNpcs( pc, false, true ); for( pets.rewind(); !pets.isEmpty(); pets++ ) { pChar pc_b=pets.getChar(); if (! pc_b ) return; pc_b->MoveTo( boat->getPosition() + sLocation(1,1,2) ); pc_b->setMulti(boat); pc_b->teleport(); } } else if ( ph ) { if ( ph->isBanned(pc) ) { client->sysmesage("You are banned from that location."); sLocation newpos = pi_multi->getArea().br + sLocation(1, 1, pc->getPosition().z); pc->setPosition(newpos); pc->teleport(); return false; } // house refreshment code moved to dooruse() } } } // end of is player if ( z == illegal_z ) { pc->setPosition( sLocation(oldx, oldy) ); pClient client = pc->getClient(); if ( ! client ) { pc->blocked = 1; return false }