forked from oerkki/voxelands
Fixed TODO and a bug, and moved raycast to Map
Now you can not hit an active object if there is a node in front of it. You can only select nodes if they are not farther than d. The raycasting algorithm was sliced into raycast() and createHilightbox(). raycast() was moved into Map so it can be used in hostile creatures' AIs.
This commit is contained in:
parent
1c217f6596
commit
0135630a4a
552
src/game.cpp
552
src/game.cpp
|
@ -248,296 +248,126 @@ public:
|
|||
};
|
||||
|
||||
/*
|
||||
Find what the player is pointing at
|
||||
*/
|
||||
void getPointedNode(Client *client,
|
||||
v3f camera_direction,v3f camera_position,
|
||||
bool &nodefound, core::line3d<f32> shootline,
|
||||
v3s16 &nodepos, v3s16 &neighbourpos, v3s16 camera_offset,
|
||||
core::aabbox3d<f32> &nodehilightbox,
|
||||
f32 d)
|
||||
{
|
||||
//inventory
|
||||
InventoryItem *wield = (InventoryItem*)client->getLocalPlayer()->getWieldItem();
|
||||
bool wield_is_hand = (wield == NULL);
|
||||
bool wield_is_tool = (wield && wield->getContent()&CONTENT_TOOLITEM_MASK);
|
||||
bool wield_is_craft = (wield && wield->getContent()&CONTENT_CRAFTITEM_MASK);
|
||||
bool wield_is_material = (!wield_is_hand && !wield_is_tool && !wield_is_craft);
|
||||
//initialize iteration
|
||||
content_t content = CONTENT_IGNORE;
|
||||
v3s16 cam_i = floatToInt(camera_position, BS);
|
||||
//coordinates of current node
|
||||
s16 x=cam_i.X;
|
||||
s16 y=cam_i.Y;
|
||||
s16 z=cam_i.Z;
|
||||
s16 oldx=x;
|
||||
s16 oldy=y;
|
||||
s16 oldz=z;
|
||||
v3f norm_pos=camera_position/BS;//divide by BS so one node is one unit
|
||||
v3f norm_dir=v3f(camera_direction);
|
||||
norm_dir.normalize();
|
||||
norm_dir*=d;
|
||||
f32 rx=2;//ratio by which we multiply norm_dir to hit node (ratio x)
|
||||
f32 rxs=1;//incrementing rx by rxs gives the next node in x direction (ratio x step)
|
||||
s16 xs=1;//incrementing rx involves incrementing x by xs (x step)
|
||||
if(norm_dir.X>0){//set rx,rxs and xs
|
||||
rx=(floorf(norm_pos.X-0.5)+1.5-norm_pos.X)/norm_dir.X;
|
||||
rxs=1/norm_dir.X;
|
||||
}else if(norm_dir.X<0){
|
||||
rx=(floorf(norm_pos.X-0.5)-norm_pos.X+0.5)/norm_dir.X;
|
||||
rxs=-1/norm_dir.X;
|
||||
xs=-1;
|
||||
}//other directions
|
||||
f32 rz=2;
|
||||
f32 rzs=1;
|
||||
s16 zs=1;
|
||||
if(norm_dir.Z>0){
|
||||
rz=(floorf(norm_pos.Z-0.5)+1.5-norm_pos.Z)/norm_dir.Z;
|
||||
rzs=1/norm_dir.Z;
|
||||
}else if(norm_dir.Z<0){
|
||||
rz=(floorf(norm_pos.Z-0.5)-norm_pos.Z+0.5)/norm_dir.Z;
|
||||
rzs=-1/norm_dir.Z;
|
||||
zs=-1;
|
||||
* Creates a hilightbox for the given node
|
||||
*/
|
||||
void createHilightbox(Map *map, v3s16 nodepos,
|
||||
v3s16 camera_offset, core::aabbox3d<f32> &nodehilightbox
|
||||
){
|
||||
MapNode n;
|
||||
try
|
||||
{
|
||||
n = map->getNode(nodepos);
|
||||
}
|
||||
f32 ry=2;
|
||||
f32 rys=1;
|
||||
s16 ys=1;
|
||||
if(norm_dir.Y>0){
|
||||
ry=(floorf(norm_pos.Y-0.5)+1.5-norm_pos.Y)/norm_dir.Y;
|
||||
rys=1/norm_dir.Y;
|
||||
}else if(norm_dir.Y<0){
|
||||
ry=(floorf(norm_pos.Y-0.5)-norm_pos.Y+0.5)/norm_dir.Y;
|
||||
rys=-1/norm_dir.Y;
|
||||
ys=-1;
|
||||
catch(InvalidPositionException &e)
|
||||
{
|
||||
return;
|
||||
}
|
||||
//now iterate through nodes
|
||||
do{
|
||||
bool testable=true;
|
||||
MapNode n;
|
||||
try
|
||||
{
|
||||
n = client->getNode(v3s16(x,y,z));
|
||||
if (content_features(n.getContent()).pointable == false) {
|
||||
if (content_features(n.getContent()).liquid_type != LIQUID_SOURCE)
|
||||
testable=false;
|
||||
if (!wield || content_toolitem_features(wield->getContent()).liquids_pointable == false)
|
||||
testable=false;
|
||||
}else if (content_features(n.getContent()).material_pointable == false && wield_is_material) {
|
||||
testable=false;
|
||||
}
|
||||
}
|
||||
catch(InvalidPositionException &e)
|
||||
{
|
||||
testable=false;
|
||||
}
|
||||
//if node is valid
|
||||
if(testable){
|
||||
v3s16 np(x,y,z);
|
||||
v3f npf = intToFloat(np, BS);
|
||||
|
||||
f32 d = 0.01;
|
||||
|
||||
v3s16 dirs[6] = {
|
||||
v3s16(0,0,1), // back
|
||||
v3s16(0,1,0), // top
|
||||
v3s16(1,0,0), // right
|
||||
v3s16(0,0,-1), // front
|
||||
v3s16(0,-1,0), // bottom
|
||||
v3s16(-1,0,0), // left
|
||||
};
|
||||
|
||||
/*
|
||||
Meta-objects
|
||||
*/
|
||||
//TODO Test whether the distance of box-shootline intersection point and camera position is not larger than d*BS
|
||||
if(n.getContent() == CONTENT_TORCH) {
|
||||
v3s16 dir = unpackDir(n.param2);
|
||||
v3f dir_f = v3f(dir.X, dir.Y, dir.Z);
|
||||
dir_f *= BS/2 - BS/6 - BS/20;
|
||||
v3f cpf = npf + dir_f;
|
||||
v3f npf = intToFloat(nodepos, BS);
|
||||
|
||||
/*
|
||||
Meta-objects
|
||||
*/
|
||||
if(n.getContent() == CONTENT_TORCH) {
|
||||
v3s16 dir = unpackDir(n.param2);
|
||||
v3f dir_f = v3f(dir.X, dir.Y, dir.Z);
|
||||
dir_f *= BS/2 - BS/6 - BS/20;
|
||||
v3f cpf = npf + dir_f;
|
||||
core::aabbox3d<f32> box;
|
||||
|
||||
// bottom
|
||||
if(dir == v3s16(0,-1,0))
|
||||
{
|
||||
box = core::aabbox3d<f32>(
|
||||
npf - v3f(BS/6, BS/2, BS/6),
|
||||
npf + v3f(BS/6, -BS/2+BS/3*2, BS/6)
|
||||
);
|
||||
}
|
||||
// top
|
||||
else if(dir == v3s16(0,1,0))
|
||||
{
|
||||
box = core::aabbox3d<f32>(
|
||||
npf - v3f(BS/6, -BS/2+BS/3*2, BS/6),
|
||||
npf + v3f(BS/6, BS/2, BS/6)
|
||||
);
|
||||
}
|
||||
// side
|
||||
else
|
||||
{
|
||||
box = core::aabbox3d<f32>(
|
||||
cpf - v3f(BS/6, BS/3, BS/6),
|
||||
cpf + v3f(BS/6, BS/3, BS/6)
|
||||
);
|
||||
}
|
||||
if(box.intersectsWithLine(shootline))
|
||||
{
|
||||
nodefound = true;
|
||||
nodepos = np;
|
||||
content = n.getContent();
|
||||
neighbourpos = np;
|
||||
box.MinEdge -= intToFloat(camera_offset,BS);
|
||||
box.MaxEdge -= intToFloat(camera_offset,BS);
|
||||
nodehilightbox = box;
|
||||
}
|
||||
}else if(n.getContent() == CONTENT_RAIL) {
|
||||
float d = (float)BS/8;
|
||||
v3f vertices[4] =
|
||||
{
|
||||
v3f(BS/2, -BS/2+d, -BS/2),
|
||||
v3f(-BS/2, -BS/2, BS/2),
|
||||
};
|
||||
|
||||
for(s32 i=0; i<2; i++)
|
||||
{
|
||||
vertices[i] += npf;
|
||||
}
|
||||
|
||||
core::aabbox3d<f32> box;
|
||||
|
||||
box = core::aabbox3d<f32>(vertices[0]);
|
||||
box.addInternalPoint(vertices[1]);
|
||||
|
||||
if(box.intersectsWithLine(shootline))
|
||||
{
|
||||
nodefound = true;
|
||||
nodepos = np;
|
||||
content = n.getContent();
|
||||
neighbourpos = np;
|
||||
box.MinEdge -= intToFloat(camera_offset,BS);
|
||||
box.MaxEdge -= intToFloat(camera_offset,BS);
|
||||
nodehilightbox = box;
|
||||
}
|
||||
/*
|
||||
Roofs and Node boxes
|
||||
*/
|
||||
}else if (
|
||||
content_features(n).draw_type == CDT_NODEBOX
|
||||
|| content_features(n).draw_type == CDT_NODEBOX_META
|
||||
|| content_features(n).draw_type == CDT_WIRELIKE
|
||||
|| content_features(n).draw_type == CDT_3DWIRELIKE
|
||||
|| content_features(n).draw_type == CDT_FENCELIKE
|
||||
|| content_features(n).draw_type == CDT_WALLLIKE
|
||||
|| content_features(n).draw_type == CDT_STAIRLIKE
|
||||
|| content_features(n).draw_type == CDT_SLABLIKE
|
||||
|| content_features(n).draw_type == CDT_FLAGLIKE
|
||||
) {
|
||||
aabb3f box;
|
||||
aabb3f nhbox(0.5*BS,0.5*BS,0.5*BS,-0.5*BS,-0.5*BS,-0.5*BS);
|
||||
bool hit = false;
|
||||
std::vector<NodeBox> boxes = content_features(n).getNodeBoxes(n);
|
||||
for (std::vector<NodeBox>::iterator b = boxes.begin(); b != boxes.end(); b++) {
|
||||
box = b->m_box;
|
||||
if (nhbox.MinEdge.X > box.MinEdge.X)
|
||||
nhbox.MinEdge.X = box.MinEdge.X;
|
||||
if (nhbox.MinEdge.Y > box.MinEdge.Y)
|
||||
nhbox.MinEdge.Y = box.MinEdge.Y;
|
||||
if (nhbox.MinEdge.Z > box.MinEdge.Z)
|
||||
nhbox.MinEdge.Z = box.MinEdge.Z;
|
||||
if (nhbox.MaxEdge.X < box.MaxEdge.X)
|
||||
nhbox.MaxEdge.X = box.MaxEdge.X;
|
||||
if (nhbox.MaxEdge.Y < box.MaxEdge.Y)
|
||||
nhbox.MaxEdge.Y = box.MaxEdge.Y;
|
||||
if (nhbox.MaxEdge.Z < box.MaxEdge.Z)
|
||||
nhbox.MaxEdge.Z = box.MaxEdge.Z;
|
||||
box.MinEdge += npf;
|
||||
box.MaxEdge += npf;
|
||||
if (box.intersectsWithLine(shootline)) {
|
||||
for(u16 i=0; i<6; i++) {
|
||||
v3f dir_f = v3f(dirs[i].X,
|
||||
dirs[i].Y, dirs[i].Z);
|
||||
|
||||
core::CMatrix4<f32> m;
|
||||
m.buildRotateFromTo(v3f(0,0,1), dir_f);
|
||||
|
||||
// This is the back face
|
||||
v3f corners[2] = {
|
||||
v3f(BS/2, BS/2, BS/2),
|
||||
v3f(-BS/2, -BS/2, BS/2+d)
|
||||
};
|
||||
for(u16 j=0; j<2; j++)
|
||||
{
|
||||
m.rotateVect(corners[j]);
|
||||
corners[j] += npf;
|
||||
}
|
||||
core::aabbox3d<f32> facebox(corners[0]);
|
||||
facebox.addInternalPoint(corners[1]);
|
||||
|
||||
if(facebox.intersectsWithLine(shootline))
|
||||
{
|
||||
nodefound = true;
|
||||
nodepos = np;
|
||||
content = n.getContent();
|
||||
neighbourpos = np + dirs[i];
|
||||
hit = true;
|
||||
}
|
||||
} // for dirs
|
||||
}
|
||||
}
|
||||
if (hit) {
|
||||
nhbox.MinEdge -= 0.002;
|
||||
nhbox.MaxEdge += 0.002;
|
||||
v3f nodepos_f = intToFloat(nodepos-camera_offset, BS);
|
||||
nhbox.MinEdge += nodepos_f;
|
||||
nhbox.MaxEdge += nodepos_f;
|
||||
nodehilightbox = nhbox;
|
||||
}
|
||||
boxes.clear();
|
||||
|
||||
/*
|
||||
Regular blocks
|
||||
*/
|
||||
}else{
|
||||
nodefound = true;
|
||||
nodepos = np;
|
||||
content = n.getContent();
|
||||
neighbourpos.set(oldx,oldy,oldz);
|
||||
const float d = 0.502;
|
||||
core::aabbox3d<f32> nodebox
|
||||
(-BS*d, -BS*d, -BS*d, BS*d, BS*d, BS*d);
|
||||
v3f nodepos_f = intToFloat(nodepos-camera_offset, BS);
|
||||
nodebox.MinEdge += nodepos_f;
|
||||
nodebox.MaxEdge += nodepos_f;
|
||||
nodehilightbox = nodebox;
|
||||
} // regular block
|
||||
} //testable
|
||||
//if found node, it is the closest
|
||||
if(nodefound)break;
|
||||
//check if we can step forward
|
||||
if(rx>1&&ry>1&&rz>1)break;
|
||||
//step to next node
|
||||
oldx=x;
|
||||
oldy=y;
|
||||
oldz=z;
|
||||
if((rx<ry)&&(rx<rz)){
|
||||
rx+=rxs;
|
||||
x+=xs;
|
||||
}else if(ry<rz){
|
||||
ry+=rys;
|
||||
y+=ys;
|
||||
}else{
|
||||
rz+=rzs;
|
||||
z+=zs;
|
||||
if(dir == v3s16(0,-1,0))
|
||||
{
|
||||
box = core::aabbox3d<f32>(
|
||||
npf - v3f(BS/6, BS/2, BS/6),
|
||||
npf + v3f(BS/6, -BS/2+BS/3*2, BS/6)
|
||||
);
|
||||
}
|
||||
}while(true);
|
||||
if (nodefound) {
|
||||
client->setPointedNode(nodepos);
|
||||
client->setPointedContent(content);
|
||||
// top
|
||||
else if(dir == v3s16(0,1,0))
|
||||
{
|
||||
box = core::aabbox3d<f32>(
|
||||
npf - v3f(BS/6, -BS/2+BS/3*2, BS/6),
|
||||
npf + v3f(BS/6, BS/2, BS/6)
|
||||
);
|
||||
}
|
||||
// side
|
||||
else
|
||||
{
|
||||
box = core::aabbox3d<f32>(
|
||||
cpf - v3f(BS/6, BS/3, BS/6),
|
||||
cpf + v3f(BS/6, BS/3, BS/6)
|
||||
);
|
||||
}
|
||||
box.MinEdge -= intToFloat(camera_offset,BS);
|
||||
box.MaxEdge -= intToFloat(camera_offset,BS);
|
||||
nodehilightbox = box;
|
||||
}else if(n.getContent() == CONTENT_RAIL) {
|
||||
float d = (float)BS/8;
|
||||
v3f vertices[4] =
|
||||
{
|
||||
v3f(BS/2, -BS/2+d, -BS/2),
|
||||
v3f(-BS/2, -BS/2, BS/2),
|
||||
};
|
||||
for(s32 i=0; i<2; i++)
|
||||
{
|
||||
vertices[i] += npf;
|
||||
}
|
||||
core::aabbox3d<f32> box;
|
||||
box = core::aabbox3d<f32>(vertices[0]);
|
||||
box.addInternalPoint(vertices[1]);
|
||||
box.MinEdge -= intToFloat(camera_offset,BS);
|
||||
box.MaxEdge -= intToFloat(camera_offset,BS);
|
||||
nodehilightbox = box;
|
||||
/*
|
||||
Roofs and Node boxes
|
||||
*/
|
||||
}else if (
|
||||
content_features(n).draw_type == CDT_NODEBOX
|
||||
|| content_features(n).draw_type == CDT_NODEBOX_META
|
||||
|| content_features(n).draw_type == CDT_WIRELIKE
|
||||
|| content_features(n).draw_type == CDT_3DWIRELIKE
|
||||
|| content_features(n).draw_type == CDT_FENCELIKE
|
||||
|| content_features(n).draw_type == CDT_WALLLIKE
|
||||
|| content_features(n).draw_type == CDT_STAIRLIKE
|
||||
|| content_features(n).draw_type == CDT_SLABLIKE
|
||||
|| content_features(n).draw_type == CDT_FLAGLIKE
|
||||
) {
|
||||
aabb3f box;
|
||||
aabb3f nhbox(0.5*BS,0.5*BS,0.5*BS,-0.5*BS,-0.5*BS,-0.5*BS);
|
||||
std::vector<NodeBox> boxes = content_features(n).getNodeBoxes(n);
|
||||
for (std::vector<NodeBox>::iterator b = boxes.begin(); b != boxes.end(); b++) {
|
||||
box = b->m_box;
|
||||
if (nhbox.MinEdge.X > box.MinEdge.X)
|
||||
nhbox.MinEdge.X = box.MinEdge.X;
|
||||
if (nhbox.MinEdge.Y > box.MinEdge.Y)
|
||||
nhbox.MinEdge.Y = box.MinEdge.Y;
|
||||
if (nhbox.MinEdge.Z > box.MinEdge.Z)
|
||||
nhbox.MinEdge.Z = box.MinEdge.Z;
|
||||
if (nhbox.MaxEdge.X < box.MaxEdge.X)
|
||||
nhbox.MaxEdge.X = box.MaxEdge.X;
|
||||
if (nhbox.MaxEdge.Y < box.MaxEdge.Y)
|
||||
nhbox.MaxEdge.Y = box.MaxEdge.Y;
|
||||
if (nhbox.MaxEdge.Z < box.MaxEdge.Z)
|
||||
nhbox.MaxEdge.Z = box.MaxEdge.Z;
|
||||
}
|
||||
nhbox.MinEdge -= 0.002;
|
||||
nhbox.MaxEdge += 0.002;
|
||||
v3f nodepos_f = intToFloat(nodepos-camera_offset, BS);
|
||||
nhbox.MinEdge += nodepos_f;
|
||||
nhbox.MaxEdge += nodepos_f;
|
||||
nodehilightbox = nhbox;
|
||||
boxes.clear();
|
||||
/*
|
||||
Regular blocks
|
||||
*/
|
||||
}else{
|
||||
client->setPointedContent(CONTENT_IGNORE);
|
||||
}
|
||||
const float d = 0.502;
|
||||
core::aabbox3d<f32> nodebox
|
||||
(-BS*d, -BS*d, -BS*d, BS*d, BS*d, BS*d);
|
||||
v3f nodepos_f = intToFloat(nodepos-camera_offset, BS);
|
||||
nodebox.MinEdge += nodepos_f;
|
||||
nodebox.MaxEdge += nodepos_f;
|
||||
nodehilightbox = nodebox;
|
||||
} // regular block
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1552,82 +1382,101 @@ void the_game(
|
|||
*/
|
||||
|
||||
f32 d = 4; // max. distance
|
||||
core::line3d<f32> shootline(camera_position, camera_position + camera_direction * BS * (d+1));
|
||||
|
||||
core::line3d<f32> shootline(camera_position, camera_position + camera_direction * BS * d);
|
||||
//which is closer: the active object or the block?
|
||||
ClientActiveObject *selected_active_object = client.getSelectedActiveObject(d*BS, camera_position, shootline);
|
||||
|
||||
if (selected_active_object != NULL) {
|
||||
has_selected_node = false;
|
||||
client.setPointedContent(selected_active_object->getContent());
|
||||
/* Clear possible cracking animation */
|
||||
f32 active_object_distance=(d+10)*BS;
|
||||
if(selected_active_object!=NULL)
|
||||
active_object_distance=(selected_active_object->getPosition()-camera_position).getLength();
|
||||
//search node
|
||||
bool nodefound = false;
|
||||
v3s16 nodepos;
|
||||
v3s16 neighbourpos;
|
||||
core::aabbox3d<f32> nodehilightbox;
|
||||
content_t content=CONTENT_IGNORE;
|
||||
//inventory test
|
||||
InventoryItem *wield = (InventoryItem*)client.getLocalPlayer()->getWieldItem();
|
||||
bool wield_is_hand = (wield == NULL);
|
||||
bool wield_is_tool = (wield && wield->getContent()&CONTENT_TOOLITEM_MASK);
|
||||
bool wield_is_craft = (wield && wield->getContent()&CONTENT_CRAFTITEM_MASK);
|
||||
bool wield_is_material = (!wield_is_hand && !wield_is_tool && !wield_is_craft);
|
||||
bool ignore_liquids=!wield || content_toolitem_features(wield->getContent()).liquids_pointable == false;
|
||||
client.getEnv().getMap().raycast(
|
||||
camera_direction, camera_position, d,
|
||||
ignore_liquids,wield_is_material,
|
||||
nodefound, nodepos, neighbourpos);
|
||||
f32 node_distance=(d+10)*BS;
|
||||
if(nodefound){
|
||||
node_distance=(intToFloat(nodepos, BS)-camera_position).getLength();
|
||||
}
|
||||
if(active_object_distance<node_distance)
|
||||
nodefound=false;
|
||||
else
|
||||
selected_active_object=NULL;
|
||||
if(!nodefound){
|
||||
if (nodepos_old != v3s16(-32768,-32768,-32768)) {
|
||||
dig_time = 0.0;
|
||||
nodepos_old = v3s16(-32768,-32768,-32768);
|
||||
}
|
||||
|
||||
core::aabbox3d<f32> *selection_box
|
||||
= selected_active_object->getSelectionBox();
|
||||
// Box should exist because object was returned in the
|
||||
// first place
|
||||
assert(selection_box);
|
||||
|
||||
v3f pos = selected_active_object->getPosition()-intToFloat(camera_offset,BS);
|
||||
|
||||
core::aabbox3d<f32> box_on_map(
|
||||
selection_box->MinEdge + pos,
|
||||
selection_box->MaxEdge + pos
|
||||
);
|
||||
|
||||
if (selected_active_object->doShowSelectionBox())
|
||||
hilightboxes.push_back(box_on_map);
|
||||
|
||||
infotext = narrow_to_wide(selected_active_object->infoText());
|
||||
|
||||
if (input->getLeftState()) {
|
||||
bool do_punch = false;
|
||||
bool do_punch_damage = false;
|
||||
if (object_hit_delay_timer <= 0.0){
|
||||
do_punch = true;
|
||||
do_punch_damage = true;
|
||||
object_hit_delay_timer = object_hit_delay;
|
||||
}
|
||||
if (input->getLeftClicked()) {
|
||||
do_punch = true;
|
||||
}
|
||||
if (do_punch) {
|
||||
infostream<<"Left-clicked object"<<std::endl;
|
||||
left_punch = true;
|
||||
}
|
||||
if (do_punch_damage) {
|
||||
client.clickActiveObject(0, selected_active_object->getId(), g_selected_item);
|
||||
}
|
||||
}else if (input->getRightClicked()) {
|
||||
infostream<<"Right-clicked object"<<std::endl;
|
||||
client.clickActiveObject(1, selected_active_object->getId(), g_selected_item);
|
||||
}
|
||||
}else{ // selected_object == NULL
|
||||
/*
|
||||
Find out which node we are pointing at
|
||||
*/
|
||||
|
||||
bool nodefound = false;
|
||||
v3s16 nodepos;
|
||||
v3s16 neighbourpos;
|
||||
core::aabbox3d<f32> nodehilightbox;
|
||||
|
||||
getPointedNode(&client,
|
||||
camera_direction, camera_position,
|
||||
nodefound, shootline,
|
||||
nodepos, neighbourpos, camera_offset,
|
||||
nodehilightbox, d);
|
||||
|
||||
if (!nodefound) {
|
||||
has_selected_node = false;
|
||||
}
|
||||
if(selected_active_object != NULL) {
|
||||
has_selected_node = false;
|
||||
client.setPointedContent(selected_active_object->getContent());
|
||||
/* Clear possible cracking animation */
|
||||
if (nodepos_old != v3s16(-32768,-32768,-32768)) {
|
||||
dig_time = 0.0;
|
||||
nodepos_old = v3s16(-32768,-32768,-32768);
|
||||
}
|
||||
has_selected_node = false;
|
||||
}else{
|
||||
|
||||
core::aabbox3d<f32> *selection_box
|
||||
= selected_active_object->getSelectionBox();
|
||||
// Box should exist because object was returned in the
|
||||
// first place
|
||||
assert(selection_box);
|
||||
|
||||
v3f pos = selected_active_object->getPosition()-intToFloat(camera_offset,BS);
|
||||
|
||||
core::aabbox3d<f32> box_on_map(
|
||||
selection_box->MinEdge + pos,
|
||||
selection_box->MaxEdge + pos
|
||||
);
|
||||
|
||||
if (selected_active_object->doShowSelectionBox())
|
||||
hilightboxes.push_back(box_on_map);
|
||||
|
||||
infotext = narrow_to_wide(selected_active_object->infoText());
|
||||
|
||||
if (input->getLeftState()) {
|
||||
bool do_punch = false;
|
||||
bool do_punch_damage = false;
|
||||
if (object_hit_delay_timer <= 0.0){
|
||||
do_punch = true;
|
||||
do_punch_damage = true;
|
||||
object_hit_delay_timer = object_hit_delay;
|
||||
}
|
||||
if (input->getLeftClicked()) {
|
||||
do_punch = true;
|
||||
}
|
||||
if (do_punch) {
|
||||
infostream<<"Left-clicked object"<<std::endl;
|
||||
left_punch = true;
|
||||
}
|
||||
if (do_punch_damage) {
|
||||
client.clickActiveObject(0, selected_active_object->getId(), g_selected_item);
|
||||
}
|
||||
}else if (input->getRightClicked()) {
|
||||
infostream<<"Right-clicked object"<<std::endl;
|
||||
client.clickActiveObject(1, selected_active_object->getId(), g_selected_item);
|
||||
}
|
||||
|
||||
}else{ // selected_active_object==NULL
|
||||
if(nodefound){
|
||||
content=client.getEnv().getMap().getNode(nodepos).getContent();
|
||||
createHilightbox(&client.getEnv().getMap(),nodepos,
|
||||
camera_offset,nodehilightbox);
|
||||
client.setPointedNode(nodepos);
|
||||
client.setPointedContent(content);
|
||||
has_selected_node = true;
|
||||
if (nodepos != selected_node_pos)
|
||||
selected_node_crack = 0;
|
||||
|
@ -1800,8 +1649,9 @@ void the_game(
|
|||
}
|
||||
|
||||
nodepos_old = nodepos;
|
||||
}else{
|
||||
client.setPointedContent(CONTENT_IGNORE);
|
||||
}
|
||||
|
||||
} // selected_object == NULL
|
||||
}
|
||||
|
||||
|
|
222
src/map.cpp
222
src/map.cpp
|
@ -42,6 +42,7 @@
|
|||
#include "settings.h"
|
||||
#include "log.h"
|
||||
#include "profiler.h"
|
||||
#include <matrix4.h>;
|
||||
|
||||
#define PP(x) "("<<(x).X<<","<<(x).Y<<","<<(x).Z<<")"
|
||||
|
||||
|
@ -1732,6 +1733,227 @@ void Map::nodeMetadataStep(float dtime, core::map<v3s16, MapBlock*> &changed_blo
|
|||
}
|
||||
}
|
||||
|
||||
void Map::raycast(v3f camera_direction,
|
||||
v3f camera_position, f32 d,
|
||||
bool ignore_liquids, bool ignore_not_material_pointable,
|
||||
bool &nodefound, v3s16 &nodepos, v3s16 &neighbourpos)
|
||||
{
|
||||
//initialize iteration
|
||||
v3s16 cam_i = floatToInt(camera_position, BS);
|
||||
//coordinates of current node
|
||||
s16 x = cam_i.X;
|
||||
s16 y = cam_i.Y;
|
||||
s16 z = cam_i.Z;
|
||||
s16 oldx = x;
|
||||
s16 oldy = y;
|
||||
s16 oldz = z;
|
||||
v3f norm_pos = camera_position / BS;//divide by BS so one node is one unit
|
||||
v3f norm_dir = v3f(camera_direction);
|
||||
norm_dir.normalize();
|
||||
norm_dir *= d;
|
||||
//create shootline
|
||||
core::line3d<f32> shootline(camera_position,
|
||||
camera_position + norm_dir * BS);
|
||||
f32 rx = 2; //ratio by which we multiply norm_dir to hit node (ratio x)
|
||||
f32 rxs = 1;//incrementing rx by rxs gives the next node in x direction (ratio x step)
|
||||
s16 xs = 1; //incrementing rx involves incrementing x by xs (x step)
|
||||
if (norm_dir.X > 0) { //set rx,rxs and xs
|
||||
rx = (floorf(norm_pos.X - 0.5) + 1.5 - norm_pos.X) / norm_dir.X;
|
||||
rxs = 1 / norm_dir.X;
|
||||
} else if (norm_dir.X < 0) {
|
||||
rx = (floorf(norm_pos.X - 0.5) - norm_pos.X + 0.5) / norm_dir.X;
|
||||
rxs = -1 / norm_dir.X;
|
||||
xs = -1;
|
||||
} //other directions
|
||||
f32 rz = 2;
|
||||
f32 rzs = 1;
|
||||
s16 zs = 1;
|
||||
if (norm_dir.Z > 0) {
|
||||
rz = (floorf(norm_pos.Z - 0.5) + 1.5 - norm_pos.Z) / norm_dir.Z;
|
||||
rzs = 1 / norm_dir.Z;
|
||||
} else if (norm_dir.Z < 0) {
|
||||
rz = (floorf(norm_pos.Z - 0.5) - norm_pos.Z + 0.5) / norm_dir.Z;
|
||||
rzs = -1 / norm_dir.Z;
|
||||
zs = -1;
|
||||
}
|
||||
f32 ry = 2;
|
||||
f32 rys = 1;
|
||||
s16 ys = 1;
|
||||
if (norm_dir.Y > 0) {
|
||||
ry = (floorf(norm_pos.Y - 0.5) + 1.5 - norm_pos.Y) / norm_dir.Y;
|
||||
rys = 1 / norm_dir.Y;
|
||||
} else if (norm_dir.Y < 0) {
|
||||
ry = (floorf(norm_pos.Y - 0.5) - norm_pos.Y + 0.5) / norm_dir.Y;
|
||||
rys = -1 / norm_dir.Y;
|
||||
ys = -1;
|
||||
}
|
||||
//now iterate through nodes
|
||||
do {
|
||||
bool testable = true;
|
||||
MapNode n;
|
||||
try {
|
||||
n = getNode(v3s16(x, y, z));
|
||||
if (content_features(n.getContent()).pointable == false) {
|
||||
if (content_features(n.getContent()).liquid_type
|
||||
!= LIQUID_SOURCE)
|
||||
testable = false;
|
||||
if (ignore_liquids)
|
||||
testable = false;
|
||||
} else if (content_features(n.getContent()).material_pointable
|
||||
== false && ignore_not_material_pointable) {
|
||||
testable = false;
|
||||
}
|
||||
} catch (InvalidPositionException &e) {
|
||||
testable = false;
|
||||
}
|
||||
//if node is valid
|
||||
if (testable) {
|
||||
v3s16 np(x, y, z);
|
||||
v3f npf = intToFloat(np, BS);
|
||||
|
||||
f32 d = 0.01;
|
||||
|
||||
v3s16 dirs[6] = { v3s16(0, 0, 1), // back
|
||||
v3s16(0, 1, 0), // top
|
||||
v3s16(1, 0, 0), // right
|
||||
v3s16(0, 0, -1), // front
|
||||
v3s16(0, -1, 0), // bottom
|
||||
v3s16(-1, 0, 0), // left
|
||||
};
|
||||
|
||||
/*
|
||||
Meta-objects
|
||||
*/
|
||||
if (n.getContent() == CONTENT_TORCH) {
|
||||
v3s16 dir = unpackDir(n.param2);
|
||||
v3f dir_f = v3f(dir.X, dir.Y, dir.Z);
|
||||
dir_f *= BS / 2 - BS / 6 - BS / 20;
|
||||
v3f cpf = npf + dir_f;
|
||||
|
||||
core::aabbox3d<f32> box;
|
||||
|
||||
// bottom
|
||||
if (dir == v3s16(0, -1, 0)) {
|
||||
box = core::aabbox3d<f32>(npf - v3f(BS / 6, BS / 2, BS / 6),
|
||||
npf + v3f(BS / 6, -BS / 2 + BS / 3 * 2, BS / 6));
|
||||
}
|
||||
// top
|
||||
else if (dir == v3s16(0, 1, 0)) {
|
||||
box = core::aabbox3d<f32>(
|
||||
npf - v3f(BS / 6, -BS / 2 + BS / 3 * 2, BS / 6),
|
||||
npf + v3f(BS / 6, BS / 2, BS / 6));
|
||||
}
|
||||
// side
|
||||
else {
|
||||
box = core::aabbox3d<f32>(cpf - v3f(BS / 6, BS / 3, BS / 6),
|
||||
cpf + v3f(BS / 6, BS / 3, BS / 6));
|
||||
}
|
||||
if (box.intersectsWithLine(shootline)) {
|
||||
nodefound = true;
|
||||
nodepos = np;
|
||||
neighbourpos = np;
|
||||
}
|
||||
} else if (n.getContent() == CONTENT_RAIL) {
|
||||
float d = (float) BS / 8;
|
||||
v3f vertices[4] = { v3f(BS / 2, -BS / 2 + d, -BS / 2), v3f(
|
||||
-BS / 2, -BS / 2, BS / 2), };
|
||||
|
||||
for (s32 i = 0; i < 2; i++) {
|
||||
vertices[i] += npf;
|
||||
}
|
||||
|
||||
core::aabbox3d<f32> box;
|
||||
|
||||
box = core::aabbox3d<f32>(vertices[0]);
|
||||
box.addInternalPoint(vertices[1]);
|
||||
|
||||
if (box.intersectsWithLine(shootline)) {
|
||||
nodefound = true;
|
||||
nodepos = np;
|
||||
neighbourpos = np;
|
||||
}
|
||||
/*
|
||||
Roofs and Node boxes
|
||||
*/
|
||||
} else if (content_features(n).draw_type == CDT_NODEBOX
|
||||
|| content_features(n).draw_type == CDT_NODEBOX_META
|
||||
|| content_features(n).draw_type == CDT_WIRELIKE
|
||||
|| content_features(n).draw_type == CDT_3DWIRELIKE
|
||||
|| content_features(n).draw_type == CDT_FENCELIKE
|
||||
|| content_features(n).draw_type == CDT_WALLLIKE
|
||||
|| content_features(n).draw_type == CDT_STAIRLIKE
|
||||
|| content_features(n).draw_type == CDT_SLABLIKE
|
||||
|| content_features(n).draw_type == CDT_FLAGLIKE) {
|
||||
aabb3f box;
|
||||
std::vector<NodeBox> boxes = content_features(n).getNodeBoxes(
|
||||
n);
|
||||
for (std::vector<NodeBox>::iterator b = boxes.begin();
|
||||
b != boxes.end(); b++) {
|
||||
box = b->m_box;
|
||||
box.MinEdge += npf;
|
||||
box.MaxEdge += npf;
|
||||
if (box.intersectsWithLine(shootline)) {
|
||||
for (u16 i = 0; i < 6; i++) {
|
||||
v3f dir_f = v3f(dirs[i].X, dirs[i].Y, dirs[i].Z);
|
||||
|
||||
core::CMatrix4<f32> m;
|
||||
m.buildRotateFromTo(v3f(0, 0, 1), dir_f);
|
||||
|
||||
// This is the back face
|
||||
v3f corners[2] = { v3f(BS / 2, BS / 2, BS / 2), v3f(
|
||||
-BS / 2, -BS / 2, BS / 2 + d) };
|
||||
for (u16 j = 0; j < 2; j++) {
|
||||
m.rotateVect(corners[j]);
|
||||
corners[j] += npf;
|
||||
}
|
||||
core::aabbox3d<f32> facebox(corners[0]);
|
||||
facebox.addInternalPoint(corners[1]);
|
||||
|
||||
if (facebox.intersectsWithLine(shootline)) {
|
||||
nodefound = true;
|
||||
nodepos = np;
|
||||
neighbourpos = np + dirs[i];
|
||||
}
|
||||
} // for dirs
|
||||
}
|
||||
}
|
||||
boxes.clear();
|
||||
|
||||
/*
|
||||
Regular blocks
|
||||
*/
|
||||
} else {
|
||||
nodefound = true;
|
||||
nodepos = np;
|
||||
neighbourpos.set(oldx, oldy, oldz);
|
||||
const float d = 0.502;
|
||||
core::aabbox3d<f32> nodebox(-BS * d, -BS * d, -BS * d, BS * d,
|
||||
BS * d, BS * d);
|
||||
} // regular block
|
||||
} //testable
|
||||
//if found node, it is the closest
|
||||
if (nodefound)
|
||||
break;
|
||||
//check if we can step forward
|
||||
if (rx > 1 && ry > 1 && rz > 1)
|
||||
break;
|
||||
//step to next node
|
||||
oldx = x;
|
||||
oldy = y;
|
||||
oldz = z;
|
||||
if ((rx < ry) && (rx < rz)) {
|
||||
rx += rxs;
|
||||
x += xs;
|
||||
} else if (ry < rz) {
|
||||
ry += rys;
|
||||
y += ys;
|
||||
} else {
|
||||
rz += rzs;
|
||||
z += zs;
|
||||
}
|
||||
} while (true);
|
||||
}
|
||||
|
||||
/*
|
||||
ServerMap
|
||||
*/
|
||||
|
|
18
src/map.h
18
src/map.h
|
@ -293,6 +293,24 @@ public:
|
|||
*/
|
||||
core::map<v2s16, MapSector*> *getSectorsPtr(){return &m_sectors;}
|
||||
|
||||
|
||||
//!Finds the nearest node from a position in a given direction.
|
||||
/**
|
||||
*\param camera_direction: direction of ray
|
||||
*\param camera_position: starting point of ray
|
||||
*\param d: maximal distance of the search
|
||||
*\param ignore_liquids: if true, liquids are invisible
|
||||
*\param ignore_not_material_pointable: if true, nodes which are not
|
||||
* material_pointable will be invisible
|
||||
*\param nodefound: true if a node was found
|
||||
*\param nodepos: the integer coordinates of found node
|
||||
*\param neighbourpos: the node in front of the found node
|
||||
*/
|
||||
void raycast(v3f camera_direction,
|
||||
v3f camera_position, f32 d,
|
||||
bool ignore_liquids, bool ignore_not_material_pointable,
|
||||
bool &nodefound, v3s16 &nodepos, v3s16 &neighbourpos);
|
||||
|
||||
/*
|
||||
Variables
|
||||
*/
|
||||
|
|
Loading…
Reference in New Issue