aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--data/item_ladder.pngbin0 -> 581 bytes
-rw-r--r--data/ladder.pngbin0 -> 691 bytes
-rw-r--r--src/content_craft.cpp16
-rw-r--r--src/content_mapblock.cpp47
-rw-r--r--src/content_mapnode.cpp14
-rw-r--r--src/content_mapnode.h2
-rw-r--r--src/environment.cpp4
-rw-r--r--src/game.cpp50
-rw-r--r--src/mapnode.h3
-rw-r--r--src/player.cpp31
-rw-r--r--src/player.h1
11 files changed, 164 insertions, 4 deletions
diff --git a/data/item_ladder.png b/data/item_ladder.png
new file mode 100644
index 000000000..f35978ff9
--- /dev/null
+++ b/data/item_ladder.png
Binary files differ
diff --git a/data/ladder.png b/data/ladder.png
new file mode 100644
index 000000000..dbbd680ec
--- /dev/null
+++ b/data/ladder.png
Binary files differ
diff --git a/src/content_craft.cpp b/src/content_craft.cpp
index b5a1dc776..481ea1a63 100644
--- a/src/content_craft.cpp
+++ b/src/content_craft.cpp
@@ -413,6 +413,22 @@ InventoryItem *craft_get_result(InventoryItem **items)
}
}
+ // Ladder
+ {
+ ItemSpec specs[9];
+ specs[0] = ItemSpec(ITEM_CRAFT, "Stick");
+ specs[2] = ItemSpec(ITEM_CRAFT, "Stick");
+ specs[3] = ItemSpec(ITEM_CRAFT, "Stick");
+ specs[4] = ItemSpec(ITEM_CRAFT, "Stick");
+ specs[5] = ItemSpec(ITEM_CRAFT, "Stick");
+ specs[6] = ItemSpec(ITEM_CRAFT, "Stick");
+ specs[8] = ItemSpec(ITEM_CRAFT, "Stick");
+ if(checkItemCombination(items, specs))
+ {
+ return new MaterialItem(CONTENT_LADDER, 1);
+ }
+ }
+
return NULL;
}
diff --git a/src/content_mapblock.cpp b/src/content_mapblock.cpp
index 3044c8b35..ed2cd766a 100644
--- a/src/content_mapblock.cpp
+++ b/src/content_mapblock.cpp
@@ -1134,6 +1134,53 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
u16 indices[] = {0,1,2,2,3,0};
collector.append(material_rail, vertices, 4, indices, 6);
}
+ else if (n.getContent() == CONTENT_LADDER) {
+ u8 l = decode_light(n.getLightBlend(data->m_daynight_ratio));
+ video::SColor c(255,l,l,l);
+
+ float d = (float)BS/16;
+
+ // Assume wall is at X+
+ video::S3DVertex vertices[4] =
+ {
+ video::S3DVertex(BS/2-d,-BS/2,-BS/2, 0,0,0, c, 0,1),
+ video::S3DVertex(BS/2-d,-BS/2,BS/2, 0,0,0, c, 1,1),
+ video::S3DVertex(BS/2-d,BS/2,BS/2, 0,0,0, c, 1,0),
+ video::S3DVertex(BS/2-d,BS/2,-BS/2, 0,0,0, c, 0,0),
+ };
+
+ v3s16 dir = unpackDir(n.param2);
+
+ for(s32 i=0; i<4; i++)
+ {
+ if(dir == v3s16(1,0,0))
+ vertices[i].Pos.rotateXZBy(0);
+ if(dir == v3s16(-1,0,0))
+ vertices[i].Pos.rotateXZBy(180);
+ if(dir == v3s16(0,0,1))
+ vertices[i].Pos.rotateXZBy(90);
+ if(dir == v3s16(0,0,-1))
+ vertices[i].Pos.rotateXZBy(-90);
+ if(dir == v3s16(0,-1,0))
+ vertices[i].Pos.rotateXYBy(-90);
+ if(dir == v3s16(0,1,0))
+ vertices[i].Pos.rotateXYBy(90);
+
+ vertices[i].Pos += intToFloat(p + blockpos_nodes, BS);
+ }
+
+ video::SMaterial material_ladder;
+ material_ladder.setFlag(video::EMF_LIGHTING, false);
+ material_ladder.setFlag(video::EMF_BACK_FACE_CULLING, false);
+ material_ladder.setFlag(video::EMF_BILINEAR_FILTER, false);
+ material_ladder.setFlag(video::EMF_FOG_ENABLE, true);
+ material_ladder.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
+ material_ladder.setTexture(0, g_texturesource->getTextureRaw("ladder.png"));
+
+ u16 indices[] = {0,1,2,2,3,0};
+ // Add to mesh collector
+ collector.append(material_ladder, vertices, 4, indices, 6);
+ }
}
}
#endif
diff --git a/src/content_mapnode.cpp b/src/content_mapnode.cpp
index 7589f06ed..8e97fa6cd 100644
--- a/src/content_mapnode.cpp
+++ b/src/content_mapnode.cpp
@@ -303,6 +303,20 @@ void content_mapnode_init()
f->walkable = false;
setDirtLikeDiggingProperties(f->digging_properties, 0.75);
+ i = CONTENT_LADDER;
+ f = &content_features(i);
+ f->setInventoryTexture("item_ladder.png");
+ f->light_propagates = true;
+ f->param_type = CPT_LIGHT;
+ f->is_ground_content = true;
+ f->dug_item = std::string("MaterialItem ")+itos(i)+" 1";
+ f->wall_mounted = true;
+ f->solidness = 0;
+ f->air_equivalent = true;
+ f->walkable = false;
+ f->climbable = true;
+ setWoodLikeDiggingProperties(f->digging_properties, 0.5);
+
// Deprecated
i = CONTENT_COALSTONE;
f = &content_features(i);
diff --git a/src/content_mapnode.h b/src/content_mapnode.h
index 609df0a95..9643db746 100644
--- a/src/content_mapnode.h
+++ b/src/content_mapnode.h
@@ -46,6 +46,7 @@ MapNode mapnode_translate_to_internal(MapNode n_from, u8 version);
#define CONTENT_FURNACE 16
#define CONTENT_FENCE 21
#define CONTENT_RAIL 30
+#define CONTENT_LADDER 31
// 0x800...0xfff (2048...4095): higher 4 bytes of param2 are not usable
#define CONTENT_GRASS 0x800 //1
@@ -75,6 +76,5 @@ MapNode mapnode_translate_to_internal(MapNode n_from, u8 version);
#define CONTENT_NC 0x817
#define CONTENT_NC_RB 0x818
-
#endif
diff --git a/src/environment.cpp b/src/environment.cpp
index e9b94f3fa..680d209fc 100644
--- a/src/environment.cpp
+++ b/src/environment.cpp
@@ -1511,6 +1511,8 @@ void ClientEnvironment::step(float dtime)
/*
Get the speed the player is going
*/
+ bool is_climbing = lplayer->is_climbing;
+
f32 player_speed = 0.001; // just some small value
player_speed = lplayer->getSpeed().getLength();
@@ -1568,7 +1570,7 @@ void ClientEnvironment::step(float dtime)
v3f lplayerpos = lplayer->getPosition();
// Apply physics
- if(free_move == false)
+ if(free_move == false && is_climbing == false)
{
// Gravity
v3f speed = lplayer->getSpeed();
diff --git a/src/game.cpp b/src/game.cpp
index 6c0474ee7..fb5d7cb93 100644
--- a/src/game.cpp
+++ b/src/game.cpp
@@ -538,6 +538,56 @@ void getPointedNode(Client *client, v3f player_position,
}
}
}
+
+ else if(n.getContent() == CONTENT_LADDER)
+ {
+ 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;
+ f32 distance = (cpf - camera_position).getLength();
+
+ v3f vertices[4] =
+ {
+ v3f(BS*0.42,-BS/2,-BS/2),
+ v3f(BS*0.49, BS/2, BS/2),
+ };
+
+ for(s32 i=0; i<2; i++)
+ {
+ if(dir == v3s16(1,0,0))
+ vertices[i].rotateXZBy(0);
+ if(dir == v3s16(-1,0,0))
+ vertices[i].rotateXZBy(180);
+ if(dir == v3s16(0,0,1))
+ vertices[i].rotateXZBy(90);
+ if(dir == v3s16(0,0,-1))
+ vertices[i].rotateXZBy(-90);
+ if(dir == v3s16(0,-1,0))
+ vertices[i].rotateXYBy(-90);
+ if(dir == v3s16(0,1,0))
+ vertices[i].rotateXYBy(90);
+
+ vertices[i] += npf;
+ }
+
+ core::aabbox3d<f32> box;
+
+ box = core::aabbox3d<f32>(vertices[0]);
+ box.addInternalPoint(vertices[1]);
+
+ if(distance < mindistance)
+ {
+ if(box.intersectsWithLine(shootline))
+ {
+ nodefound = true;
+ nodepos = np;
+ neighbourpos = np;
+ mindistance = distance;
+ nodehilightbox = box;
+ }
+ }
+ }
else if(n.getContent() == CONTENT_RAIL)
{
v3s16 dir = unpackDir(n.param0);
diff --git a/src/mapnode.h b/src/mapnode.h
index 1fb84e1c9..484ad4e19 100644
--- a/src/mapnode.h
+++ b/src/mapnode.h
@@ -128,6 +128,8 @@ struct ContentFeatures
bool pointable;
// Player can dig these
bool diggable;
+ // Player can climb these
+ bool climbable;
// Player can build on these
bool buildable_to;
// Whether the node has no liquid, source liquid or flowing liquid
@@ -171,6 +173,7 @@ struct ContentFeatures
walkable = true;
pointable = true;
diggable = true;
+ climbable = false;
buildable_to = false;
liquid_type = LIQUID_NONE;
wall_mounted = false;
diff --git a/src/player.cpp b/src/player.cpp
index c43276ef1..be478e869 100644
--- a/src/player.cpp
+++ b/src/player.cpp
@@ -376,6 +376,21 @@ void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d,
}
/*
+ Check if player is climbing
+ */
+
+ try {
+ v3s16 pp = floatToInt(position + v3f(0,0.5*BS,0), BS);
+ v3s16 pp2 = floatToInt(position + v3f(0,-0.2*BS,0), BS);
+ is_climbing = ((content_features(map.getNode(pp).getContent()).climbable ||
+ content_features(map.getNode(pp2).getContent()).climbable) && !free_move);
+ }
+ catch(InvalidPositionException &e)
+ {
+ is_climbing = false;
+ }
+
+ /*
Collision uncertainty radius
Make it a bit larger than the maximum distance of movement
*/
@@ -461,7 +476,7 @@ void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d,
Player is allowed to jump when this is true.
*/
touching_ground = false;
-
+
/*std::cout<<"Checking collisions for ("
<<oldpos_i.X<<","<<oldpos_i.Y<<","<<oldpos_i.Z
<<") -> ("
@@ -723,7 +738,7 @@ void LocalPlayer::applyControl(float dtime)
bool fast_move = g_settings.getBool("fast_move");
bool continuous_forward = g_settings.getBool("continuous_forward");
- if(free_move)
+ if(free_move || is_climbing)
{
v3f speed = getSpeed();
speed.Y = 0;
@@ -750,6 +765,12 @@ void LocalPlayer::applyControl(float dtime)
speed.Y = -walkspeed_max;
setSpeed(speed);
}
+ else if(is_climbing)
+ {
+ v3f speed = getSpeed();
+ speed.Y = -3*BS;
+ setSpeed(speed);
+ }
else
{
// If not free movement but fast is allowed, aux1 is
@@ -812,6 +833,12 @@ void LocalPlayer::applyControl(float dtime)
setSpeed(speed);
swimming_up = true;
}
+ else if(is_climbing)
+ {
+ v3f speed = getSpeed();
+ speed.Y = 3*BS;
+ setSpeed(speed);
+ }
}
// The speed of the player (Y is ignored)
diff --git a/src/player.h b/src/player.h
index 29460e1e1..78ca14948 100644
--- a/src/player.h
+++ b/src/player.h
@@ -118,6 +118,7 @@ public:
bool in_water;
// This is more stable and defines the maximum speed of the player
bool in_water_stable;
+ bool is_climbing;
bool swimming_up;
Inventory inventory;