本文整理汇总了C++中P_ITEM::pos方法的典型用法代码示例。如果您正苦于以下问题:C++ P_ITEM::pos方法的具体用法?C++ P_ITEM::pos怎么用?C++ P_ITEM::pos使用的例子?那么, 这里精选的方法代码示例或许可以为您提供帮助。您也可以进一步了解该方法所在类P_ITEM
的用法示例。
在下文中一共展示了P_ITEM::pos方法的15个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C++代码示例。
示例1: handleItems
/*!
Sends items which came in range and handles collisions with teleporters
or damaging items.
*/
void handleItems( P_CHAR pChar, const Coord& oldpos )
{
P_PLAYER player = dynamic_cast<P_PLAYER>( pChar );
MapItemsIterator iter = MapObjects::instance()->listItemsInCircle( pChar->pos(), VISRANGE );
for ( P_ITEM pItem = iter.first(); pItem; pItem = iter.next() )
{
// Check for item collisions here.
if ( pChar->pos().x == pItem->pos().x && pChar->pos().y == pItem->pos().y )
{
if ( pItem->pos().z >= pChar->pos().z - 15 && pItem->pos().z <= pChar->pos().z + 15 )
{
if ( handleItemCollision( pChar, pItem ) )
{
break;
}
}
}
// If we are a connected player then send new items
if ( player && player->socket() )
{
UI32 oldDist = oldpos.distance( pItem->pos() );
if ( oldDist >= player->visualRange() )
{
// was out of range before and now is in range
pItem->update( player->socket() );
}
}
}
}
示例2: DynTile
Q_UINT16 DynTile( const Coord_cl& pos )
{
RegionIterator4Items ri( pos );
for ( ri.Begin(); !ri.atEnd(); ri++ )
{
P_ITEM mapitem = ri.GetData();
if ( mapitem )
{
if ( mapitem->isMulti() )
{
MultiDefinition* def = MultiCache::instance()->getMulti( mapitem->id() - 0x4000 );
if ( !def )
return 0;
QValueVector<multiItem_st> multi = def->getEntries();
for ( Q_UINT32 j = 0; j < multi.size(); ++j )
{
if ( ( multi[j].visible && ( mapitem->pos().x + multi[j].x == pos.x ) && ( mapitem->pos().y + multi[j].y == pos.y ) && ( abs( mapitem->pos().z + multi[j].z - pos.z ) <= 1 ) ) )
{
return multi[j].tile;
}
}
}
else if ( mapitem->pos() == pos )
return mapitem->id();
}
}
return ( Q_UINT16 ) - 1;
}
示例3: DynTile
Q_UINT16 DynTile( const Coord& pos )
{
MapItemsIterator ri = MapObjects::instance()->listItemsInCircle( pos, 18 );
for ( P_ITEM mapitem = ri.first(); mapitem; mapitem = ri.next() )
{
if ( mapitem->isMulti() )
{
MultiDefinition* def = MultiCache::instance()->getMulti( mapitem->id() - 0x4000 );
if ( !def )
return 0;
QValueVector<multiItem_st> multi = def->getEntries();
for ( Q_UINT32 j = 0; j < multi.size(); ++j )
{
if ( ( multi[j].visible && ( mapitem->pos().x + multi[j].x == pos.x ) && ( mapitem->pos().y + multi[j].y == pos.y ) && ( abs( mapitem->pos().z + multi[j].z - pos.z ) <= 1 ) ) )
{
return multi[j].tile;
}
}
}
else if ( mapitem->pos() == pos )
{
return mapitem->id();
}
}
return ( Q_UINT16 ) - 1;
}
示例4: canLandMonsterMoveHere
bool cMovement::canLandMonsterMoveHere( const Coord_cl& pos ) const
{
if ( pos.x >= ( Maps::instance()->mapTileWidth( pos.map ) * 8 ) || pos.y >= ( Maps::instance()->mapTileHeight( pos.map ) * 8 ) )
return false;
const signed char elev = Maps::instance()->mapElevation( pos );
Coord_cl target = pos;
target.z = elev;
if ( ILLEGAL_Z == elev )
return false;
// get the tile id of any dynamic tiles at this spot
Coord_cl mPos = pos;
mPos.z = elev;
const Q_INT32 dt = DynTile( mPos );
// if there is a dynamic tile at this spot, check to see if its a blocker
// if it does block, might as well Q_INT16-circuit and return right away
if ( dt >= 0 )
{
tile_st tile = TileCache::instance()->getTile( dt );
if ( tile.isBlocking() || tile.isWet() )
return false;
}
// if there's a static block here in our way, return false
StaticsIterator msi = Maps::instance()->staticsIterator( pos );
while ( !msi.atEnd() )
{
tile_st tile = TileCache::instance()->getTile( msi->itemid );
const Q_INT32 elev = msi->zoff + cTileCache::tileHeight( tile );
if ( ( elev >= pos.z ) && ( msi->zoff <= pos.z ) )
{
if ( tile.isBlocking() || tile.isWet() )
return false;
}
msi++;
}
RegionIterator4Items items( pos, 0 );
for ( items.Begin(); !items.atEnd(); items++ )
{
P_ITEM item = items.GetData();
tile_st tile = TileCache::instance()->getTile( item->id() );
const Q_INT32 elev = item->pos().z + cTileCache::tileHeight( tile );
if ( ( elev >= pos.z ) && ( item->pos().z <= pos.z ) )
{
if ( tile.isBlocking() || tile.isWet() )
return false;
}
}
return true;
}
示例5: losTargetPoint
Coord Coord::losTargetPoint( cUORxTarget* target, unsigned char map )
{
SERIAL serial = target->serial();
P_ITEM pItem = World::instance()->findItem( serial );
P_CHAR pChar = World::instance()->findChar( serial );
if ( pItem )
{
pItem = pItem->getOutmostItem();
if ( pItem->container() && pItem->container()->isChar() )
{
return pItem->container()->pos().losCharPoint();
}
else
{
return pItem->pos().losItemPoint( pItem->id() );
}
}
else if ( pChar )
{
return pChar->pos().losCharPoint();
}
else
{
return Coord( target->x(), target->y(), target->z(), map );
}
}
示例6: removeFromView
// Remove it from all in-range sockets
void cUObject::removeFromView( bool clean )
{
// Get Real pos
Coord_cl mPos = pos_;
if( isItemSerial( serial_ ) )
{
P_ITEM pItem = dynamic_cast<P_ITEM>(this);
P_ITEM pCont = pItem->getOutmostItem();
if( pCont )
{
mPos = pCont->pos();
P_CHAR pOwner = dynamic_cast<P_CHAR>( pCont->container() );
if( pOwner )
mPos = pOwner->pos();
}
}
cUOTxRemoveObject remove;
remove.setSerial(serial_);
for (cUOSocket *socket = cNetwork::instance()->first(); socket; socket = cNetwork::instance()->next()) {
if (socket->player() != this && (clean || socket->canSee(this))) {
socket->send(&remove);
}
}
}
示例7: inRange
/*!
Checks if the specified object is in given range
*/
bool cUObject::inRange( cUObject* object, quint32 range ) const
{
if ( !object )
return false;
Coord pos = object->pos_;
if ( object->isItem() )
{
P_ITEM pItem = dynamic_cast<P_ITEM>( object );
if ( pItem )
{
P_ITEM pCont = pItem->getOutmostItem();
P_CHAR pEquipped = pItem->getOutmostChar();
if ( pEquipped )
{
pos = pEquipped->pos();
}
else if ( pCont )
{
pos = pCont->pos();
}
}
}
return pos_.distance( pos ) <= range;
}
示例8: add
void cSectorMaps::add( cUObject* object )
{
// Very powerful statement. It completely
// annihilates the need to check for
// nullpointers in our object-map
if ( !object )
return;
if ( isItemSerial( object->serial() ) )
{
P_ITEM pItem = dynamic_cast<P_ITEM>( object );
if ( pItem )
{
Coord_cl pos = pItem->pos();
std::map<unsigned char, cSectorMap*>::const_iterator it = itemmaps.find( pos.map );
if ( it == itemmaps.end() )
throw QString( "Couldn't find a map with the id %1." ).arg( pos.map );
it->second->addItem( ( cUObject * ) pItem );
Timing::instance()->addDecayItem( pItem );
}
}
else if ( isCharSerial( object->serial() ) )
{
// This is a safety check to make sure that
// stabled pets don't appear on our sectormap
P_NPC npc = dynamic_cast<P_NPC>( object );
if ( npc && npc->stablemasterSerial() != INVALID_SERIAL )
{
return;
}
// The same check for players
/*P_PLAYER player = dynamic_cast<P_PLAYER>( object );
if ( player && !player->socket() && !player->logoutTime() )
{
return;
}*/
P_CHAR pChar = dynamic_cast<P_CHAR>( object );
if ( pChar )
{
Coord_cl pos = pChar->pos();
std::map<unsigned char, cSectorMap*>::const_iterator it = charmaps.find( pos.map );
if ( it == charmaps.end() )
throw QString( "Couldn't find a map with the id %1." ).arg( pos.map );
it->second->addItem( ( cUObject * ) pChar );
}
}
}
示例9: remove
void cSectorMaps::remove( cUObject* object )
{
// Very powerful statement. It completely
// annihilates the need to check for
// nullpointers in our object-map
if ( !object )
return;
if ( isItemSerial( object->serial() ) )
{
P_ITEM pItem = dynamic_cast<P_ITEM>( object );
if ( pItem )
{
Coord_cl pos = pItem->pos();
std::map<unsigned char, cSectorMap*>::const_iterator it = itemmaps.find( pos.map );
if ( it == itemmaps.end() )
throw QString( "Couldn't find a map with the id %1." ).arg( pos.map );
it->second->removeItem( ( cUObject * ) pItem );
Timing::instance()->removeDecayItem( pItem );
}
}
else if ( isCharSerial( object->serial() ) )
{
P_CHAR pChar = dynamic_cast<P_CHAR>( object );
if ( pChar )
{
Coord_cl pos = pChar->pos();
std::map<unsigned char, cSectorMap*>::const_iterator it = charmaps.find( pos.map );
if ( it == charmaps.end() )
throw QString( "Couldn't find a map with the id %1." ).arg( pos.map );
it->second->removeItem( ( cUObject * ) pChar );
}
}
}
示例10: removeFromView
// Remove it from all in-range sockets
void cUObject::removeFromView( bool clean )
{
// Get Real pos
Coord_cl mPos = pos_;
if( isItemSerial( serial_ ) )
{
P_ITEM pItem = dynamic_cast<P_ITEM>(this);
P_ITEM pCont = pItem->getOutmostItem();
if( pCont )
{
mPos = pCont->pos();
P_CHAR pOwner = dynamic_cast<P_CHAR>( pCont->container() );
if( pOwner )
mPos = pOwner->pos();
}
}
for( cUOSocket *socket = cNetwork::instance()->first(); socket; socket = cNetwork::instance()->next() )
if( clean || ( socket->player() && ( socket->player()->pos().distance( mPos ) <= socket->player()->visualRange() ) ) )
socket->removeObject( this );
}
示例11: getBlockingItems
// The highest items will be @ the beginning
// While walking we always will try the highest first.
vector< stBlockItem > getBlockingItems( P_CHAR pChar, const Coord& pos )
{
vector<stBlockItem> blockList;
make_heap( blockList.begin(), blockList.end(), compareTiles() );
// Process the map at that position
stBlockItem mapBlock;
mapBlock.maptile = true;
mapBlock.z = Maps::instance()->mapAverageElevation( pos );
mapBlock.height = 0;
// TODO: Calculate the REAL average Z Value of that Map Tile here! Otherwise clients will have minor walking problems.
map_st mapCell = Maps::instance()->seekMap( pos );
//mapBlock.z = mapCell.z;
land_st mapTile = TileCache::instance()->getLand( mapCell.id );
// If it's not impassable it's automatically walkable
if ( !( mapTile.flag1 & 0x40 ) )
mapBlock.walkable = true;
else
mapBlock.walkable = checkWalkable( pChar, mapCell.id );
if ( mapCell.id != 0x02 )
{
blockList.push_back( mapBlock );
push_heap( blockList.begin(), blockList.end(), compareTiles() );
}
// Now for the static-items
StaticsIterator staIter = Maps::instance()->staticsIterator( pos, true );
for ( ; !staIter.atEnd(); ++staIter )
{
tile_st tTile = TileCache::instance()->getTile( staIter->itemid );
// Here is decided if the tile is needed
// It's uninteresting if it's NOT blocking
// And NOT a bridge/surface
if ( !( ( tTile.flag2 & 0x02 ) || ( tTile.flag1 & 0x40 ) || ( tTile.flag2 & 0x04 ) ) )
continue;
stBlockItem staticBlock;
staticBlock.z = staIter->zoff;
// If we are a surface we can always walk here, otherwise check if
// we are special
if ( ( tTile.flag2 & 0x02 ) && !( tTile.flag1 & 0x40 ) )
staticBlock.walkable = true;
else
staticBlock.walkable = checkWalkable( pChar, staIter->itemid );
// If we are a stair only the half height counts (round up)
if ( tTile.flag2 & 0x04 )
staticBlock.height = ( Q_UINT8 ) ( ( tTile.height ) / 2 );
else
staticBlock.height = tTile.height;
blockList.push_back( staticBlock );
push_heap( blockList.begin(), blockList.end(), compareTiles() );
}
// We are only interested in items at pos
// todo: we could impliment blocking for items on the adjacent sides
// during a diagonal move here, but this has yet to be decided.
MapItemsIterator iIter = MapObjects::instance()->listItemsAtCoord( pos );
for ( P_ITEM pItem = iIter.first(); pItem; pItem = iIter.next() )
{
if ( pChar && pChar->isDead() )
{
// Doors can be passed by ghosts
if ( pItem->hasScript( "door" ) )
{
continue;
}
}
tile_st tTile = TileCache::instance()->getTile( pItem->id() );
// See above for what the flags mean
if ( !( ( tTile.flag2 & 0x02 ) || ( tTile.flag1 & 0x40 ) || ( tTile.flag2 & 0x04 ) ) )
continue;
stBlockItem blockItem;
blockItem.height = ( tTile.flag2 & 0x04 ) ? ( tTile.height / 2 ) : tTile.height;
blockItem.z = pItem->pos().z;
// Once again: see above for a description of this part
if ( ( tTile.flag2 & 0x02 ) && !( tTile.flag1 & 0x40 ) )
blockItem.walkable = true;
else
blockItem.walkable = checkWalkable( pChar, pItem->id() );
blockList.push_back( blockItem );
push_heap( blockList.begin(), blockList.end(), compareTiles() );
}
// deal with the multis now, or not.
//.........这里部分代码省略.........
示例12: dropOnItem
//.........这里部分代码省略.........
return;
}
if( pItem->amount() > 1 )
{
socket->sysMessage( tr( "You can only put 1 scroll into a spellbook at a time" ) );
socket->bounceItem( pItem, BR_NO_REASON );
return;
}
else
{
pBook->addSpell( spellId );
Items->DeleItem( pItem );
pBook->update( socket );
return;
}
}
// We drop something on the belongings of one of our playervendors
/* if( ( packOwner != NULL ) && ( packOwner->npcaitype() == 17 ) && packOwner->owner() == pChar )
{
socket->sysMessage( tr( "You drop something into your playervendor (unimplemented)" ) );
socket->bounceItem( pItem, BR_NO_REASON );
return;
}*/
// Playervendors (chest equipped by the vendor - opened to the client)
/*if( !( pCont->pileable() && pItem->pileable() && pCont->id() == pItem->id() || ( pCont->type() != 1 && pCont->type() != 9 ) ) )
{
P_CHAR pc_j = GetPackOwner(pCont);
if (pc_j != NULL)
{
if (pc_j->npcaitype() == 17 && pc_j->isNpc() && pChar->Owns(pc_j))
{
pChar->inputitem = pItem->serial;
pChar->inputmode = cChar::enPricing;
sysmessage(s, "Set a price for this item.");
}
}
*/
// We may also drop into *any* locked chest
// So we can have post-boxes ;o)
// Spellbooks are containers for us as well
if( pCont->type() == 1 || pCont->type() == 8 || pCont->type() == 63 || pCont->type() == 65 || pCont->type() == 66 )
{
// If we're dropping it onto the closed container
if( dropPos.distance( pCont->pos() ) == 0 )
{
pCont->addItem( pItem );
}
else
{
pCont->addItem( pItem, false );
pItem->setPos( dropPos );
}
// Dropped on another Container/in another Container
pChar->soundEffect( 0x57 );
pItem->update();
return;
}
// Item matching needs to be extended !!! at least Color! (for certain types)
else if ( pCont->isPileable() && pItem->isPileable() && ( pCont->id() == pItem->id() ) )
{
if( pCont->amount() + pItem->amount() <= 65535 )
{
pCont->setAmount( pCont->amount() + pItem->amount() );
Items->DeleItem( pItem );
pCont->update(); // Need to update the amount
return;
}
// We have to *keep* our current item
else
{
pCont->setAmount( 65535 ); // Max out the amount
pCont->update();
// The delta between 65535 and pCont->amount() sub our Amount is the
// new amount
pItem->setAmount( pItem->amount() - ( 65535 - pCont->amount() ) );
}
}
// We dropped the item NOT on a container
// And were *un*able to stack it (!)
// >> Set it to the location of the item we dropped it on and stack it up by 2
pItem->moveTo( pCont->pos() );
pItem->setPos( pItem->pos() + Coord_cl(0, 0, 2) );
pItem->update();
/* // This needs to be checked
// It annoyingly shows the spellbook
// whenever you add a scroll
// << could it be that addItemToContainer is enough?? >>
if( pCont->type() == 9 )
Magic->openSpellBook( pChar, pCont );*/
}
示例13: dropOnItem
//.........这里部分代码省略.........
if ( !pChar->canPickUp( pItem ) )
{
socket->bounceItem( pItem, BR_CANNOT_PICK_THAT_UP );
return;
}
// We drop something on the belongings of one of our playervendors
/* if( ( packOwner != NULL ) && ( packOwner->npcaitype() == 17 ) && packOwner->owner() == pChar )
{
socket->sysMessage( tr( "You drop something into your playervendor (unimplemented)" ) );
socket->bounceItem( pItem, BR_NO_REASON );
return;
}*/
// Playervendors (chest equipped by the vendor - opened to the client)
/*if( !( pCont->pileable() && pItem->pileable() && pCont->id() == pItem->id() || ( pCont->type() != 1 && pCont->type() != 9 ) ) )
{
P_CHAR pc_j = GetPackOwner(pCont);
if (pc_j != NULL)
{
if (pc_j->npcaitype() == 17 && pc_j->isNpc() && pChar->Owns(pc_j))
{
pChar->inputitem = pItem->serial;
pChar->inputmode = cChar::enPricing;
sysmessage(s, "Set a price for this item.");
}
}
*/
// We may also drop into *any* locked chest
// So we can have post-boxes ;o)
if ( pCont->type() == 1 )
{
// If we're dropping it onto the closed container
if ( dropPos.x == 0xFFFF && dropPos.y == 0xFFFF )
{
pCont->addItem( pItem );
}
else
{
pCont->addItem( pItem, false );
pItem->setPos( dropPos );
}
// Dropped on another Container/in another Container
pChar->soundEffect( 0x57 );
pItem->update();
return;
}
else if ( pCont->canStack( pItem ) )
{
if ( pCont->amount() + pItem->amount() <= 65535 )
{
pCont->setAmount( pCont->amount() + pItem->amount() );
pItem->remove();
pCont->update(); // Need to update the amount
pCont->resendTooltip();
return;
}
else
{
// The delta between 65535 and pCont->amount() sub our Amount is the
// new amount
pItem->setAmount( pItem->amount() - ( 65535 - pCont->amount() ) );
pItem->resendTooltip();
pCont->setAmount( 65535 ); // Max out the amount
pCont->update();
pCont->resendTooltip();
}
}
// We dropped the item NOT on a container
// And were *un*able to stack it (!)
// >> Set it to the location of the item we dropped it on and stack it up by 2
if ( pCont->container() )
{
P_ITEM pNewCont = dynamic_cast<P_ITEM>( pCont->container() );
if ( pNewCont )
{
pNewCont->addItem( pItem, false );
pItem->setPos( pCont->pos() + Coord_cl( 0, 0, 2 ) );
}
else
{
pChar->getBackpack()->addItem( pItem );
}
}
else
{
pItem->removeFromCont();
pItem->moveTo( pCont->pos() + Coord_cl( 0, 0, 2 ) );
}
pItem->update();
}
示例14: iIter
// The highest items will be @ the beginning
// While walking we always will try the highest first.
vector< stBlockItem > getBlockingItems( P_CHAR pChar, const Coord_cl& pos )
{
vector<stBlockItem> blockList;
make_heap( blockList.begin(), blockList.end(), compareTiles() );
// Process the map at that position
stBlockItem mapBlock;
mapBlock.maptile = true;
mapBlock.z = Maps::instance()->mapAverageElevation( pos );
mapBlock.height = 0;
// TODO: Calculate the REAL average Z Value of that Map Tile here! Otherwise clients will have minor walking problems.
map_st mapCell = Maps::instance()->seekMap( pos );
//mapBlock.z = mapCell.z;*/
land_st mapTile = TileCache::instance()->getLand( mapCell.id );
// If it's not impassable it's automatically walkable
if ( !( mapTile.flag1 & 0x40 ) )
mapBlock.walkable = true;
else
mapBlock.walkable = checkWalkable( pChar, mapCell.id );
if ( mapCell.id != 0x02 )
{
blockList.push_back( mapBlock );
push_heap( blockList.begin(), blockList.end(), compareTiles() );
}
// Now for the static-items
StaticsIterator staIter = Maps::instance()->staticsIterator( pos, true );
for ( ; !staIter.atEnd(); ++staIter )
{
tile_st tTile = TileCache::instance()->getTile( staIter->itemid );
// Here is decided if the tile is needed
// It's uninteresting if it's NOT blocking
// And NOT a bridge/surface
if ( !( ( tTile.flag2 & 0x02 ) || ( tTile.flag1 & 0x40 ) || ( tTile.flag2 & 0x04 ) ) )
continue;
stBlockItem staticBlock;
staticBlock.z = staIter->zoff;
// If we are a surface we can always walk here, otherwise check if
// we are special
if ( ( tTile.flag2 & 0x02 ) && !( tTile.flag1 & 0x40 ) )
staticBlock.walkable = true;
else
staticBlock.walkable = checkWalkable( pChar, staIter->itemid );
// If we are a stair only the half height counts (round up)
if ( tTile.flag2 & 0x04 )
staticBlock.height = ( Q_UINT8 ) ( ( tTile.height + 1 ) / 2 );
else
staticBlock.height = tTile.height;
blockList.push_back( staticBlock );
push_heap( blockList.begin(), blockList.end(), compareTiles() );
}
RegionIterator4Items iIter( pos );
for ( iIter.Begin(); !iIter.atEnd(); iIter++ )
{
P_ITEM pItem = iIter.GetData();
if ( !pItem )
continue;
if ( pItem->id() >= 0x4000 )
{
MultiDefinition* def = MultiCache::instance()->getMulti( pItem->id() - 0x4000 );
if ( !def )
continue;
QValueVector<multiItem_st> multi = def->getEntries();
unsigned int j;
for ( j = 0; j < multi.size(); ++j )
{
if ( multi[j].visible && ( pItem->pos().x + multi[j].x == pos.x ) && ( pItem->pos().y + multi[j].y == pos.y ) )
{
tile_st tTile = TileCache::instance()->getTile( multi[j].tile );
if ( !( ( tTile.flag2 & 0x02 ) || ( tTile.flag1 & 0x40 ) || ( tTile.flag2 & 0x04 ) ) )
continue;
stBlockItem blockItem;
blockItem.height = tTile.height;
blockItem.z = pItem->pos().z + multi[j].z;
if ( ( tTile.flag2 & 0x02 ) && !( tTile.flag1 & 0x40 ) )
blockItem.walkable = true;
else
blockItem.walkable = checkWalkable( pChar, pItem->id() );
blockList.push_back( blockItem );
push_heap( blockList.begin(), blockList.end(), compareTiles() );
}
}
continue;
}
//.........这里部分代码省略.........
示例15: lineOfSight
bool Coord_cl::lineOfSight( const Coord_cl &target, UI16 targetheight, bool touch )
{
//Console::instance()->send( QString( "LOScheck: Source:%1,Target:%2,Targetheight:%3\n" ).arg( z ).arg( target.z ).arg( targetheight ) );
if( target.map != map )
return false;
if( (x == target.x) && (y == target.y) && (z == target.z) )
return true; // if source and target are on the same position
SI32 n = ( target.x - x ), m = ( target.y - y ), i = 0;
SI08 sgn_x = ( x <= target.x ) ? 1 : (-1); // signum for x
SI08 sgn_y = ( y <= target.y ) ? 1 : (-1); // signum for y
SI08 sgn_z = ( z <= target.z ) ? 1 : (-1); // signum for z
if( x == target.x )
sgn_x = 0;
if( y == target.y )
sgn_y = 0;
if( z == target.z )
sgn_z = 0;
QValueList< Coord_cl > collisions;
//first we get our x-y-coordinates
if( sgn_x == 0 && sgn_y == 0 && !sgn_z == 0 ) // should fix shooting through floor issues
{
collisions.push_back( Coord_cl( x, y, 0, map ) );
}
else if( sgn_x == 0 ) // if we are on the same x-level, just push every x/y coordinate in y-direction from src to trg into the array
for( i = 0; i <= (sgn_y * m); ++i )
{
collisions.push_back( Coord_cl( x, y + (sgn_y * i), 0, map ) );
}
else if ( sgn_y == 0 ) // if we are on the same y-level, just push every x/y coordinate in x-direction from src to trg into the array
for( i = 0; i <= (sgn_x * n); ++i )
{
collisions.push_back( Coord_cl( x + (sgn_x * i), y, 0, map ) );
}
else
{
SI32 oldpos = y;
bool exaktpos = false;
for( i = 0; (sgn_x * n >= sgn_y * m) && (i <= (sgn_x * n)); i++ )
{
//Console::instance()->send( QString( "x:%1\n" ).arg( i ) );
SI32 gridx = x + (sgn_x * i);
if( ( ( n == 0 ) && ( gridx == 0 ) ) ||
( ( n + ( gridx * m ) == 0 ) ) )
continue;
else
{
if( exaktpos )
{
collisions.push_back( Coord_cl( gridx, oldpos-sgn_y, 0, map ) );
//Console::instance()->send( QString( "add exaktpos coordinate %1,%2\n" ).arg( gridx ).arg( oldpos-sgn_y ) );
exaktpos = false;
}
// linear evaluation of extended 2x2 matrix, abbreviated
double t = (double)sgn_x * ((double)i+0.5) * (double)m / (double)n + (double)y;
//Console::instance()->send( QString( "t:%1\n" ).arg( t ) );
if( ((sgn_y>0) && (specialFloor(t)==oldpos+0.5)) || ((sgn_y<0) && (specialFloor(t)==oldpos-0.5)) )
{
exaktpos = true;
}
if( ((sgn_y>0) && (t<oldpos+0.5)) || ((sgn_y<0) && (t>oldpos-0.5)) || (oldpos==target.y) )
{
collisions.push_back( Coord_cl( gridx, oldpos, 0, map ) );
//Console::instance()->send( QString( "add coordinate %1,%2\n" ).arg( gridx ).arg( oldpos ) );
}
// but if not, we have to take BOTH coordinates, which the calculated collision is between!
else
{
collisions.push_back( Coord_cl( gridx, oldpos, 0, map ) );
//Console::instance()->send( QString( "add coordinate %1,%2\n" ).arg( gridx ).arg( oldpos ) );
oldpos += sgn_y;
collisions.push_back( Coord_cl( gridx, oldpos, 0, map ) );
//Console::instance()->send( QString( "add coordinate %1,%2\n" ).arg( gridx ).arg( oldpos ) );
}
}
}
oldpos = x;
exaktpos = false;
for( i = 0; (sgn_y * m >= sgn_x * n) && (i <= (sgn_y * m)); ++i )
{
//Console::instance()->send( QString( "y:%1\n" ).arg( i ) );
SI32 gridy = y + (sgn_y * i);
if( ( ( m == 0 ) && ( gridy == 0 ) ) ||
( ( m + ( gridy * n ) == 0 ) ) )
continue;
else
{
if( exaktpos )
{
collisions.push_back( Coord_cl( oldpos-sgn_x, gridy, 0, map ) );
//Console::instance()->send( QString( "add exaktpos coordinate %1,%2\n" ).arg( oldpos-sgn_x ).arg( gridy ) );
exaktpos = false;
}
//.........这里部分代码省略.........